Merge pull request #380 from simonduq/contrib/tsch-burst-mode
TSCH burst mode
This commit is contained in:
commit
73103de195
|
@ -317,6 +317,15 @@
|
||||||
#define TSCH_SCHEDULE_WITH_6TISCH_MINIMAL (!(BUILD_WITH_ORCHESTRA))
|
#define TSCH_SCHEDULE_WITH_6TISCH_MINIMAL (!(BUILD_WITH_ORCHESTRA))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Set an upper bound on burst length. Set to 0 to never set the frame pending
|
||||||
|
* bit, i.e., never trigger a burst. Note that receiver-side support for burst
|
||||||
|
* is always enabled, as it is part of IEEE 802.1.5.4-2015 (Section 7.2.1.3)*/
|
||||||
|
#ifdef TSCH_CONF_BURST_MAX_LEN
|
||||||
|
#define TSCH_BURST_MAX_LEN TSCH_CONF_BURST_MAX_LEN
|
||||||
|
#else
|
||||||
|
#define TSCH_BURST_MAX_LEN 32
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 6TiSCH Minimal schedule slotframe length */
|
/* 6TiSCH Minimal schedule slotframe length */
|
||||||
#ifdef TSCH_SCHEDULE_CONF_DEFAULT_LENGTH
|
#ifdef TSCH_SCHEDULE_CONF_DEFAULT_LENGTH
|
||||||
#define TSCH_SCHEDULE_DEFAULT_LENGTH TSCH_SCHEDULE_CONF_DEFAULT_LENGTH
|
#define TSCH_SCHEDULE_DEFAULT_LENGTH TSCH_SCHEDULE_CONF_DEFAULT_LENGTH
|
||||||
|
|
|
@ -82,10 +82,11 @@ tsch_log_process_pending(void)
|
||||||
printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link-NULL} ", log->asn.ms1b, log->asn.ls4b);
|
printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link-NULL} ", log->asn.ms1b, log->asn.ls4b);
|
||||||
} else {
|
} else {
|
||||||
struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(log->link->slotframe_handle);
|
struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(log->link->slotframe_handle);
|
||||||
printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link %2u %3u %3u %2u ch %2u} ",
|
printf("[INFO: TSCH-LOG ] {asn %02x.%08lx link %2u %3u %3u %2u %2u ch %2u} ",
|
||||||
log->asn.ms1b, log->asn.ls4b,
|
log->asn.ms1b, log->asn.ls4b,
|
||||||
log->link->slotframe_handle, sf ? sf->size.val : 0, log->link->timeslot, log->link->channel_offset,
|
log->link->slotframe_handle, sf ? sf->size.val : 0,
|
||||||
tsch_calculate_channel(&log->asn, log->link->channel_offset));
|
log->burst_count, log->link->timeslot + log->burst_count, log->link->channel_offset,
|
||||||
|
log->channel);
|
||||||
}
|
}
|
||||||
switch(log->type) {
|
switch(log->type) {
|
||||||
case tsch_log_tx:
|
case tsch_log_tx:
|
||||||
|
@ -135,6 +136,8 @@ tsch_log_prepare_add(void)
|
||||||
struct tsch_log_t *log = &log_array[log_index];
|
struct tsch_log_t *log = &log_array[log_index];
|
||||||
log->asn = tsch_current_asn;
|
log->asn = tsch_current_asn;
|
||||||
log->link = current_link;
|
log->link = current_link;
|
||||||
|
log->burst_count = tsch_current_burst_count;
|
||||||
|
log->channel = tsch_current_channel;
|
||||||
return log;
|
return log;
|
||||||
} else {
|
} else {
|
||||||
log_dropped++;
|
log_dropped++;
|
||||||
|
|
|
@ -80,6 +80,8 @@ struct tsch_log_t {
|
||||||
} type;
|
} type;
|
||||||
struct tsch_asn_t asn;
|
struct tsch_asn_t asn;
|
||||||
struct tsch_link *link;
|
struct tsch_link *link;
|
||||||
|
uint8_t burst_count;
|
||||||
|
uint8_t channel;
|
||||||
union {
|
union {
|
||||||
char message[48];
|
char message[48];
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -70,6 +70,9 @@
|
||||||
*/
|
*/
|
||||||
static struct packetbuf_attr eackbuf_attrs[PACKETBUF_NUM_ATTRS];
|
static struct packetbuf_attr eackbuf_attrs[PACKETBUF_NUM_ATTRS];
|
||||||
|
|
||||||
|
/* The offset of the frame pending bit flag within the first byte of FCF */
|
||||||
|
#define IEEE802154_FRAME_PENDING_BIT_OFFSET 4
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
tsch_packet_eackbuf_set_attr(uint8_t type, const packetbuf_attr_t val)
|
tsch_packet_eackbuf_set_attr(uint8_t type, const packetbuf_attr_t val)
|
||||||
|
@ -459,4 +462,18 @@ tsch_packet_parse_eb(const uint8_t *buf, int buf_size,
|
||||||
return curr_len;
|
return curr_len;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Set frame pending bit in a packet (whose header was already build) */
|
||||||
|
void
|
||||||
|
tsch_packet_set_frame_pending(uint8_t *buf, int buf_size)
|
||||||
|
{
|
||||||
|
buf[0] |= (1 << IEEE802154_FRAME_PENDING_BIT_OFFSET);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Get frame pending bit from a packet */
|
||||||
|
int
|
||||||
|
tsch_packet_get_frame_pending(uint8_t *buf, int buf_size)
|
||||||
|
{
|
||||||
|
return (buf[0] >> IEEE802154_FRAME_PENDING_BIT_OFFSET) & 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -101,6 +101,19 @@ int tsch_packet_update_eb(uint8_t *buf, int buf_size, uint8_t tsch_sync_ie_offse
|
||||||
int tsch_packet_parse_eb(const uint8_t *buf, int buf_size,
|
int tsch_packet_parse_eb(const uint8_t *buf, int buf_size,
|
||||||
frame802154_t *frame, struct ieee802154_ies *ies,
|
frame802154_t *frame, struct ieee802154_ies *ies,
|
||||||
uint8_t *hdrlen, int frame_without_mic);
|
uint8_t *hdrlen, int frame_without_mic);
|
||||||
|
/**
|
||||||
|
* \brief Set frame pending bit in a packet (whose header was already build)
|
||||||
|
* \param buf The buffer where the packet resides
|
||||||
|
* \param buf_size The buffer size
|
||||||
|
*/
|
||||||
|
void tsch_packet_set_frame_pending(uint8_t *buf, int buf_size);
|
||||||
|
/**
|
||||||
|
* \brief Get frame pending bit from a packet
|
||||||
|
* \param buf The buffer where the packet resides
|
||||||
|
* \param buf_size The buffer size
|
||||||
|
* \return The value of the frame pending bit, 1 or 0
|
||||||
|
*/
|
||||||
|
int tsch_packet_get_frame_pending(uint8_t *buf, int buf_size);
|
||||||
|
|
||||||
#endif /* __TSCH_PACKET_H__ */
|
#endif /* __TSCH_PACKET_H__ */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -423,7 +423,7 @@ tsch_schedule_create_minimal(void)
|
||||||
* but is required according to 802.15.4e if also used for EB transmission.
|
* but is required according to 802.15.4e if also used for EB transmission.
|
||||||
* Timeslot: 0, channel offset: 0. */
|
* Timeslot: 0, channel offset: 0. */
|
||||||
tsch_schedule_add_link(sf_min,
|
tsch_schedule_add_link(sf_min,
|
||||||
LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED | LINK_OPTION_TIME_KEEPING,
|
(LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED | LINK_OPTION_TIME_KEEPING),
|
||||||
LINK_TYPE_ADVERTISING, &tsch_broadcast_address,
|
LINK_TYPE_ADVERTISING, &tsch_broadcast_address,
|
||||||
0, 0);
|
0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ static rtimer_clock_t volatile current_slot_start;
|
||||||
static volatile int tsch_in_slot_operation = 0;
|
static volatile int tsch_in_slot_operation = 0;
|
||||||
|
|
||||||
/* If we are inside a slot, this tells the current channel */
|
/* If we are inside a slot, this tells the current channel */
|
||||||
static uint8_t current_channel;
|
uint8_t tsch_current_channel;
|
||||||
|
|
||||||
/* Info about the link, packet and neighbor of
|
/* Info about the link, packet and neighbor of
|
||||||
* the current (or next) slot */
|
* the current (or next) slot */
|
||||||
|
@ -167,6 +167,11 @@ static struct tsch_link *backup_link = NULL;
|
||||||
static struct tsch_packet *current_packet = NULL;
|
static struct tsch_packet *current_packet = NULL;
|
||||||
static struct tsch_neighbor *current_neighbor = NULL;
|
static struct tsch_neighbor *current_neighbor = NULL;
|
||||||
|
|
||||||
|
/* Indicates whether an extra link is needed to handle the current burst */
|
||||||
|
static int burst_link_scheduled = 0;
|
||||||
|
/* Counts the length of the current burst */
|
||||||
|
int tsch_current_burst_count = 0;
|
||||||
|
|
||||||
/* Protothread for association */
|
/* Protothread for association */
|
||||||
PT_THREAD(tsch_scan(struct pt *pt));
|
PT_THREAD(tsch_scan(struct pt *pt));
|
||||||
/* Protothread for slot operation, called from rtimer interrupt
|
/* Protothread for slot operation, called from rtimer interrupt
|
||||||
|
@ -456,6 +461,8 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
/* is this a broadcast packet? (wait for ack?) */
|
/* is this a broadcast packet? (wait for ack?) */
|
||||||
static uint8_t is_broadcast;
|
static uint8_t is_broadcast;
|
||||||
static rtimer_clock_t tx_start_time;
|
static rtimer_clock_t tx_start_time;
|
||||||
|
/* Did we set the frame pending bit to request an extra burst link? */
|
||||||
|
static int burst_link_requested;
|
||||||
|
|
||||||
#if CCA_ENABLED
|
#if CCA_ENABLED
|
||||||
static uint8_t cca_status;
|
static uint8_t cca_status;
|
||||||
|
@ -466,6 +473,14 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
packet_len = queuebuf_datalen(current_packet->qb);
|
packet_len = queuebuf_datalen(current_packet->qb);
|
||||||
/* is this a broadcast packet? (wait for ack?) */
|
/* is this a broadcast packet? (wait for ack?) */
|
||||||
is_broadcast = current_neighbor->is_broadcast;
|
is_broadcast = current_neighbor->is_broadcast;
|
||||||
|
/* Unicast. More packets in queue for the neighbor? */
|
||||||
|
burst_link_requested = 0;
|
||||||
|
if(!is_broadcast
|
||||||
|
&& tsch_current_burst_count + 1 < TSCH_BURST_MAX_LEN
|
||||||
|
&& tsch_queue_packet_count(¤t_neighbor->addr) > 1) {
|
||||||
|
burst_link_requested = 1;
|
||||||
|
tsch_packet_set_frame_pending(packet, packet_len);
|
||||||
|
}
|
||||||
/* read seqno from payload */
|
/* read seqno from payload */
|
||||||
seqno = ((uint8_t *)(packet))[2];
|
seqno = ((uint8_t *)(packet))[2];
|
||||||
/* if this is an EB, then update its Sync-IE */
|
/* if this is an EB, then update its Sync-IE */
|
||||||
|
@ -618,6 +633,12 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
tsch_schedule_keepalive();
|
tsch_schedule_keepalive();
|
||||||
}
|
}
|
||||||
mac_tx_status = MAC_TX_OK;
|
mac_tx_status = MAC_TX_OK;
|
||||||
|
|
||||||
|
/* We requested an extra slot and got an ack. This means
|
||||||
|
the extra slot will be scheduled at the received */
|
||||||
|
if(burst_link_requested) {
|
||||||
|
burst_link_scheduled = 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mac_tx_status = MAC_TX_NOACK;
|
mac_tx_status = MAC_TX_NOACK;
|
||||||
}
|
}
|
||||||
|
@ -749,7 +770,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
||||||
NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi);
|
NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi);
|
||||||
current_input->rx_asn = tsch_current_asn;
|
current_input->rx_asn = tsch_current_asn;
|
||||||
current_input->rssi = (signed)radio_last_rssi;
|
current_input->rssi = (signed)radio_last_rssi;
|
||||||
current_input->channel = current_channel;
|
current_input->channel = tsch_current_channel;
|
||||||
header_len = frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame);
|
header_len = frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame);
|
||||||
frame_valid = header_len > 0 &&
|
frame_valid = header_len > 0 &&
|
||||||
frame802154_check_dest_panid(&frame) &&
|
frame802154_check_dest_panid(&frame) &&
|
||||||
|
@ -844,6 +865,9 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
||||||
TSCH_DEBUG_RX_EVENT();
|
TSCH_DEBUG_RX_EVENT();
|
||||||
NETSTACK_RADIO.transmit(ack_len);
|
NETSTACK_RADIO.transmit(ack_len);
|
||||||
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||||
|
|
||||||
|
/* Schedule a burst link iff the frame pending bit was set */
|
||||||
|
burst_link_scheduled = tsch_packet_get_frame_pending(current_input->payload, current_input->len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,9 +964,16 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
||||||
}
|
}
|
||||||
is_active_slot = current_packet != NULL || (current_link->link_options & LINK_OPTION_RX);
|
is_active_slot = current_packet != NULL || (current_link->link_options & LINK_OPTION_RX);
|
||||||
if(is_active_slot) {
|
if(is_active_slot) {
|
||||||
/* Hop channel */
|
/* If we are in a burst, we stick to current channel instead of
|
||||||
current_channel = tsch_calculate_channel(&tsch_current_asn, current_link->channel_offset);
|
* doing channel hopping, as per IEEE 802.15.4-2015 */
|
||||||
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel);
|
if(burst_link_scheduled) {
|
||||||
|
/* Reset burst_link_scheduled flag. Will be set again if burst continue. */
|
||||||
|
burst_link_scheduled = 0;
|
||||||
|
} else {
|
||||||
|
/* Hop channel */
|
||||||
|
tsch_current_channel = tsch_calculate_channel(&tsch_current_asn, current_link->channel_offset);
|
||||||
|
}
|
||||||
|
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, tsch_current_channel);
|
||||||
/* Turn the radio on already here if configured so; necessary for radios with slow startup */
|
/* Turn the radio on already here if configured so; necessary for radios with slow startup */
|
||||||
tsch_radio_on(TSCH_RADIO_CMD_ON_START_OF_TIMESLOT);
|
tsch_radio_on(TSCH_RADIO_CMD_ON_START_OF_TIMESLOT);
|
||||||
/* Decide whether it is a TX/RX/IDLE or OFF slot */
|
/* Decide whether it is a TX/RX/IDLE or OFF slot */
|
||||||
|
@ -960,6 +991,10 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
||||||
static struct pt slot_rx_pt;
|
static struct pt slot_rx_pt;
|
||||||
PT_SPAWN(&slot_operation_pt, &slot_rx_pt, tsch_rx_slot(&slot_rx_pt, t));
|
PT_SPAWN(&slot_operation_pt, &slot_rx_pt, tsch_rx_slot(&slot_rx_pt, t));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* Make sure to end the burst in cast, for some reason, we were
|
||||||
|
* in a burst but now without any more packet to send. */
|
||||||
|
burst_link_scheduled = 0;
|
||||||
}
|
}
|
||||||
TSCH_DEBUG_SLOT_END();
|
TSCH_DEBUG_SLOT_END();
|
||||||
}
|
}
|
||||||
|
@ -993,13 +1028,27 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
||||||
tsch_queue_update_all_backoff_windows(¤t_link->addr);
|
tsch_queue_update_all_backoff_windows(¤t_link->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get next active link */
|
/* A burst link was scheduled. Replay the current link at the
|
||||||
current_link = tsch_schedule_get_next_active_link(&tsch_current_asn, ×lot_diff, &backup_link);
|
next time offset */
|
||||||
if(current_link == NULL) {
|
if(burst_link_scheduled) {
|
||||||
/* There is no next link. Fall back to default
|
|
||||||
* behavior: wake up at the next slot. */
|
|
||||||
timeslot_diff = 1;
|
timeslot_diff = 1;
|
||||||
|
backup_link = NULL;
|
||||||
|
/* Keep track of the number of repetitions */
|
||||||
|
tsch_current_burst_count++;
|
||||||
|
} else {
|
||||||
|
/* Get next active link */
|
||||||
|
current_link = tsch_schedule_get_next_active_link(&tsch_current_asn, ×lot_diff, &backup_link);
|
||||||
|
if(current_link == NULL) {
|
||||||
|
/* There is no next link. Fall back to default
|
||||||
|
* behavior: wake up at the next slot. */
|
||||||
|
timeslot_diff = 1;
|
||||||
|
} else {
|
||||||
|
/* Reset burst index now that the link was scheduled from
|
||||||
|
normal schedule (as opposed to from ongoing burst) */
|
||||||
|
tsch_current_burst_count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update ASN */
|
/* Update ASN */
|
||||||
TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
|
TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
|
||||||
/* Time to next wake up */
|
/* Time to next wake up */
|
||||||
|
|
|
@ -57,6 +57,8 @@ extern struct ringbufindex input_ringbuf;
|
||||||
extern struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
|
extern struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
|
||||||
/* Last clock_time_t where synchronization happened */
|
/* Last clock_time_t where synchronization happened */
|
||||||
extern clock_time_t last_sync_time;
|
extern clock_time_t last_sync_time;
|
||||||
|
/* Counts the length of the current burst */
|
||||||
|
extern int tsch_current_burst_count;
|
||||||
|
|
||||||
/********** Functions *********/
|
/********** Functions *********/
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,8 @@ extern const linkaddr_t tsch_eb_address;
|
||||||
extern struct tsch_asn_t tsch_current_asn;
|
extern struct tsch_asn_t tsch_current_asn;
|
||||||
extern uint8_t tsch_join_priority;
|
extern uint8_t tsch_join_priority;
|
||||||
extern struct tsch_link *current_link;
|
extern struct tsch_link *current_link;
|
||||||
|
/* If we are inside a slot, this tells the current channel */
|
||||||
|
extern uint8_t tsch_current_channel;
|
||||||
/* TSCH channel hopping sequence */
|
/* TSCH channel hopping sequence */
|
||||||
extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
|
extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
|
||||||
extern struct tsch_asn_divisor_t tsch_hopping_sequence_length;
|
extern struct tsch_asn_divisor_t tsch_hopping_sequence_length;
|
||||||
|
|
Loading…
Reference in New Issue