Bugfix and optimization: X-MAC did not properly switch the radio off after sending a packet, resulting in increased power consumption. For packets that require an ACK, we can let the radio be on in anticipation of the ACK (controlled with an WITH_ACK_OPTIMIZATION option)

This commit is contained in:
adamdunkels 2009-03-05 19:37:52 +00:00
parent 64badeb282
commit dc7491f810
1 changed files with 24 additions and 15 deletions

View File

@ -28,7 +28,7 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* $Id: xmac.c,v 1.26 2009/03/01 20:38:57 adamdunkels Exp $ * $Id: xmac.c,v 1.27 2009/03/05 19:37:52 adamdunkels Exp $
*/ */
/** /**
@ -63,6 +63,7 @@
#define WITH_CHANNEL_CHECK 0 /* Seems to work badly when enabled */ #define WITH_CHANNEL_CHECK 0 /* Seems to work badly when enabled */
#define WITH_TIMESYNCH 0 #define WITH_TIMESYNCH 0
#define WITH_QUEUE 0 #define WITH_QUEUE 0
#define WITH_ACK_OPTIMIZATION 1
struct announcement_data { struct announcement_data {
uint16_t id; uint16_t id;
@ -353,7 +354,7 @@ send_packet(void)
rtimer_clock_t t; rtimer_clock_t t;
int strobes; int strobes;
struct xmac_hdr hdr; struct xmac_hdr hdr;
int got_ack = 0; int got_strobe_ack = 0;
struct { struct {
struct xmac_hdr hdr; struct xmac_hdr hdr;
struct announcement_msg announcement; struct announcement_msg announcement;
@ -421,9 +422,9 @@ send_packet(void)
} }
watchdog_stop(); watchdog_stop();
got_ack = 0; got_strobe_ack = 0;
for(strobes = 0; for(strobes = 0;
got_ack == 0 && got_strobe_ack == 0 &&
RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time); RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + xmac_config.strobe_time);
strobes++) { strobes++) {
@ -444,7 +445,7 @@ send_packet(void)
CPRINTF("+"); CPRINTF("+");
while(got_ack == 0 && while(got_strobe_ack == 0 &&
RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) { RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)) {
/* See if we got an ACK */ /* See if we got an ACK */
len = radio->read((uint8_t *)&strobe, sizeof(struct xmac_hdr)); len = radio->read((uint8_t *)&strobe, sizeof(struct xmac_hdr));
@ -458,7 +459,7 @@ send_packet(void)
CPRINTF("@"); CPRINTF("@");
/* We got an ACK from the receiver, so we can immediately send /* We got an ACK from the receiver, so we can immediately send
the packet. */ the packet. */
got_ack = 1; got_strobe_ack = 1;
} }
} }
} }
@ -466,28 +467,37 @@ send_packet(void)
/* XXX: turn off radio if we haven't heard an ACK within a /* XXX: turn off radio if we haven't heard an ACK within a
specified time interval. */ specified time interval. */
/* if(got_ack == 0) { /* if(got_strobe_ack == 0) {
off(); off();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time)); while(RTIMER_CLOCK_LT(RTIMER_NOW(), t + xmac_config.strobe_wait_time));
on(); on();
}*/ }*/
} }
if(got_ack /* XXX && needs_ack */) { /* If we have received the strobe ACK, and we are sending a packet
that will need an upper layer ACK (as signified by the
RIMEBUF_ATTR_RELIABLE packet attribute), we keep the radio on. */
if(got_strobe_ack && rimebuf_attr(RIMEBUF_ATTR_RELIABLE)) {
#if WITH_TIMETABLE #if WITH_TIMETABLE
TIMETABLE_TIMESTAMP(xmac_timetable, "send got ack"); TIMETABLE_TIMESTAMP(xmac_timetable, "send got ack");
#endif #endif
on(); /* Wait for possible ACK packet */ #if WITH_ACK_OPTIMIZATION
} else if(!is_broadcast) { on(); /* Wait for ACK packet */
waiting_for_packet = 1;
#else /* WITH_ACK_OPTIMIZATION */
off();
#endif /* WITH_ACK_OPTIMIZATION */
} else {
#if WITH_TIMETABLE #if WITH_TIMETABLE
TIMETABLE_TIMESTAMP(xmac_timetable, "send no ack received"); TIMETABLE_TIMESTAMP(xmac_timetable, "send no ack received");
#endif #endif
on(); /* shell ping don't seem to work with off() here, so we'll off(); /* shell ping don't seem to work with off() here, so we'll
keep it on() for a while. */ keep it on() for a while. */
} }
/* Send the data packet. */ /* Send the data packet. */
if(is_broadcast || got_ack) { if(is_broadcast || got_strobe_ack) {
#if WITH_TIMETABLE #if WITH_TIMETABLE
TIMETABLE_TIMESTAMP(xmac_timetable, "send packet"); TIMETABLE_TIMESTAMP(xmac_timetable, "send packet");
#endif #endif
@ -497,7 +507,7 @@ send_packet(void)
watchdog_start(); watchdog_start();
PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes, PRINTF("xmac: send (strobes=%u,len=%u,%s), done\n", strobes,
rimebuf_totlen(), got_ack ? "ack" : "no ack"); rimebuf_totlen(), got_strobe_ack ? "ack" : "no ack");
#if XMAC_CONF_COMPOWER #if XMAC_CONF_COMPOWER
/* Accumulate the power consumption for the packet transmission. */ /* Accumulate the power consumption for the packet transmission. */
@ -566,7 +576,7 @@ read_packet(void)
rimebuf_clear(); rimebuf_clear();
len = radio->read(rimebuf_dataptr(), RIMEBUF_SIZE); len = radio->read(rimebuf_dataptr(), RIMEBUF_SIZE);
if(len > 0) { if(len > 0) {
rimebuf_set_datalen(len); rimebuf_set_datalen(len);
hdr = rimebuf_dataptr(); hdr = rimebuf_dataptr();
@ -640,7 +650,6 @@ read_packet(void)
#if XMAC_CONF_COMPOWER #if XMAC_CONF_COMPOWER
/* Accumulate the power consumption for the packet reception. */ /* Accumulate the power consumption for the packet reception. */
compower_accumulate(&current_packet); compower_accumulate(&current_packet);
/* Convert the accumulated power consumption for the received /* Convert the accumulated power consumption for the received
packet to packet attributes so that the higher levels can packet to packet attributes so that the higher levels can
keep track of the amount of energy spent on receiving the keep track of the amount of energy spent on receiving the