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))
|
||||
#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 */
|
||||
#ifdef 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);
|
||||
} else {
|
||||
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->link->slotframe_handle, sf ? sf->size.val : 0, log->link->timeslot, log->link->channel_offset,
|
||||
tsch_calculate_channel(&log->asn, log->link->channel_offset));
|
||||
log->link->slotframe_handle, sf ? sf->size.val : 0,
|
||||
log->burst_count, log->link->timeslot + log->burst_count, log->link->channel_offset,
|
||||
log->channel);
|
||||
}
|
||||
switch(log->type) {
|
||||
case tsch_log_tx:
|
||||
|
@ -135,6 +136,8 @@ tsch_log_prepare_add(void)
|
|||
struct tsch_log_t *log = &log_array[log_index];
|
||||
log->asn = tsch_current_asn;
|
||||
log->link = current_link;
|
||||
log->burst_count = tsch_current_burst_count;
|
||||
log->channel = tsch_current_channel;
|
||||
return log;
|
||||
} else {
|
||||
log_dropped++;
|
||||
|
|
|
@ -80,6 +80,8 @@ struct tsch_log_t {
|
|||
} type;
|
||||
struct tsch_asn_t asn;
|
||||
struct tsch_link *link;
|
||||
uint8_t burst_count;
|
||||
uint8_t channel;
|
||||
union {
|
||||
char message[48];
|
||||
struct {
|
||||
|
|
|
@ -70,6 +70,9 @@
|
|||
*/
|
||||
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
|
||||
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;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* 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,
|
||||
frame802154_t *frame, struct ieee802154_ies *ies,
|
||||
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__ */
|
||||
/** @} */
|
||||
|
|
|
@ -423,7 +423,7 @@ tsch_schedule_create_minimal(void)
|
|||
* but is required according to 802.15.4e if also used for EB transmission.
|
||||
* Timeslot: 0, channel offset: 0. */
|
||||
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,
|
||||
0, 0);
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ static rtimer_clock_t volatile current_slot_start;
|
|||
static volatile int tsch_in_slot_operation = 0;
|
||||
|
||||
/* 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
|
||||
* 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_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 */
|
||||
PT_THREAD(tsch_scan(struct pt *pt));
|
||||
/* 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?) */
|
||||
static uint8_t is_broadcast;
|
||||
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
|
||||
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);
|
||||
/* is this a broadcast packet? (wait for ack?) */
|
||||
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 */
|
||||
seqno = ((uint8_t *)(packet))[2];
|
||||
/* 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();
|
||||
}
|
||||
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 {
|
||||
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);
|
||||
current_input->rx_asn = tsch_current_asn;
|
||||
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);
|
||||
frame_valid = header_len > 0 &&
|
||||
frame802154_check_dest_panid(&frame) &&
|
||||
|
@ -844,6 +865,9 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
|||
TSCH_DEBUG_RX_EVENT();
|
||||
NETSTACK_RADIO.transmit(ack_len);
|
||||
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);
|
||||
if(is_active_slot) {
|
||||
/* Hop channel */
|
||||
current_channel = tsch_calculate_channel(&tsch_current_asn, current_link->channel_offset);
|
||||
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel);
|
||||
/* If we are in a burst, we stick to current channel instead of
|
||||
* doing channel hopping, as per IEEE 802.15.4-2015 */
|
||||
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 */
|
||||
tsch_radio_on(TSCH_RADIO_CMD_ON_START_OF_TIMESLOT);
|
||||
/* 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;
|
||||
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();
|
||||
}
|
||||
|
@ -993,13 +1028,27 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
|||
tsch_queue_update_all_backoff_windows(¤t_link->addr);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
/* A burst link was scheduled. Replay the current link at the
|
||||
next time offset */
|
||||
if(burst_link_scheduled) {
|
||||
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 */
|
||||
TSCH_ASN_INC(tsch_current_asn, timeslot_diff);
|
||||
/* Time to next wake up */
|
||||
|
|
|
@ -57,6 +57,8 @@ extern struct ringbufindex input_ringbuf;
|
|||
extern struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
|
||||
/* Last clock_time_t where synchronization happened */
|
||||
extern clock_time_t last_sync_time;
|
||||
/* Counts the length of the current burst */
|
||||
extern int tsch_current_burst_count;
|
||||
|
||||
/********** Functions *********/
|
||||
|
||||
|
|
|
@ -164,6 +164,8 @@ extern const linkaddr_t tsch_eb_address;
|
|||
extern struct tsch_asn_t tsch_current_asn;
|
||||
extern uint8_t tsch_join_priority;
|
||||
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 */
|
||||
extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
|
||||
extern struct tsch_asn_divisor_t tsch_hopping_sequence_length;
|
||||
|
|
Loading…
Reference in New Issue