44 #include "net/nbr-table.h"
47 #include "net/mac/tsch/tsch.h"
48 #include "net/mac/tsch/tsch-queue.h"
50 #include "net/mac/tsch/tsch-packet.h"
51 #include "net/mac/tsch/tsch-schedule.h"
52 #include "net/mac/tsch/tsch-log.h"
58 #if TSCH_LOG_LEVEL >= 1
59 #define DEBUG DEBUG_PRINT
61 #define DEBUG DEBUG_NONE
66 MEMB(link_memb,
struct tsch_link, TSCH_SCHEDULE_MAX_LINKS);
68 MEMB(slotframe_memb,
struct tsch_slotframe, TSCH_SCHEDULE_MAX_SLOTFRAMES);
73 struct tsch_slotframe *
74 tsch_schedule_add_slotframe(uint16_t handle, uint16_t size)
80 if(tsch_schedule_get_slotframe_by_handle(handle)) {
86 struct tsch_slotframe *sf =
memb_alloc(&slotframe_memb);
90 ASN_DIVISOR_INIT(sf->size, size);
95 PRINTF(
"TSCH-schedule: add_slotframe %u %u\n",
105 tsch_schedule_remove_all_slotframes(
void)
107 struct tsch_slotframe *sf;
108 while((sf =
list_head(slotframe_list))) {
109 if(tsch_schedule_remove_slotframe(sf) == 0) {
118 tsch_schedule_remove_slotframe(
struct tsch_slotframe *slotframe)
120 if(slotframe !=
NULL) {
123 while((l =
list_head(slotframe->links_list))) {
124 tsch_schedule_remove_link(slotframe, l);
128 if(tsch_get_lock()) {
129 PRINTF(
"TSCH-schedule: remove slotframe %u %u\n", slotframe->handle, slotframe->size.val);
140 struct tsch_slotframe *
141 tsch_schedule_get_slotframe_by_handle(uint16_t handle)
143 if(!tsch_is_locked()) {
144 struct tsch_slotframe *sf =
list_head(slotframe_list);
146 if(sf->handle == handle) {
157 tsch_schedule_get_link_by_handle(uint16_t handle)
159 if(!tsch_is_locked()) {
160 struct tsch_slotframe *sf =
list_head(slotframe_list);
162 struct tsch_link *l =
list_head(sf->links_list);
165 if(l->handle == handle) {
178 tsch_schedule_add_link(
struct tsch_slotframe *slotframe,
179 uint8_t link_options,
enum link_type link_type,
const linkaddr_t *address,
180 uint16_t timeslot, uint16_t channel_offset)
182 struct tsch_link *l =
NULL;
183 if(slotframe !=
NULL) {
187 tsch_schedule_remove_link_by_timeslot(slotframe, timeslot);
188 if(!tsch_get_lock()) {
189 PRINTF(
"TSCH-schedule:! add_link memb_alloc couldn't take lock\n");
193 PRINTF(
"TSCH-schedule:! add_link memb_alloc failed\n");
196 static int current_link_handle = 0;
197 struct tsch_neighbor *n;
201 l->handle = current_link_handle++;
202 l->link_options = link_options;
203 l->link_type = link_type;
204 l->slotframe_handle = slotframe->handle;
205 l->timeslot = timeslot;
206 l->channel_offset = channel_offset;
208 if(address ==
NULL) {
213 PRINTF(
"TSCH-schedule: add_link %u %u %u %u %u %u\n",
214 slotframe->handle, link_options, link_type, timeslot, channel_offset, TSCH_LOG_ID_FROM_LINKADDR(address));
219 if(l->link_options & LINK_OPTION_TX) {
220 n = tsch_queue_add_nbr(&l->addr);
224 if(!(l->link_options & LINK_OPTION_SHARED)) {
225 n->dedicated_tx_links_count++;
237 tsch_schedule_remove_link(
struct tsch_slotframe *slotframe,
struct tsch_link *l)
239 if(slotframe !=
NULL && l !=
NULL && l->slotframe_handle == slotframe->handle) {
240 if(tsch_get_lock()) {
241 uint8_t link_options;
246 link_options = l->link_options;
251 if(l == current_link) {
254 PRINTF(
"TSCH-schedule: remove_link %u %u %u %u %u\n",
255 slotframe->handle, l->link_options, l->timeslot, l->channel_offset,
256 TSCH_LOG_ID_FROM_LINKADDR(&l->addr));
265 if(link_options & LINK_OPTION_TX) {
266 struct tsch_neighbor *n = tsch_queue_add_nbr(&addr);
269 if(!(link_options & LINK_OPTION_SHARED)) {
270 n->dedicated_tx_links_count--;
277 PRINTF(
"TSCH-schedule:! remove_link memb_alloc couldn't take lock\n");
285 tsch_schedule_remove_link_by_timeslot(
struct tsch_slotframe *slotframe, uint16_t timeslot)
287 return slotframe !=
NULL &&
288 tsch_schedule_remove_link(slotframe, tsch_schedule_get_link_by_timeslot(slotframe, timeslot));
293 tsch_schedule_get_link_by_timeslot(
struct tsch_slotframe *slotframe, uint16_t timeslot)
295 if(!tsch_is_locked()) {
296 if(slotframe !=
NULL) {
297 struct tsch_link *l =
list_head(slotframe->links_list);
300 if(l->timeslot == timeslot) {
313 tsch_schedule_get_next_active_link(
struct asn_t *asn, uint16_t *time_offset,
314 struct tsch_link **backup_link)
316 uint16_t time_to_curr_best = 0;
317 struct tsch_link *curr_best =
NULL;
318 struct tsch_link *curr_backup =
NULL;
322 if(!tsch_is_locked()) {
323 struct tsch_slotframe *sf =
list_head(slotframe_list);
327 uint16_t timeslot = ASN_MOD(*asn, sf->size);
328 struct tsch_link *l =
list_head(sf->links_list);
330 uint16_t time_to_timeslot =
331 l->timeslot > timeslot ?
332 l->timeslot - timeslot :
333 sf->size.val + l->timeslot - timeslot;
334 if(curr_best ==
NULL || time_to_timeslot < time_to_curr_best) {
335 time_to_curr_best = time_to_timeslot;
338 }
else if(time_to_timeslot == time_to_curr_best) {
339 struct tsch_link *new_best =
NULL;
342 if((curr_best->link_options & LINK_OPTION_TX) == (l->link_options & LINK_OPTION_TX)) {
344 if(l->slotframe_handle < curr_best->slotframe_handle) {
349 if(l->link_options & LINK_OPTION_TX) {
355 if(curr_backup ==
NULL) {
357 if(new_best != l && (l->link_options & LINK_OPTION_RX)) {
361 if(new_best != curr_best && (curr_best->link_options & LINK_OPTION_RX)) {
362 curr_backup = curr_best;
367 if(new_best !=
NULL) {
368 curr_best = new_best;
376 if(time_offset !=
NULL) {
377 *time_offset = time_to_curr_best;
380 if(backup_link !=
NULL) {
381 *backup_link = curr_backup;
388 tsch_schedule_init(
void)
390 if(tsch_get_lock()) {
403 tsch_schedule_create_minimal(
void)
405 struct tsch_slotframe *sf_min;
407 tsch_schedule_remove_all_slotframes();
410 sf_min = tsch_schedule_add_slotframe(0, TSCH_SCHEDULE_DEFAULT_LENGTH);
415 tsch_schedule_add_link(sf_min,
416 LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED | LINK_OPTION_TIME_KEEPING,
417 LINK_TYPE_ADVERTISING, &tsch_broadcast_address,
423 tsch_schedule_print(
void)
425 if(!tsch_is_locked()) {
426 struct tsch_slotframe *sf =
list_head(slotframe_list);
428 printf(
"Schedule: slotframe list\n");
431 struct tsch_link *l =
list_head(sf->links_list);
433 printf(
"[Slotframe] Handle %u, size %u\n", sf->handle, sf->size.val);
434 printf(
"List of links:\n");
437 printf(
"[Link] Options %02x, type %u, timeslot %u, channel offset %u, address %u\n",
438 l->link_options, l->link_type, l->timeslot, l->channel_offset, l->addr.u8[7]);
445 printf(
"Schedule: end of slotframe list\n");
Header file for the real-time timer module.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
#define LIST(name)
Declare a linked list.
static uip_ds6_addr_t * addr
Pointer to a router list entry.
#define MEMB(name, structure, num)
Declare a memory block.
void * list_item_next(void *item)
Get the next item following this item.
Private TSCH definitions (meant for use by TSCH implementation files only) ...
const linkaddr_t linkaddr_null
The null Rime address.
Header file for the Rime buffer (packetbuf) management
void list_init(list_t list)
Initialize a list.
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
void * list_head(list_t list)
Get a pointer to the first element of a list.
A set of debugging macros for the netstack
#define NULL
The null pointer.
802.15.4 frame creation and parsing functions
void list_add(list_t list, void *item)
Add an item at the end of a list.
Header file for the Contiki process interface.
Memory block allocation routines.
Header file for the Rime queue buffer management
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a Rime address.
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().