Reworked the locking code, which seems to fix a few bugs caused by the interaction with contikimac. Contikimac performs a CCA check in a preempting rtimer, which requires underlying code to properly call the GET_LOCK() macro. This fix seems to solve most problems, but there may be others left.

This commit is contained in:
adamdunkels 2010-03-14 22:45:20 +00:00
parent 3769a28516
commit 0035a70537
1 changed files with 57 additions and 45 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: cc2420.c,v 1.43 2010/03/09 15:45:29 joxe Exp $ * @(#)$Id: cc2420.c,v 1.44 2010/03/14 22:45:20 adamdunkels Exp $
*/ */
/* /*
* This code is almost device independent and should be easy to port. * This code is almost device independent and should be easy to port.
@ -184,7 +184,7 @@ static void
on(void) on(void)
{ {
ENERGEST_ON(ENERGEST_TYPE_LISTEN); ENERGEST_ON(ENERGEST_TYPE_LISTEN);
PRINTF("on\n"); /* PRINTF("on\n");*/
receive_on = 1; receive_on = 1;
ENABLE_FIFOP_INT(); ENABLE_FIFOP_INT();
@ -195,11 +195,11 @@ static void
off(void) off(void)
{ {
leds_on(LEDS_GREEN); leds_on(LEDS_GREEN);
PRINTF("off\n"); /* PRINTF("off\n");*/
receive_on = 0; receive_on = 0;
/* Wait for transmission to end before turning radio off. */ /* Wait for transmission to end before turning radio off. */
// while(status() & BV(CC2420_TX_ACTIVE)); while(status() & BV(CC2420_TX_ACTIVE));
strobe(CC2420_SRFOFF); strobe(CC2420_SRFOFF);
DISABLE_FIFOP_INT(); DISABLE_FIFOP_INT();
@ -207,17 +207,19 @@ off(void)
leds_off(LEDS_GREEN); leds_off(LEDS_GREEN);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define GET_LOCK() locked = 1 #define GET_LOCK() locked++
static void RELEASE_LOCK(void) { static void RELEASE_LOCK(void) {
if(lock_on) { if(locked == 1) {
on(); if(lock_on) {
lock_on = 0; on();
lock_on = 0;
}
if(lock_off) {
off();
lock_off = 0;
}
} }
if(lock_off) { locked--;
off();
lock_off = 0;
}
locked = 0;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static unsigned static unsigned
@ -355,6 +357,7 @@ cc2420_transmit(unsigned short payload_len)
/* SFD went high but we are not transmitting. This means that /* SFD went high but we are not transmitting. This means that
we just started receiving a packet, so we drop the we just started receiving a packet, so we drop the
transmission. */ transmission. */
RELEASE_LOCK();
return RADIO_TX_ERR; return RADIO_TX_ERR;
} }
if(receive_on) { if(receive_on) {
@ -453,20 +456,23 @@ cc2420_off(void)
/* If we are called when the driver is locked, we indicate that the /* If we are called when the driver is locked, we indicate that the
radio should be turned off when the lock is unlocked. */ radio should be turned off when the lock is unlocked. */
if(locked) { if(locked) {
/* printf("Off when locked (%d)\n", locked);*/
leds_on(LEDS_GREEN + LEDS_BLUE);
lock_off = 1; lock_off = 1;
return 1; return 1;
} }
GET_LOCK();
/* If we are currently receiving a packet (indicated by SFD == 1), /* If we are currently receiving a packet (indicated by SFD == 1),
we don't actually switch the radio off now, but signal that the we don't actually switch the radio off now, but signal that the
driver should switch off the radio once the packet has been driver should switch off the radio once the packet has been
received and processed, by setting the 'lock_off' variable. */ received and processed, by setting the 'lock_off' variable. */
if(status() & BV(CC2420_TX_ACTIVE)) { if(status() & BV(CC2420_TX_ACTIVE)) {
lock_off = 1; lock_off = 1;
return 1; } else {
off();
} }
RELEASE_LOCK();
off();
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -477,11 +483,14 @@ cc2420_on(void)
return 1; return 1;
} }
if(locked) { if(locked) {
leds_on(LEDS_GREEN + LEDS_RED);
lock_on = 1; lock_on = 1;
return 1; return 1;
} }
GET_LOCK();
on(); on();
RELEASE_LOCK();
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -495,11 +504,12 @@ void
cc2420_set_channel(int c) cc2420_set_channel(int c)
{ {
uint16_t f; uint16_t f;
GET_LOCK();
/* /*
* Subtract the base channel (11), multiply by 5, which is the * Subtract the base channel (11), multiply by 5, which is the
* channel spacing. 357 is 2405-2048 and 0x4000 is LOCK_THR = 1. * channel spacing. 357 is 2405-2048 and 0x4000 is LOCK_THR = 1.
*/ */
channel = c; channel = c;
f = 5 * (c - 11) + 357 + 0x4000; f = 5 * (c - 11) + 357 + 0x4000;
@ -519,6 +529,7 @@ cc2420_set_channel(int c)
strobe(CC2420_SRXON); strobe(CC2420_SRXON);
} }
RELEASE_LOCK();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -528,6 +539,9 @@ cc2420_set_pan_addr(unsigned pan,
{ {
uint16_t f = 0; uint16_t f = 0;
uint8_t tmp[2]; uint8_t tmp[2];
GET_LOCK();
/* /*
* Writing RAM requires crystal oscillator to be stable. * Writing RAM requires crystal oscillator to be stable.
*/ */
@ -548,6 +562,7 @@ cc2420_set_pan_addr(unsigned pan,
} }
FASTSPI_WRITE_RAM_LE(tmp_addr, CC2420RAM_IEEEADDR, 8, f); FASTSPI_WRITE_RAM_LE(tmp_addr, CC2420RAM_IEEEADDR, 8, f);
} }
RELEASE_LOCK();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
@ -616,16 +631,16 @@ cc2420_read(void *buf, unsigned short bufsize)
#endif /* CC2420_CONF_CHECKSUM */ #endif /* CC2420_CONF_CHECKSUM */
pending = 0; pending = 0;
if(!FIFOP_IS_1) { if(!FIFOP_IS_1) {
/* If FIFOP is 0, there is no packet in the RXFIFO. */ /* If FIFOP is 0, there is no packet in the RXFIFO. */
return 0; return 0;
} }
GET_LOCK(); GET_LOCK();
cc2420_packets_read++; cc2420_packets_read++;
getrxbyte(&len); getrxbyte(&len);
if(len > CC2420_MAX_PACKET_LEN) { if(len > CC2420_MAX_PACKET_LEN) {
@ -713,7 +728,11 @@ cc2420_set_txpower(uint8_t power)
int int
cc2420_get_txpower(void) cc2420_get_txpower(void)
{ {
return (int)(getreg(CC2420_TXCTRL) & 0x001f); int power;
GET_LOCK();
power = (int)(getreg(CC2420_TXCTRL) & 0x001f);
RELEASE_LOCK();
return power;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
@ -722,6 +741,8 @@ cc2420_rssi(void)
int rssi; int rssi;
int radio_was_off = 0; int radio_was_off = 0;
GET_LOCK();
if(!receive_on) { if(!receive_on) {
radio_was_off = 1; radio_was_off = 1;
cc2420_on(); cc2420_on();
@ -735,13 +756,21 @@ cc2420_rssi(void)
if(radio_was_off) { if(radio_was_off) {
cc2420_off(); cc2420_off();
} }
RELEASE_LOCK();
return rssi; return rssi;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
cc2420_cca_valid(void) cc2420_cca_valid(void)
{ {
return !!(status() & BV(CC2420_RSSI_VALID)); int valid;
if(locked) {
return 1;
}
GET_LOCK();
valid = !!(status() & BV(CC2420_RSSI_VALID));
RELEASE_LOCK();
return valid;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static int
@ -757,7 +786,8 @@ cc2420_cca(void)
if(locked) { if(locked) {
return 1; return 1;
} }
GET_LOCK();
if(!receive_on) { if(!receive_on) {
radio_was_off = 1; radio_was_off = 1;
cc2420_on(); cc2420_on();
@ -765,6 +795,7 @@ cc2420_cca(void)
/* Make sure that the radio really got turned on. */ /* Make sure that the radio really got turned on. */
if(!receive_on) { if(!receive_on) {
RELEASE_LOCK();
return 1; return 1;
} }
@ -777,6 +808,7 @@ cc2420_cca(void)
if(radio_was_off) { if(radio_was_off) {
cc2420_off(); cc2420_off();
} }
RELEASE_LOCK();
return cca; return cca;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -793,31 +825,11 @@ pending_packet(void)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
cc2420_ugly_hack_send_only_one_symbol(void)
{
uint8_t len;
GET_LOCK();
/* Write packet to TX FIFO. */
strobe(CC2420_SFLUSHTX);
len = 1;
FASTSPI_WRITE_FIFO(&len, 1);
FASTSPI_WRITE_FIFO(&len, 1);
strobe(CC2420_STXON);
while(!SFD_IS_1);
/* Turn radio off immediately after sending the first symbol. */
strobe(CC2420_SRFOFF);
RELEASE_LOCK();
return;
}
/*---------------------------------------------------------------------------*/
void
cc2420_set_cca_threshold(int value) cc2420_set_cca_threshold(int value)
{ {
uint16_t shifted = value << 8; uint16_t shifted = value << 8;
GET_LOCK();
setreg(CC2420_RSSI, shifted); setreg(CC2420_RSSI, shifted);
RELEASE_LOCK();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/