Fixed wrong first cycle_start

The first time that powercycle() runs, cycle_start is incremented
by CHECK_TIME twice which causes the second cycle to be late.

This commit fixes this.
This commit is contained in:
Billy Kozak 2015-07-10 15:44:46 -06:00
parent 0313a429e2
commit ac6a1c5255
1 changed files with 54 additions and 42 deletions

View File

@ -289,9 +289,15 @@ off(void)
}
}
/*---------------------------------------------------------------------------*/
static volatile rtimer_clock_t cycle_start;
static void powercycle_wrapper(struct rtimer *t, void *ptr);
static char powercycle(struct rtimer *t, void *ptr);
/*---------------------------------------------------------------------------*/
static volatile rtimer_clock_t cycle_start;
#if SYNC_CYCLE_STARTS
static volatile rtimer_clock_t sync_cycle_start;
static volatile uint8_t sync_cycle_phase;
#endif
/*---------------------------------------------------------------------------*/
static void
schedule_powercycle(struct rtimer *t, rtimer_clock_t time)
{
@ -340,7 +346,7 @@ powercycle_turn_radio_off(void)
#if CONTIKIMAC_CONF_COMPOWER
uint8_t was_on = radio_is_on;
#endif /* CONTIKIMAC_CONF_COMPOWER */
if(we_are_sending == 0 && we_are_receiving_burst == 0) {
off();
#if CONTIKIMAC_CONF_COMPOWER
@ -365,13 +371,34 @@ powercycle_wrapper(struct rtimer *t, void *ptr)
powercycle(t, ptr);
}
/*---------------------------------------------------------------------------*/
static void
advance_cycle_start(void)
{
#if SYNC_CYCLE_STARTS
/* Compute cycle start when RTIMER_ARCH_SECOND is not a multiple
of CHANNEL_CHECK_RATE */
if(sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
sync_cycle_phase = 0;
sync_cycle_start += RTIMER_ARCH_SECOND;
cycle_start = sync_cycle_start;
} else if( (RTIMER_ARCH_SECOND * NETSTACK_RDC_CHANNEL_CHECK_RATE) > 65535) {
uint32_t phase_time = sync_cycle_phase*RTIMER_ARCH_SECOND;
cycle_start = sync_cycle_start + phase_time/NETSTACK_RDC_CHANNEL_CHECK_RATE;
} else {
unsigned phase_time = sync_cycle_phase*RTIMER_ARCH_SECOND;
cycle_start = sync_cycle_start + phase_time/NETSTACK_RDC_CHANNEL_CHECK_RATE;
}
#endif
cycle_start += CYCLE_TIME;
}
/*---------------------------------------------------------------------------*/
static char
powercycle(struct rtimer *t, void *ptr)
{
#if SYNC_CYCLE_STARTS
static volatile rtimer_clock_t sync_cycle_start;
static volatile uint8_t sync_cycle_phase;
#endif
PT_BEGIN(&pt);
@ -385,24 +412,6 @@ powercycle(struct rtimer *t, void *ptr)
static uint8_t packet_seen;
static uint8_t count;
#if SYNC_CYCLE_STARTS
/* Compute cycle start when RTIMER_ARCH_SECOND is not a multiple
of CHANNEL_CHECK_RATE */
if(sync_cycle_phase++ == NETSTACK_RDC_CHANNEL_CHECK_RATE) {
sync_cycle_phase = 0;
sync_cycle_start += RTIMER_ARCH_SECOND;
cycle_start = sync_cycle_start;
} else {
#if (RTIMER_ARCH_SECOND * NETSTACK_RDC_CHANNEL_CHECK_RATE) > 65535
cycle_start = sync_cycle_start + ((unsigned long)(sync_cycle_phase*RTIMER_ARCH_SECOND))/NETSTACK_RDC_CHANNEL_CHECK_RATE;
#else
cycle_start = sync_cycle_start + (sync_cycle_phase*RTIMER_ARCH_SECOND)/NETSTACK_RDC_CHANNEL_CHECK_RATE;
#endif
}
#else
cycle_start += CYCLE_TIME;
#endif
packet_seen = 0;
for(count = 0; count < CCA_COUNT_MAX; ++count) {
@ -483,22 +492,25 @@ powercycle(struct rtimer *t, void *ptr)
}
}
if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) {
advance_cycle_start();
if(RTIMER_CLOCK_LT(RTIMER_NOW() , cycle_start - CHECK_TIME * 4)) {
/* Schedule the next powercycle interrupt, or sleep the mcu
until then. Sleeping will not exit from this interrupt, so
ensure an occasional wake cycle or foreground processing will
be blocked until a packet is detected */
until then. Sleeping will not exit from this interrupt, so
ensure an occasional wake cycle or foreground processing will
be blocked until a packet is detected */
#if RDC_CONF_MCU_SLEEP
static uint8_t sleepcycle;
if((sleepcycle++ < 16) && !we_are_sending && !radio_is_on) {
rtimer_arch_sleep(CYCLE_TIME - (RTIMER_NOW() - cycle_start));
rtimer_arch_sleep(RTIMER_NOW() - cycle_start);
} else {
sleepcycle = 0;
schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
schedule_powercycle_fixed(t, cycle_start);
PT_YIELD(&pt);
}
#else
schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
schedule_powercycle_fixed(t, cycle_start);
PT_YIELD(&pt);
#endif
}
@ -549,13 +561,13 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
int len;
uint8_t seqno;
#endif
/* Exit if RDC and radio were explicitly turned off */
if(!contikimac_is_on && !contikimac_keep_radio_on) {
PRINTF("contikimac: radio is turned off\n");
return MAC_TX_ERR_FATAL;
}
if(packetbuf_totlen() == 0) {
PRINTF("contikimac: send_packet data len 0\n");
return MAC_TX_ERR_FATAL;
@ -597,10 +609,10 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
return MAC_TX_ERR_FATAL;
}
}
transmit_len = packetbuf_totlen();
NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len);
if(!is_broadcast && !is_receiver_awake) {
#if WITH_PHASE_OPTIMIZATION
ret = phase_wait(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
@ -612,9 +624,9 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
if(ret != PHASE_UNKNOWN) {
is_known_receiver = 1;
}
#endif /* WITH_PHASE_OPTIMIZATION */
#endif /* WITH_PHASE_OPTIMIZATION */
}
/* By setting we_are_sending to one, we ensure that the rtimer
@ -632,7 +644,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr,
NETSTACK_RADIO.receiving_packet(), NETSTACK_RADIO.pending_packet());
return MAC_TX_COLLISION;
}
/* Switch off the radio to ensure that we didn't start sending while
the radio was doing a channel check. */
off();
@ -838,7 +850,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
int ret;
int is_receiver_awake;
int pending;
if(buf_list == NULL) {
return;
}
@ -850,7 +862,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
mac_call_sent_callback(sent, ptr, MAC_TX_COLLISION, 1);
return;
}
/* Create and secure frames in advance */
curr = buf_list;
do {
@ -867,13 +879,13 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1);
return;
}
packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1);
queuebuf_update_from_packetbuf(curr->buf);
}
curr = next;
} while(next != NULL);
/* The receiver needs to be awoken before we send */
is_receiver_awake = 0;
curr = buf_list;