Add RDC_CONF_HARDWARE_CSMA, RDC_CONF_HARDWARE_ACK, RDC_CONF_MCU_SLEEP, CONTIKIMAC_CONF_SHORTEST_PACKET_SIZE for use with hardware having those modes.

Default behaviour should be unchanged.
This commit is contained in:
David Kopf 2011-11-14 12:02:47 -05:00
parent 3612fdff5b
commit 8e47694597

View file

@ -28,7 +28,6 @@
* *
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
* *
* $Id: contikimac.c,v 1.48 2011/01/25 14:29:46 adamdunkels Exp $
*/ */
/** /**
@ -55,17 +54,33 @@
#include <string.h> #include <string.h>
/* TX/RX cycles are synchronized with neighbor wake periods */
#ifndef WITH_PHASE_OPTIMIZATION #ifndef WITH_PHASE_OPTIMIZATION
#define WITH_PHASE_OPTIMIZATION 1 #define WITH_PHASE_OPTIMIZATION 1
#endif #endif
/* Two byte header added to allow recovery of padded short packets */
/* Wireshark will not understand such packets at present */
#ifdef CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER #ifdef CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER
#define WITH_CONTIKIMAC_HEADER CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER #define WITH_CONTIKIMAC_HEADER CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER
#else #else
#define WITH_CONTIKIMAC_HEADER 1 #define WITH_CONTIKIMAC_HEADER 1
#endif #endif
/* More aggressive radio sleeping when channel is busy with other traffic */
#ifndef WITH_FAST_SLEEP #ifndef WITH_FAST_SLEEP
#define WITH_FAST_SLEEP 1 #define WITH_FAST_SLEEP 1
#endif #endif
/* Radio does CSMA and autobackoff */
#ifndef RDC_CONF_HARDWARE_CSMA
#define RDC_CONF_HARDWARE_CSMA 0
#endif
/* Radio returns TX_OK/TX_NOACK after autoack wait */
#ifndef RDC_CONF_HARDWARE_ACK
#define RDC_CONF_HARDWARE_ACK 0
#endif
/* MCU can sleep during radio off */
#ifndef RDC_CONF_MCU_SLEEP
#define RDC_CONF_MCU_SLEEP 0
#endif
#if NETSTACK_RDC_CHANNEL_CHECK_RATE >= 64 #if NETSTACK_RDC_CHANNEL_CHECK_RATE >= 64
#undef WITH_PHASE_OPTIMIZATION #undef WITH_PHASE_OPTIMIZATION
@ -107,10 +122,16 @@ static int is_receiver_awake = 0;
#define CCA_COUNT_MAX_TX 6 #define CCA_COUNT_MAX_TX 6
/* CCA_CHECK_TIME is the time it takes to perform a CCA check. */ /* CCA_CHECK_TIME is the time it takes to perform a CCA check. */
/* Note this may be zero. AVRs have 7612 ticks/sec, but block until cca is done */
#define CCA_CHECK_TIME RTIMER_ARCH_SECOND / 8192 #define CCA_CHECK_TIME RTIMER_ARCH_SECOND / 8192
/* CCA_SLEEP_TIME is the time between two successive CCA checks. */ /* CCA_SLEEP_TIME is the time between two successive CCA checks. */
/* Add 1 when rtimer ticks are coarse */
#if RTIMER_ARCH_SECOND > 8000
#define CCA_SLEEP_TIME RTIMER_ARCH_SECOND / 2000 #define CCA_SLEEP_TIME RTIMER_ARCH_SECOND / 2000
#else
#define CCA_SLEEP_TIME (RTIMER_ARCH_SECOND / 2000) + 1
#endif
/* CHECK_TIME is the total time it takes to perform CCA_COUNT_MAX /* CHECK_TIME is the total time it takes to perform CCA_COUNT_MAX
CCAs. */ CCAs. */
@ -161,8 +182,15 @@ static int is_receiver_awake = 0;
/* SHORTEST_PACKET_SIZE is the shortest packet that ContikiMAC /* SHORTEST_PACKET_SIZE is the shortest packet that ContikiMAC
allows. Packets have to be a certain size to be able to be detected allows. Packets have to be a certain size to be able to be detected
by two consecutive CCA checks, and here is where we define this by two consecutive CCA checks, and here is where we define this
shortest size. */ shortest size.
Padded packets will have the wrong ipv6 checksum unless CONTIKIMAC_HEADER
is used (on both sides) and the receiver will ignore them.
With no header, reduce to transmit a proper multicast RPL DIS. */
#ifdef CONTIKIMAC_CONF_SHORTEST_PACKET_SIZE
#define SHORTEST_PACKET_SIZE CONTIKIMAC_CONF_SHORTEST_PACKET_SIZE
#else
#define SHORTEST_PACKET_SIZE 43 #define SHORTEST_PACKET_SIZE 43
#endif
#define ACK_LEN 3 #define ACK_LEN 3
@ -367,11 +395,15 @@ powercycle(struct rtimer *t, void *ptr)
received (as indicated by the received (as indicated by the
NETSTACK_RADIO.pending_packet() function), we stop NETSTACK_RADIO.pending_packet() function), we stop
snooping. */ snooping. */
#if !RDC_CONF_HARDWARE_CSMA
/* A cca cycle will disrupt rx on some radios, e.g. mc1322x, rf230 */
/*TODO: Modify those drivers to just return the internal RSSI when already in rx mode */
if(NETSTACK_RADIO.channel_clear()) { if(NETSTACK_RADIO.channel_clear()) {
++silence_periods; ++silence_periods;
} else { } else {
silence_periods = 0; silence_periods = 0;
} }
#endif
++periods; ++periods;
@ -407,8 +439,22 @@ powercycle(struct rtimer *t, void *ptr)
} }
if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - CHECK_TIME * 4)) { if(RTIMER_CLOCK_LT(RTIMER_NOW() - cycle_start, CYCLE_TIME - 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 */
#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));
} else {
sleepcycle = 0;
schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
PT_YIELD(&pt);
}
#else
schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start); schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
PT_YIELD(&pt); PT_YIELD(&pt);
#endif
} }
} }
@ -449,7 +495,6 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
uint8_t is_known_receiver = 0; uint8_t is_known_receiver = 0;
uint8_t collisions; uint8_t collisions;
int transmit_len; int transmit_len;
int i;
int ret; int ret;
uint8_t contikimac_was_on; uint8_t contikimac_was_on;
uint8_t seqno; uint8_t seqno;
@ -594,12 +639,17 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
contikimac_was_on = contikimac_is_on; contikimac_was_on = contikimac_is_on;
contikimac_is_on = 1; contikimac_is_on = 1;
if(is_receiver_awake == 0) { #if !RDC_CONF_HARDWARE_CSMA
/* Check if there are any transmissions by others. */ /* Check if there are any transmissions by others. */
/* TODO: why does this give collisions before sending with the mc1322x? */
if(is_receiver_awake == 0) {
int i;
for(i = 0; i < CCA_COUNT_MAX_TX; ++i) { for(i = 0; i < CCA_COUNT_MAX_TX; ++i) {
t0 = RTIMER_NOW(); t0 = RTIMER_NOW();
on(); on();
#if CCA_CHECK_TIME > 0
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { } while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + CCA_CHECK_TIME)) { }
#endif
if(NETSTACK_RADIO.channel_clear() == 0) { if(NETSTACK_RADIO.channel_clear() == 0) {
collisions++; collisions++;
off(); off();
@ -618,10 +668,15 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
contikimac_is_on = contikimac_was_on; contikimac_is_on = contikimac_was_on;
return MAC_TX_COLLISION; return MAC_TX_COLLISION;
} }
#endif /* RDC_CONF_HARDWARE_CSMA */
#if !RDC_CONF_HARDWARE_ACK
if(!is_broadcast) { if(!is_broadcast) {
on(); /* Turn radio on to receive expected unicast ack.
Not necessary with hardware ack detection, and may trigger an unnecessary cca or rx cycle */
on();
} }
#endif
watchdog_periodic(); watchdog_periodic();
t0 = RTIMER_NOW(); t0 = RTIMER_NOW();
@ -649,6 +704,23 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
txtime = RTIMER_NOW(); txtime = RTIMER_NOW();
ret = NETSTACK_RADIO.transmit(transmit_len); ret = NETSTACK_RADIO.transmit(transmit_len);
#if RDC_CONF_HARDWARE_ACK
/* For radios that block in the transmit routine and detect the ACK in hardware */
if(ret == RADIO_TX_OK) {
if(!is_broadcast) {
got_strobe_ack = 1;
encounter_time = previous_txtime;
break;
}
} else if (ret == RADIO_TX_NOACK) {
} else if (ret == RADIO_TX_COLLISION) {
PRINTF("contikimac: collisions while sending\n");
collisions++;
}
wt = RTIMER_NOW();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
#else
/* Wait for the ACK packet */
wt = RTIMER_NOW(); wt = RTIMER_NOW();
while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { } while(RTIMER_CLOCK_LT(RTIMER_NOW(), wt + INTER_PACKET_INTERVAL)) { }
@ -669,6 +741,8 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, struct rdc_buf_
collisions++; collisions++;
} }
} }
#endif /* RDC_CONF_HARDWARE_ACK */
previous_txtime = txtime; previous_txtime = txtime;
} }
} }
@ -743,12 +817,11 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list)
struct rdc_buf_list *next; struct rdc_buf_list *next;
int ret; int ret;
if(curr == NULL) { if(curr == NULL) {
mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1);
return; return;
} }
/* Do not send during reception of a burst */ /* Do not send during reception of a burst */
if(we_are_receiving_burst) { if(we_are_receiving_burst) {
/* Prepare the packetbuf for callback */
queuebuf_to_packetbuf(curr->buf);
/* Return COLLISION so the MAC may try again later */ /* Return COLLISION so the MAC may try again later */
mac_call_sent_callback(sent, ptr, MAC_TX_COLLISION, 1); mac_call_sent_callback(sent, ptr, MAC_TX_COLLISION, 1);
return; return;