TSCH: add option to not to turn off radio during active TSCH timeslots
This commit is contained in:
parent
723c7e1117
commit
45510f57fa
|
@ -184,4 +184,11 @@
|
|||
#define TSCH_HW_FRAME_FILTERING 1
|
||||
#endif /* TSCH_CONF_HW_FRAME_FILTERING */
|
||||
|
||||
/* Keep radio always on within TSCH timeslot (1) or turn it off between packet and ACK? (0) */
|
||||
#ifdef TSCH_CONF_RADIO_ON_DURING_TIMESLOT
|
||||
#define TSCH_RADIO_ON_DURING_TIMESLOT TSCH_CONF_RADIO_ON_DURING_TIMESLOT
|
||||
#else
|
||||
#define TSCH_RADIO_ON_DURING_TIMESLOT 0
|
||||
#endif
|
||||
|
||||
#endif /* __TSCH_CONF_H__ */
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
* \author
|
||||
* Simon Duquennoy <simonduq@sics.se>
|
||||
* Beshr Al Nahas <beshr@sics.se>
|
||||
* Atis Elsts <atis.elsts@bristol.ac.uk>
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -109,6 +110,18 @@
|
|||
#define RTIMER_GUARD 2u
|
||||
#endif
|
||||
|
||||
enum tsch_radio_state_on_cmd {
|
||||
TSCH_RADIO_CMD_ON_START_OF_TIMESLOT,
|
||||
TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT,
|
||||
TSCH_RADIO_CMD_ON_FORCE,
|
||||
};
|
||||
|
||||
enum tsch_radio_state_off_cmd {
|
||||
TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT,
|
||||
TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT,
|
||||
TSCH_RADIO_CMD_OFF_FORCE,
|
||||
};
|
||||
|
||||
/* A ringbuf storing outgoing packets after they were dequeued.
|
||||
* Will be processed layer by tsch_tx_process_pending */
|
||||
struct ringbufindex dequeued_ringbuf;
|
||||
|
@ -370,6 +383,68 @@ update_neighbor_state(struct tsch_neighbor *n, struct tsch_packet *p,
|
|||
return in_queue;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* This function turns on the radio. Its semantics is dependent on
|
||||
* the value of TSCH_RADIO_ON_DURING_TIMESLOT constant:
|
||||
* - if enabled, the radio is turned on at the start of the slot
|
||||
* - if disabled, the radio is turned on within the slot,
|
||||
* directly before the packet Rx guard time and ACK Rx guard time.
|
||||
*/
|
||||
static void
|
||||
tsch_radio_on(enum tsch_radio_state_on_cmd command)
|
||||
{
|
||||
int do_it = 0;
|
||||
switch(command) {
|
||||
case TSCH_RADIO_CMD_ON_START_OF_TIMESLOT:
|
||||
if(TSCH_RADIO_ON_DURING_TIMESLOT) {
|
||||
do_it = 1;
|
||||
}
|
||||
break;
|
||||
case TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT:
|
||||
if(!TSCH_RADIO_ON_DURING_TIMESLOT) {
|
||||
do_it = 1;
|
||||
}
|
||||
break;
|
||||
case TSCH_RADIO_CMD_ON_FORCE:
|
||||
do_it = 1;
|
||||
break;
|
||||
}
|
||||
if(do_it) {
|
||||
NETSTACK_RADIO.on();
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* This function turns off the radio. In the same way as for tsch_radio_on(),
|
||||
* it depends on the value of TSCH_RADIO_ON_DURING_TIMESLOT constant:
|
||||
* - if enabled, the radio is turned off at the end of the slot
|
||||
* - if disabled, the radio is turned off within the slot,
|
||||
* directly after Tx'ing or Rx'ing a packet or Tx'ing an ACK.
|
||||
*/
|
||||
static void
|
||||
tsch_radio_off(enum tsch_radio_state_off_cmd command)
|
||||
{
|
||||
int do_it = 0;
|
||||
switch(command) {
|
||||
case TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT:
|
||||
if(TSCH_RADIO_ON_DURING_TIMESLOT) {
|
||||
do_it = 1;
|
||||
}
|
||||
break;
|
||||
case TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT:
|
||||
if(!TSCH_RADIO_ON_DURING_TIMESLOT) {
|
||||
do_it = 1;
|
||||
}
|
||||
break;
|
||||
case TSCH_RADIO_CMD_OFF_FORCE:
|
||||
do_it = 1;
|
||||
break;
|
||||
}
|
||||
if(do_it) {
|
||||
NETSTACK_RADIO.off();
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static
|
||||
PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||
{
|
||||
|
@ -456,7 +531,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
|||
/* delay before CCA */
|
||||
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, TS_CCA_OFFSET, "cca");
|
||||
TSCH_DEBUG_TX_EVENT();
|
||||
NETSTACK_RADIO.on();
|
||||
tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT);
|
||||
/* CCA */
|
||||
BUSYWAIT_UNTIL_ABS(!(cca_status |= NETSTACK_RADIO.channel_clear()),
|
||||
current_slot_start, TS_CCA_OFFSET + TS_CCA);
|
||||
|
@ -480,7 +555,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
|||
/* limit tx_time to its max value */
|
||||
tx_duration = MIN(tx_duration, tsch_timing[tsch_ts_max_tx]);
|
||||
/* turn tadio off -- will turn on again to wait for ACK if needed */
|
||||
NETSTACK_RADIO.off();
|
||||
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||
|
||||
if(mac_tx_status == RADIO_TX_OK) {
|
||||
if(!is_broadcast) {
|
||||
|
@ -502,7 +577,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
|||
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start,
|
||||
tsch_timing[tsch_ts_tx_offset] + tx_duration + tsch_timing[tsch_ts_rx_ack_delay] - RADIO_DELAY_BEFORE_RX, "TxBeforeAck");
|
||||
TSCH_DEBUG_TX_EVENT();
|
||||
NETSTACK_RADIO.on();
|
||||
tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT);
|
||||
/* Wait for ACK to come */
|
||||
BUSYWAIT_UNTIL_ABS(NETSTACK_RADIO.receiving_packet(),
|
||||
tx_start_time, tx_duration + tsch_timing[tsch_ts_rx_ack_delay] + tsch_timing[tsch_ts_ack_wait]);
|
||||
|
@ -514,7 +589,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
|||
BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
|
||||
ack_start_time, tsch_timing[tsch_ts_max_ack]);
|
||||
TSCH_DEBUG_TX_EVENT();
|
||||
NETSTACK_RADIO.off();
|
||||
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||
|
||||
#if TSCH_HW_FRAME_FILTERING
|
||||
/* Leaving promiscuous mode */
|
||||
|
@ -588,6 +663,8 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
|||
}
|
||||
}
|
||||
|
||||
tsch_radio_off(TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT);
|
||||
|
||||
current_packet->transmissions++;
|
||||
current_packet->ret = mac_tx_status;
|
||||
|
||||
|
@ -671,27 +748,26 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
|||
TSCH_DEBUG_RX_EVENT();
|
||||
|
||||
/* Start radio for at least guard time */
|
||||
NETSTACK_RADIO.on();
|
||||
packet_seen = NETSTACK_RADIO.receiving_packet();
|
||||
tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT);
|
||||
packet_seen = NETSTACK_RADIO.receiving_packet() || NETSTACK_RADIO.pending_packet();
|
||||
if(!packet_seen) {
|
||||
/* Check if receiving within guard time */
|
||||
BUSYWAIT_UNTIL_ABS((packet_seen = NETSTACK_RADIO.receiving_packet()),
|
||||
current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait]);
|
||||
}
|
||||
if(packet_seen) {
|
||||
if(!packet_seen) {
|
||||
/* no packets on air */
|
||||
tsch_radio_off(TSCH_RADIO_CMD_OFF_FORCE);
|
||||
} else {
|
||||
TSCH_DEBUG_RX_EVENT();
|
||||
/* Save packet timestamp */
|
||||
rx_start_time = RTIMER_NOW() - RADIO_DELAY_BEFORE_DETECT;
|
||||
}
|
||||
if(!NETSTACK_RADIO.receiving_packet() && !NETSTACK_RADIO.pending_packet()) {
|
||||
NETSTACK_RADIO.off();
|
||||
/* no packets on air */
|
||||
} else {
|
||||
|
||||
/* Wait until packet is received, turn radio off */
|
||||
BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(),
|
||||
current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait] + tsch_timing[tsch_ts_max_tx]);
|
||||
TSCH_DEBUG_RX_EVENT();
|
||||
NETSTACK_RADIO.off();
|
||||
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||
|
||||
#if TSCH_RESYNC_WITH_SFD_TIMESTAMPS
|
||||
/* At the end of the reception, get an more accurate estimate of SFD arrival time */
|
||||
|
@ -784,7 +860,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
|||
packet_duration + tsch_timing[tsch_ts_tx_ack_delay] - RADIO_DELAY_BEFORE_TX, "RxBeforeAck");
|
||||
TSCH_DEBUG_RX_EVENT();
|
||||
NETSTACK_RADIO.transmit(ack_len);
|
||||
NETSTACK_RADIO.off();
|
||||
tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT);
|
||||
}
|
||||
|
||||
/* If the sender is a time source, proceed to clock drift compensation */
|
||||
|
@ -820,6 +896,8 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
|
|||
process_poll(&tsch_pending_events_process);
|
||||
}
|
||||
}
|
||||
|
||||
tsch_radio_off(TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT);
|
||||
}
|
||||
|
||||
if(input_queue_drop != 0) {
|
||||
|
@ -860,8 +938,12 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
|||
|
||||
} else {
|
||||
uint8_t current_channel;
|
||||
int is_active_slot;
|
||||
TSCH_DEBUG_SLOT_START();
|
||||
tsch_in_slot_operation = 1;
|
||||
/* Reset drift correction */
|
||||
drift_correction = 0;
|
||||
is_drift_correction_used = 0;
|
||||
/* Get a packet ready to be sent */
|
||||
current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor);
|
||||
/* There is no packet to send, and this link does not have Rx flag. Instead of doing
|
||||
|
@ -870,26 +952,28 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
|
|||
current_link = backup_link;
|
||||
current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor);
|
||||
}
|
||||
/* Hop channel */
|
||||
current_channel = tsch_calculate_channel(¤t_asn, current_link->channel_offset);
|
||||
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel);
|
||||
/* Reset drift correction */
|
||||
drift_correction = 0;
|
||||
is_drift_correction_used = 0;
|
||||
/* Decide whether it is a TX/RX/IDLE or OFF slot */
|
||||
/* Actual slot operation */
|
||||
if(current_packet != NULL) {
|
||||
/* We have something to transmit, do the following:
|
||||
* 1. send
|
||||
* 2. update_backoff_state(current_neighbor)
|
||||
* 3. post tx callback
|
||||
**/
|
||||
static struct pt slot_tx_pt;
|
||||
PT_SPAWN(&slot_operation_pt, &slot_tx_pt, tsch_tx_slot(&slot_tx_pt, t));
|
||||
} else if((current_link->link_options & LINK_OPTION_RX)) {
|
||||
/* Listen */
|
||||
static struct pt slot_rx_pt;
|
||||
PT_SPAWN(&slot_operation_pt, &slot_rx_pt, tsch_rx_slot(&slot_rx_pt, t));
|
||||
is_active_slot = current_packet != NULL || (current_link->link_options & LINK_OPTION_RX);
|
||||
if(is_active_slot) {
|
||||
/* Hop channel */
|
||||
current_channel = tsch_calculate_channel(¤t_asn, current_link->channel_offset);
|
||||
NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, 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 */
|
||||
/* Actual slot operation */
|
||||
if(current_packet != NULL) {
|
||||
/* We have something to transmit, do the following:
|
||||
* 1. send
|
||||
* 2. update_backoff_state(current_neighbor)
|
||||
* 3. post tx callback
|
||||
**/
|
||||
static struct pt slot_tx_pt;
|
||||
PT_SPAWN(&slot_operation_pt, &slot_tx_pt, tsch_tx_slot(&slot_tx_pt, t));
|
||||
} else {
|
||||
/* Listen */
|
||||
static struct pt slot_rx_pt;
|
||||
PT_SPAWN(&slot_operation_pt, &slot_rx_pt, tsch_rx_slot(&slot_rx_pt, t));
|
||||
}
|
||||
}
|
||||
TSCH_DEBUG_SLOT_END();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue