48 #include "net/mac/tsch/tsch.h"
49 #include "net/mac/tsch/tsch-slot-operation.h"
50 #include "net/mac/tsch/tsch-queue.h"
52 #include "net/mac/tsch/tsch-log.h"
53 #include "net/mac/tsch/tsch-packet.h"
54 #include "net/mac/tsch/tsch-security.h"
55 #include "net/mac/tsch/tsch-adaptive-timesync.h"
57 #if TSCH_LOG_LEVEL >= 1
58 #define DEBUG DEBUG_PRINT
60 #define DEBUG DEBUG_NONE
66 #ifndef TSCH_DEBUG_INIT
67 #define TSCH_DEBUG_INIT()
69 #ifndef TSCH_DEBUG_INTERRUPT
70 #define TSCH_DEBUG_INTERRUPT()
72 #ifndef TSCH_DEBUG_RX_EVENT
73 #define TSCH_DEBUG_RX_EVENT()
75 #ifndef TSCH_DEBUG_TX_EVENT
76 #define TSCH_DEBUG_TX_EVENT()
78 #ifndef TSCH_DEBUG_SLOT_START
79 #define TSCH_DEBUG_SLOT_START()
81 #ifndef TSCH_DEBUG_SLOT_END
82 #define TSCH_DEBUG_SLOT_END()
86 #if (TSCH_MAX_INCOMING_PACKETS & (TSCH_MAX_INCOMING_PACKETS - 1)) != 0
87 #error TSCH_MAX_INCOMING_PACKETS must be power of two
91 #if TSCH_DEQUEUED_ARRAY_SIZE < QUEUEBUF_NUM
92 #error TSCH_DEQUEUED_ARRAY_SIZE must be greater or equal to QUEUEBUF_NUM
94 #if (TSCH_DEQUEUED_ARRAY_SIZE & (TSCH_DEQUEUED_ARRAY_SIZE - 1)) != 0
95 #error TSCH_DEQUEUED_ARRAY_SIZE must be power of two
100 #define SYNC_IE_BOUND ((int32_t)US_TO_RTIMERTICKS(TSCH_DEFAULT_TS_RX_WAIT / 4))
103 #if RTIMER_SECOND < (32 * 1024)
104 #error "TSCH: RTIMER_SECOND < (32 * 1024)"
106 #if RTIMER_SECOND >= 200000
107 #define RTIMER_GUARD (RTIMER_SECOND / 100000)
109 #define RTIMER_GUARD 2u
114 struct ringbufindex dequeued_ringbuf;
115 struct tsch_packet *dequeued_array[TSCH_DEQUEUED_ARRAY_SIZE];
118 struct ringbufindex input_ringbuf;
119 struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
122 static struct asn_t last_sync_asn;
125 static volatile int tsch_locked = 0;
127 static volatile int tsch_lock_requested = 0;
131 static int32_t drift_correction = 0;
133 static uint8_t is_drift_correction_used;
136 struct tsch_neighbor *last_timesource_neighbor =
NULL;
139 static rtimer_clock_t
volatile current_slot_start;
142 static volatile int tsch_in_slot_operation = 0;
146 struct tsch_link *current_link =
NULL;
150 static struct tsch_link *backup_link =
NULL;
151 static struct tsch_packet *current_packet =
NULL;
152 static struct tsch_neighbor *current_neighbor =
NULL;
159 static struct pt slot_operation_pt;
179 rtimer_clock_t busy_wait_time;
182 tsch_lock_requested = 1;
184 if(tsch_in_slot_operation) {
187 while(tsch_in_slot_operation);
188 busy_wait_time =
RTIMER_NOW() - busy_wait_time;
193 tsch_lock_requested = 0;
196 TSCH_LOG_ADD(tsch_log_message,
197 snprintf(log->message,
sizeof(log->message),
198 "!get lock delay %u", (
unsigned)busy_wait_time);
204 TSCH_LOG_ADD(tsch_log_message,
205 snprintf(log->message,
sizeof(log->message),
213 tsch_release_lock(
void)
223 tsch_calculate_channel(
struct asn_t *asn, uint8_t channel_offset)
225 uint16_t index_of_0 = ASN_MOD(*asn, tsch_hopping_sequence_length);
226 uint16_t index_of_offset = (index_of_0 + channel_offset) % tsch_hopping_sequence_length.val;
227 return tsch_hopping_sequence[index_of_offset];
236 check_timer_miss(rtimer_clock_t ref_time, rtimer_clock_t offset, rtimer_clock_t now)
238 rtimer_clock_t target = ref_time + offset;
239 int now_has_overflowed = now < ref_time;
240 int target_has_overflowed = target < ref_time;
242 if(now_has_overflowed == target_has_overflowed) {
244 return target <= now;
250 return now_has_overflowed;
258 tsch_schedule_slot_operation(
struct rtimer *
tm, rtimer_clock_t ref_time, rtimer_clock_t offset,
const char *str)
264 int missed = check_timer_miss(ref_time, offset - RTIMER_GUARD, now);
267 TSCH_LOG_ADD(tsch_log_message,
268 snprintf(log->message,
sizeof(log->message),
270 str, (
int)(now-ref_time), (
int)offset);
286 #define TSCH_SCHEDULE_AND_YIELD(pt, tm, ref_time, offset, str) \
288 if(tsch_schedule_slot_operation(tm, ref_time, offset - RTIMER_GUARD, str)) { \
291 BUSYWAIT_UNTIL_ABS(0, ref_time, offset); \
295 static struct tsch_packet *
296 get_packet_and_neighbor_for_link(
struct tsch_link *link,
struct tsch_neighbor **target_neighbor)
298 struct tsch_packet *p =
NULL;
299 struct tsch_neighbor *n =
NULL;
302 if(link->link_options & LINK_OPTION_TX) {
304 if(link->link_type == LINK_TYPE_ADVERTISING || link->link_type == LINK_TYPE_ADVERTISING_ONLY) {
307 p = tsch_queue_get_packet_for_nbr(n, link);
309 if(link->link_type != LINK_TYPE_ADVERTISING_ONLY) {
313 n = tsch_queue_get_nbr(&link->addr);
314 p = tsch_queue_get_packet_for_nbr(n, link);
316 if(p ==
NULL && n == n_broadcast) {
317 p = tsch_queue_get_unicast_packet_for_any(&n, link);
323 if(target_neighbor !=
NULL) {
324 *target_neighbor = n;
332 update_neighbor_state(
struct tsch_neighbor *n,
struct tsch_packet *p,
333 struct tsch_link *link, uint8_t mac_tx_status)
336 int is_shared_link = link->link_options & LINK_OPTION_SHARED;
337 int is_unicast = !n->is_broadcast;
341 tsch_queue_remove_packet_from_queue(n);
346 if(is_shared_link || tsch_queue_is_empty(n)) {
349 tsch_queue_backoff_reset(n);
354 if(p->transmissions >= TSCH_MAC_MAX_FRAME_RETRIES + 1) {
356 tsch_queue_remove_packet_from_queue(n);
365 tsch_queue_backoff_inc(n);
388 static uint8_t mac_tx_status;
391 static int dequeued_index;
392 static int packet_ready = 1;
396 TSCH_DEBUG_TX_EVENT();
400 dequeued_index = ringbufindex_peek_put(&dequeued_ringbuf);
401 if(dequeued_index != -1) {
402 if(current_packet ==
NULL || current_packet->qb ==
NULL) {
403 mac_tx_status = MAC_TX_ERR_FATAL;
407 #if LLSEC802154_ENABLED
409 static uint8_t encrypted_packet[TSCH_PACKET_MAX_LEN];
412 static uint8_t packet_len;
414 static uint8_t seqno;
416 static uint8_t is_broadcast;
417 static rtimer_clock_t tx_start_time;
420 static uint8_t cca_status;
424 packet = queuebuf_dataptr(current_packet->qb);
425 packet_len = queuebuf_datalen(current_packet->qb);
427 is_broadcast = current_neighbor->is_broadcast;
429 seqno = ((uint8_t *)(packet))[2];
431 if(current_neighbor == n_eb) {
432 packet_ready = tsch_packet_update_eb(packet, packet_len, current_packet->tsch_sync_ie_offset);
437 #if LLSEC802154_ENABLED
438 if(tsch_is_pan_secured) {
441 int with_encryption = queuebuf_attr(current_packet->qb, PACKETBUF_ATTR_SECURITY_LEVEL) & 0x4;
442 packet_len += tsch_security_secure_frame(packet, with_encryption ? encrypted_packet : packet, current_packet->header_len,
443 packet_len - current_packet->header_len, ¤t_asn);
444 if(with_encryption) {
445 packet = encrypted_packet;
451 if(packet_ready && NETSTACK_RADIO.prepare(packet, packet_len) == 0) {
452 static rtimer_clock_t tx_duration;
457 TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, TS_CCA_OFFSET,
"cca");
458 TSCH_DEBUG_TX_EVENT();
461 BUSYWAIT_UNTIL_ABS(!(cca_status |= NETSTACK_RADIO.channel_clear()),
462 current_slot_start, TS_CCA_OFFSET + TS_CCA);
463 TSCH_DEBUG_TX_EVENT();
466 if(cca_status == 0) {
472 TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, tsch_timing[tsch_ts_tx_offset] - RADIO_DELAY_BEFORE_TX,
"TxBeforeTx");
473 TSCH_DEBUG_TX_EVENT();
475 mac_tx_status = NETSTACK_RADIO.transmit(packet_len);
477 tx_start_time = current_slot_start + tsch_timing[tsch_ts_tx_offset];
479 tx_duration = TSCH_PACKET_DURATION(packet_len);
481 tx_duration = MIN(tx_duration, tsch_timing[tsch_ts_max_tx]);
483 NETSTACK_RADIO.off();
485 if(mac_tx_status == RADIO_TX_OK) {
487 uint8_t ackbuf[TSCH_PACKET_MAX_LEN];
489 rtimer_clock_t ack_start_time;
492 struct ieee802154_ies ack_ies;
496 #if TSCH_HW_FRAME_FILTERING
498 NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
502 TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start,
503 tsch_timing[tsch_ts_tx_offset] + tx_duration + tsch_timing[tsch_ts_rx_ack_delay] - RADIO_DELAY_BEFORE_RX,
"TxBeforeAck");
504 TSCH_DEBUG_TX_EVENT();
507 BUSYWAIT_UNTIL_ABS(NETSTACK_RADIO.receiving_packet(),
508 tx_start_time, tx_duration + tsch_timing[tsch_ts_rx_ack_delay] + tsch_timing[tsch_ts_ack_wait]);
509 TSCH_DEBUG_TX_EVENT();
511 ack_start_time =
RTIMER_NOW() - RADIO_DELAY_BEFORE_DETECT;
514 BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
515 ack_start_time, tsch_timing[tsch_ts_max_ack]);
516 TSCH_DEBUG_TX_EVENT();
517 NETSTACK_RADIO.off();
519 #if TSCH_HW_FRAME_FILTERING
521 NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
526 ack_len = NETSTACK_RADIO.read((
void *)ackbuf,
sizeof(ackbuf));
531 is_time_source = current_neighbor !=
NULL && current_neighbor->is_time_source;
532 if(tsch_packet_parse_eack(ackbuf, ack_len, seqno,
533 &frame, &ack_ies, &ack_hdrlen) == 0) {
537 #if LLSEC802154_ENABLED
539 if(!tsch_security_parse_frame(ackbuf, ack_hdrlen, ack_len - ack_hdrlen - tsch_security_mic_len(&frame),
540 &frame, ¤t_neighbor->addr, ¤t_asn)) {
541 TSCH_LOG_ADD(tsch_log_message,
542 snprintf(log->message,
sizeof(log->message),
543 "!failed to authenticate ACK"));
547 TSCH_LOG_ADD(tsch_log_message,
548 snprintf(log->message,
sizeof(log->message),
549 "!failed to parse ACK"));
556 int32_t eack_time_correction = US_TO_RTIMERTICKS(ack_ies.ie_time_correction);
557 int32_t since_last_timesync = ASN_DIFF(current_asn, last_sync_asn);
558 if(eack_time_correction > SYNC_IE_BOUND) {
559 drift_correction = SYNC_IE_BOUND;
560 }
else if(eack_time_correction < -SYNC_IE_BOUND) {
561 drift_correction = -SYNC_IE_BOUND;
563 drift_correction = eack_time_correction;
565 if(drift_correction != eack_time_correction) {
566 TSCH_LOG_ADD(tsch_log_message,
567 snprintf(log->message,
sizeof(log->message),
568 "!truncated dr %d %d", (
int)eack_time_correction, (
int)drift_correction);
571 is_drift_correction_used = 1;
572 tsch_timesync_update(current_neighbor, since_last_timesync, drift_correction);
574 last_sync_asn = current_asn;
575 tsch_schedule_keepalive();
591 current_packet->transmissions++;
592 current_packet->ret = mac_tx_status;
595 in_queue = update_neighbor_state(current_neighbor, current_packet, current_link, mac_tx_status);
599 dequeued_array[dequeued_index] = current_packet;
600 ringbufindex_put(&dequeued_ringbuf);
604 TSCH_LOG_ADD(tsch_log_tx,
605 log->tx.mac_tx_status = mac_tx_status;
606 log->tx.num_tx = current_packet->transmissions;
607 log->tx.datalen = queuebuf_datalen(current_packet->qb);
608 log->tx.drift = drift_correction;
609 log->tx.drift_used = is_drift_correction_used;
610 log->tx.is_data = ((((uint8_t *)(queuebuf_dataptr(current_packet->qb)))[0]) & 7) == FRAME802154_DATAFRAME;
611 #
if LLSEC802154_ENABLED
612 log->tx.sec_level = queuebuf_attr(current_packet->qb, PACKETBUF_ATTR_SECURITY_LEVEL);
614 log->tx.sec_level = 0;
616 log->tx.dest = TSCH_LOG_ID_FROM_LINKADDR(queuebuf_addr(current_packet->qb, PACKETBUF_ADDR_RECEIVER));
623 TSCH_DEBUG_TX_EVENT();
640 struct tsch_neighbor *n;
641 static linkaddr_t source_address;
642 static linkaddr_t destination_address;
643 static int16_t input_index;
644 static int input_queue_drop = 0;
648 TSCH_DEBUG_RX_EVENT();
650 input_index = ringbufindex_peek_put(&input_ringbuf);
651 if(input_index == -1) {
654 static struct input_packet *current_input;
656 static int32_t estimated_drift;
658 static rtimer_clock_t rx_start_time;
659 static rtimer_clock_t expected_rx_time;
660 static rtimer_clock_t packet_duration;
663 expected_rx_time = current_slot_start + tsch_timing[tsch_ts_tx_offset];
665 rx_start_time = expected_rx_time;
667 current_input = &input_array[input_index];
670 TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, tsch_timing[tsch_ts_rx_offset] - RADIO_DELAY_BEFORE_RX,
"RxBeforeListen");
671 TSCH_DEBUG_RX_EVENT();
675 packet_seen = NETSTACK_RADIO.receiving_packet();
678 BUSYWAIT_UNTIL_ABS((packet_seen = NETSTACK_RADIO.receiving_packet()),
679 current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait]);
682 TSCH_DEBUG_RX_EVENT();
684 rx_start_time =
RTIMER_NOW() - RADIO_DELAY_BEFORE_DETECT;
686 if(!NETSTACK_RADIO.receiving_packet() && !NETSTACK_RADIO.pending_packet()) {
687 NETSTACK_RADIO.off();
691 BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
692 current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait] + tsch_timing[tsch_ts_max_tx]);
693 TSCH_DEBUG_RX_EVENT();
694 NETSTACK_RADIO.off();
696 #if TSCH_RESYNC_WITH_SFD_TIMESTAMPS
698 NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &rx_start_time,
sizeof(rtimer_clock_t));
701 if(NETSTACK_RADIO.pending_packet()) {
702 static int frame_valid;
703 static int header_len;
707 NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi);
709 current_input->len = NETSTACK_RADIO.read((
void *)current_input->payload, TSCH_PACKET_MAX_LEN);
710 current_input->rx_asn = current_asn;
711 current_input->rssi = (signed)radio_last_rssi;
712 header_len =
frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame);
713 frame_valid = header_len > 0 &&
714 frame802154_check_dest_panid(&frame) &&
715 frame802154_extract_linkaddr(&frame, &source_address, &destination_address);
717 packet_duration = TSCH_PACKET_DURATION(current_input->len);
719 #if LLSEC802154_ENABLED
722 if(tsch_security_parse_frame(
723 current_input->payload, header_len, current_input->len - header_len - tsch_security_mic_len(&frame),
724 &frame, &source_address, ¤t_asn)) {
725 current_input->len -= tsch_security_mic_len(&frame);
727 TSCH_LOG_ADD(tsch_log_message,
728 snprintf(log->message,
sizeof(log->message),
729 "!failed to authenticate frame %u", current_input->len));
733 TSCH_LOG_ADD(tsch_log_message,
734 snprintf(log->message,
sizeof(log->message),
735 "!failed to parse frame %u %u", header_len, current_input->len));
744 estimated_drift = RTIMER_CLOCK_DIFF(expected_rx_time, rx_start_time);
746 #if TSCH_TIMESYNC_REMOVE_JITTER
748 if(
abs(estimated_drift) <= TSCH_TIMESYNC_MEASUREMENT_ERROR) {
750 }
else if(estimated_drift > 0) {
751 estimated_drift -= TSCH_TIMESYNC_MEASUREMENT_ERROR;
753 estimated_drift += TSCH_TIMESYNC_MEASUREMENT_ERROR;
757 #ifdef TSCH_CALLBACK_DO_NACK
759 do_nack = TSCH_CALLBACK_DO_NACK(current_link,
760 &source_address, &destination_address);
765 static uint8_t ack_buf[TSCH_PACKET_MAX_LEN];
769 ack_len = tsch_packet_create_eack(ack_buf,
sizeof(ack_buf),
770 &source_address, frame.
seq, (int16_t)RTIMERTICKS_TO_US(estimated_drift), do_nack);
772 #if LLSEC802154_ENABLED
773 if(tsch_is_pan_secured) {
775 ack_len += tsch_security_secure_frame(ack_buf, ack_buf, ack_len, 0, ¤t_asn);
780 NETSTACK_RADIO.prepare((
const void *)ack_buf, ack_len);
783 TSCH_SCHEDULE_AND_YIELD(pt, t, rx_start_time,
784 packet_duration + tsch_timing[tsch_ts_tx_ack_delay] - RADIO_DELAY_BEFORE_TX,
"RxBeforeAck");
785 TSCH_DEBUG_RX_EVENT();
786 NETSTACK_RADIO.transmit(ack_len);
787 NETSTACK_RADIO.off();
791 n = tsch_queue_get_nbr(&source_address);
792 if(n !=
NULL && n->is_time_source) {
793 int32_t since_last_timesync = ASN_DIFF(current_asn, last_sync_asn);
795 last_sync_asn = current_asn;
797 drift_correction = -estimated_drift;
798 is_drift_correction_used = 1;
799 tsch_timesync_update(n, since_last_timesync, -estimated_drift);
800 tsch_schedule_keepalive();
804 ringbufindex_put(&input_ringbuf);
807 TSCH_LOG_ADD(tsch_log_rx,
808 log->rx.src = TSCH_LOG_ID_FROM_LINKADDR((linkaddr_t*)&frame.
src_addr);
810 log->rx.datalen = current_input->len;
811 log->rx.drift = drift_correction;
812 log->rx.drift_used = is_drift_correction_used;
813 log->rx.is_data = frame.
fcf.
frame_type == FRAME802154_DATAFRAME;
815 log->rx.estimated_drift = estimated_drift;
825 if(input_queue_drop != 0) {
826 TSCH_LOG_ADD(tsch_log_message,
827 snprintf(log->message,
sizeof(log->message),
828 "!queue full skipped %u", input_queue_drop);
830 input_queue_drop = 0;
834 TSCH_DEBUG_RX_EVENT();
844 TSCH_DEBUG_INTERRUPT();
848 while(tsch_is_associated) {
850 if(current_link ==
NULL || tsch_lock_requested) {
853 TSCH_LOG_ADD(tsch_log_message,
854 snprintf(log->message,
sizeof(log->message),
855 "!skipped slot %u %u %u",
858 current_link ==
NULL);
862 uint8_t current_channel;
863 TSCH_DEBUG_SLOT_START();
864 tsch_in_slot_operation = 1;
866 current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor);
869 if(current_packet ==
NULL && !(current_link->link_options & LINK_OPTION_RX) && backup_link !=
NULL) {
870 current_link = backup_link;
871 current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor);
874 current_channel = tsch_calculate_channel(¤t_asn, current_link->channel_offset);
875 NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel);
877 drift_correction = 0;
878 is_drift_correction_used = 0;
881 if(current_packet !=
NULL) {
887 static struct pt slot_tx_pt;
888 PT_SPAWN(&slot_operation_pt, &slot_tx_pt, tsch_tx_slot(&slot_tx_pt, t));
889 }
else if((current_link->link_options & LINK_OPTION_RX)) {
891 static struct pt slot_rx_pt;
892 PT_SPAWN(&slot_operation_pt, &slot_rx_pt, tsch_rx_slot(&slot_rx_pt, t));
894 TSCH_DEBUG_SLOT_END();
900 if(!tsch_is_coordinator && (ASN_DIFF(current_asn, last_sync_asn) >
901 (100 * TSCH_CLOCK_TO_SLOTS(TSCH_DESYNC_THRESHOLD / 100, tsch_timing[tsch_ts_timeslot_length])))) {
902 TSCH_LOG_ADD(tsch_log_message,
903 snprintf(log->message,
sizeof(log->message),
904 "! leaving the network, last sync %u",
905 (
unsigned)ASN_DIFF(current_asn, last_sync_asn));
907 last_timesource_neighbor =
NULL;
912 uint16_t timeslot_diff = 0;
913 rtimer_clock_t prev_slot_start;
915 rtimer_clock_t time_to_next_active_slot;
918 if(current_link !=
NULL
919 && current_link->link_options & LINK_OPTION_TX
920 && current_link->link_options & LINK_OPTION_SHARED) {
923 tsch_queue_update_all_backoff_windows(¤t_link->addr);
927 current_link = tsch_schedule_get_next_active_link(¤t_asn, ×lot_diff, &backup_link);
928 if(current_link ==
NULL) {
934 ASN_INC(current_asn, timeslot_diff);
936 time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length] + drift_correction;
937 drift_correction = 0;
938 is_drift_correction_used = 0;
940 prev_slot_start = current_slot_start;
941 current_slot_start += time_to_next_active_slot;
942 current_slot_start += tsch_timesync_adaptive_compensate(time_to_next_active_slot);
943 }
while(!tsch_schedule_slot_operation(t, prev_slot_start, time_to_next_active_slot,
"main"));
946 tsch_in_slot_operation = 0;
950 PT_END(&slot_operation_pt);
956 tsch_slot_operation_start(
void)
958 static struct rtimer slot_operation_timer;
959 rtimer_clock_t time_to_next_active_slot;
960 rtimer_clock_t prev_slot_start;
963 uint16_t timeslot_diff;
965 current_link = tsch_schedule_get_next_active_link(¤t_asn, ×lot_diff, &backup_link);
966 if(current_link ==
NULL) {
972 ASN_INC(current_asn, timeslot_diff);
974 time_to_next_active_slot = timeslot_diff * tsch_timing[tsch_ts_timeslot_length];
976 prev_slot_start = current_slot_start;
977 current_slot_start += time_to_next_active_slot;
978 }
while(!tsch_schedule_slot_operation(&slot_operation_timer, prev_slot_start, time_to_next_active_slot,
"association"));
983 tsch_slot_operation_sync(rtimer_clock_t next_slot_start,
984 struct asn_t *next_slot_asn)
986 current_slot_start = next_slot_start;
987 current_asn = *next_slot_asn;
988 last_sync_asn = current_asn;
#define PT_SPAWN(pt, child, thread)
Spawn a child protothread and wait until it exits.
void process_poll(struct process *p)
Request a process to be polled.
frame802154_scf_t security_control
Security control bitfield.
The MAC layer deferred the transmission for a later time.
The MAC layer did not get an acknowledgement for the packet.
Header file for the radio API
frame802154_fcf_t fcf
Frame control field.
#define RTIMER_NOW()
Get the current clock time.
uint8_t src_addr[8]
Source address.
#define PT_YIELD(pt)
Yield from the current protothread.
uint8_t seq
Sequence number.
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
The MAC layer transmission could not be performed because of a fatal error.
A set of debugging macros for the netstack
The MAC layer transmission was OK.
#define NULL
The null pointer.
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
#define PT_THREAD(name_args)
Declaration of a protothread.
int rtimer_set(struct rtimer *rtimer, rtimer_clock_t time, rtimer_clock_t duration, rtimer_callback_t func, void *ptr)
Post a real-time task.
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
int frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
Parses an input frame.
uint8_t security_level
3 bit.
frame802154_aux_hdr_t aux_hdr
Aux security header.
uint8_t ack_required
1 bit.
#define PT_END(pt)
Declare the end of a protothread.
Header file for the Rime queue buffer management
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two Rime addresses.
linkaddr_t linkaddr_node_addr
The Rime address of the node.
Representation of a real-time task.
Parameters used by the frame802154_create() function.
Include file for the Contiki low-layer network stack (NETSTACK)
int abs(int I)
Returns the absolute value of I (also called the magnitude of I).
A MAC framer for IEEE 802.15.4