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

View file

@ -28,7 +28,7 @@
*
* 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.
@ -184,7 +184,7 @@ static void
on(void)
{
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
PRINTF("on\n");
/* PRINTF("on\n");*/
receive_on = 1;
ENABLE_FIFOP_INT();
@ -195,11 +195,11 @@ static void
off(void)
{
leds_on(LEDS_GREEN);
PRINTF("off\n");
/* PRINTF("off\n");*/
receive_on = 0;
/* Wait for transmission to end before turning radio off. */
// while(status() & BV(CC2420_TX_ACTIVE));
while(status() & BV(CC2420_TX_ACTIVE));
strobe(CC2420_SRFOFF);
DISABLE_FIFOP_INT();
@ -207,17 +207,19 @@ off(void)
leds_off(LEDS_GREEN);
}
/*---------------------------------------------------------------------------*/
#define GET_LOCK() locked = 1
#define GET_LOCK() locked++
static void RELEASE_LOCK(void) {
if(lock_on) {
on();
lock_on = 0;
if(locked == 1) {
if(lock_on) {
on();
lock_on = 0;
}
if(lock_off) {
off();
lock_off = 0;
}
}
if(lock_off) {
off();
lock_off = 0;
}
locked = 0;
locked--;
}
/*---------------------------------------------------------------------------*/
static unsigned
@ -355,6 +357,7 @@ cc2420_transmit(unsigned short payload_len)
/* SFD went high but we are not transmitting. This means that
we just started receiving a packet, so we drop the
transmission. */
RELEASE_LOCK();
return RADIO_TX_ERR;
}
if(receive_on) {
@ -453,20 +456,23 @@ cc2420_off(void)
/* If we are called when the driver is locked, we indicate that the
radio should be turned off when the lock is unlocked. */
if(locked) {
/* printf("Off when locked (%d)\n", locked);*/
leds_on(LEDS_GREEN + LEDS_BLUE);
lock_off = 1;
return 1;
}
GET_LOCK();
/* If we are currently receiving a packet (indicated by SFD == 1),
we don't actually switch the radio off now, but signal that the
driver should switch off the radio once the packet has been
received and processed, by setting the 'lock_off' variable. */
if(status() & BV(CC2420_TX_ACTIVE)) {
lock_off = 1;
return 1;
} else {
off();
}
off();
RELEASE_LOCK();
return 1;
}
/*---------------------------------------------------------------------------*/
@ -477,11 +483,14 @@ cc2420_on(void)
return 1;
}
if(locked) {
leds_on(LEDS_GREEN + LEDS_RED);
lock_on = 1;
return 1;
}
GET_LOCK();
on();
RELEASE_LOCK();
return 1;
}
/*---------------------------------------------------------------------------*/
@ -495,11 +504,12 @@ void
cc2420_set_channel(int c)
{
uint16_t f;
GET_LOCK();
/*
* Subtract the base channel (11), multiply by 5, which is the
* channel spacing. 357 is 2405-2048 and 0x4000 is LOCK_THR = 1.
*/
channel = c;
f = 5 * (c - 11) + 357 + 0x4000;
@ -519,6 +529,7 @@ cc2420_set_channel(int c)
strobe(CC2420_SRXON);
}
RELEASE_LOCK();
}
/*---------------------------------------------------------------------------*/
void
@ -528,6 +539,9 @@ cc2420_set_pan_addr(unsigned pan,
{
uint16_t f = 0;
uint8_t tmp[2];
GET_LOCK();
/*
* 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);
}
RELEASE_LOCK();
}
/*---------------------------------------------------------------------------*/
/*
@ -713,7 +728,11 @@ cc2420_set_txpower(uint8_t power)
int
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
@ -722,6 +741,8 @@ cc2420_rssi(void)
int rssi;
int radio_was_off = 0;
GET_LOCK();
if(!receive_on) {
radio_was_off = 1;
cc2420_on();
@ -735,13 +756,21 @@ cc2420_rssi(void)
if(radio_was_off) {
cc2420_off();
}
RELEASE_LOCK();
return rssi;
}
/*---------------------------------------------------------------------------*/
int
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
@ -758,6 +787,7 @@ cc2420_cca(void)
return 1;
}
GET_LOCK();
if(!receive_on) {
radio_was_off = 1;
cc2420_on();
@ -765,6 +795,7 @@ cc2420_cca(void)
/* Make sure that the radio really got turned on. */
if(!receive_on) {
RELEASE_LOCK();
return 1;
}
@ -777,6 +808,7 @@ cc2420_cca(void)
if(radio_was_off) {
cc2420_off();
}
RELEASE_LOCK();
return cca;
}
/*---------------------------------------------------------------------------*/
@ -793,31 +825,11 @@ pending_packet(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)
{
uint16_t shifted = value << 8;
GET_LOCK();
setreg(CC2420_RSSI, shifted);
RELEASE_LOCK();
}
/*---------------------------------------------------------------------------*/