If you have specific tests to do with Contiki OS and TSCH maybe this post will interest you. Lately, I wanted to have a specific slotframe with TSCH to have a better understanding of TSCH. For this purpose, I needed some timeslots to have congestion-free communications between specific nodes.
For example, with tree nodes 1, 2 and 3. I wanted two slots to have unidirectional communications between node 2 and 1 and node 1 and 2.
This post explains how to hard code the following slotframe. The slotframe have a length of 5, we have 6 channels and we have 3 timeslots. The first one is shared and is used for advertising and broadcast in TSCH. If we use the “minimal schedule” of Contiki TSCH we will have only this one, then other communications like unicast will also be performed in this timeslot.

The slotframe length is defined with the macro TSCH_SCHEDULE_CONF_DEFAULT_LENGTH
in Contiki. The schedule is defined in the file core/net/mac/tsch/tsch-schedule.c
. To change the schedule with another static version we will surcharge the function void tsch_schedule_create_minimal(void)
This function create a 6TiSCH minimal schedule i.e. a slotframe with only a shared slot at timeslot number 0 and channel offset 0.
02 | void tsch_schedule_create_minimal( void ) |
04 | struct tsch_slotframe *sf_min; |
06 | tsch_schedule_remove_all_slotframes(); |
09 | sf_min = tsch_schedule_add_slotframe(0, TSCH_SCHEDULE_DEFAULT_LENGTH); |
14 | tsch_schedule_add_link(sf_min, |
15 | LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED | LINK_OPTION_TIME_KEEPING, |
16 | LINK_TYPE_ADVERTISING, &tsch_broadcast_address, |
An important fact: a slotframe is defined locally. If we take the node 3
it will have only the shared timeslot (0,0) and the timeslot 3 -> 2
(2,0). More in detail, the timeslot (0,0) will be used in reception and transmission and the timeslot (2,0) will be a transmission slot with the destination address 2. To personalize the slotframe we will use the MAC node address.
First we will initialize static node address variables in the schedule file. We will later replace each address by the current node address and replace the last byte with the correct Node ID value. Then we will branch based on the last byte of the node address to add specific timeslot.
02 | static linkaddr_t node_1_address = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; |
03 | static linkaddr_t node_2_address = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; |
04 | static linkaddr_t node_3_address = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; |
08 | tsch_schedule_create_example( void ) |
10 | struct tsch_slotframe *sf_custom; |
12 | tsch_schedule_remove_all_slotframes(); |
15 | sf_custom = tsch_schedule_add_slotframe(0, TSCH_SCHEDULE_DEFAULT_LENGTH); |
20 | tsch_schedule_add_link(sf_custom, |
21 | LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED | LINK_OPTION_TIME_KEEPING, |
22 | LINK_TYPE_ADVERTISING, &tsch_broadcast_address, |
25 | linkaddr_copy(&node_1_address, &linkaddr_node_addr); |
26 | node_1_address.u8[7] = 0x1; |
27 | linkaddr_copy(&node_2_address, &linkaddr_node_addr); |
28 | node_2_address.u8[7] = 0x2; |
29 | linkaddr_copy(&node_3_address, &linkaddr_node_addr); |
30 | node_3_address.u8[7] = 0x3; |
32 | if (linkaddr_node_addr.u8[7] == 0x01){ |
33 | tsch_schedule_add_link(sf_custom, LINK_OPTION_RX, LINK_TYPE_NORMAL, &node_2_address, 3, 1); |
35 | else if (linkaddr_node_addr.u8[7] == 0x02){ |
36 | tsch_schedule_add_link(sf_custom, LINK_OPTION_TX, LINK_TYPE_NORMAL, &node_1_address, 3, 1); |
37 | tsch_schedule_add_link(sf_custom, LINK_OPTION_RX, LINK_TYPE_NORMAL, &node_3_address, 2, 2); |
39 | else if (linkaddr_node_addr.u8[7] == 0x03){ |
40 | tsch_schedule_add_link(sf_custom, LINK_OPTION_TX, LINK_TYPE_NORMAL, &node_2_address, 2, 2); |
Finally, we have to set the node address of each node. It can be done with the argument NODEID
when upload the firmware (in case of the Zolertia Zoul platform).
Post Views: 89