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:
parent
3612fdff5b
commit
8e47694597
|
@ -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,9 +439,23 @@ 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);
|
schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
|
||||||
PT_YIELD(&pt);
|
PT_YIELD(&pt);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
schedule_powercycle_fixed(t, CYCLE_TIME + cycle_start);
|
||||||
|
PT_YIELD(&pt);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PT_END(&pt);
|
PT_END(&pt);
|
||||||
|
@ -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) {
|
||||||
|
/* Turn radio on to receive expected unicast ack.
|
||||||
|
Not necessary with hardware ack detection, and may trigger an unnecessary cca or rx cycle */
|
||||||
on();
|
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;
|
||||||
|
|
Loading…
Reference in a new issue