A work-in-progress rework of the Contiki MAC and radio layers. The
main ideas are: * Separates the Contiki low-layer network stack into four layers: network (e.g. sicslowpan / rime), Medium Access Control MAC (e.g. CSMA), Radio Duty Cycling RDC (e.g. ContikiMAC, X-MAC), and radio (e.g. cc2420). * Introduces a new way to configure the network stack. Four #defines that specify what mechanism/protocol/driver to use at the four layers: NETSTACK_CONF_NETWORK, NETSTACK_CONF_MAC, NETSTACK_CONF_RDC, NETSTACK_CONF_RADIO. * Adds a callback mechanism to inform the MAC and network layers about the fate of a transmitted packet: if the packet was not possible to transmit, the cause of the failure is reported, and if the packets was successfully transmitted, the number of tries before it was finally transmitted is reported. * NULL-protocols at both the MAC and RDC layers: nullmac and nullrdc, which can be used when MAC and RDC functionality is not needed. * Extends the radio API with three new functions that enable more efficient radio duty cycling protocols: channel check, pending packet, and receiving packet. * New initialization mechanism, which takes advantage of the NETSTACK #defines.
This commit is contained in:
parent
1817acae15
commit
e34eb54960
29 changed files with 1176 additions and 768 deletions
|
@ -28,7 +28,7 @@
|
|||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* @(#)$Id: cc2420.c,v 1.37 2010/01/14 23:32:05 adamdunkels Exp $
|
||||
* @(#)$Id: cc2420.c,v 1.38 2010/02/18 21:48:39 adamdunkels Exp $
|
||||
*/
|
||||
/*
|
||||
* This code is almost device independent and should be easy to port.
|
||||
|
@ -52,11 +52,13 @@
|
|||
|
||||
#include "net/rime/packetbuf.h"
|
||||
#include "net/rime/rimestats.h"
|
||||
#include "net/netstack.h"
|
||||
|
||||
#include "sys/timetable.h"
|
||||
|
||||
#define WITH_SEND_CCA 0
|
||||
|
||||
#include "cc2420-arch-sfd.h"
|
||||
|
||||
#if CC2420_CONF_TIMESTAMPS
|
||||
#include "net/rime/timesynch.h"
|
||||
|
@ -112,30 +114,41 @@ static unsigned long total_time_for_transmission, total_transmission_len;
|
|||
static int num_transmissions;
|
||||
#endif /* CC2420_CONF_TIMESTAMPS */
|
||||
|
||||
int cc2420_packets_seen, cc2420_packets_read;
|
||||
|
||||
static uint8_t volatile pending;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS(cc2420_process, "CC2420 driver");
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static void (* receiver_callback)(const struct radio_driver *);
|
||||
|
||||
int cc2420_on(void);
|
||||
int cc2420_off(void);
|
||||
|
||||
int cc2420_read(void *buf, unsigned short bufsize);
|
||||
static int cc2420_read(void *buf, unsigned short bufsize);
|
||||
|
||||
int cc2420_send(const void *data, unsigned short len);
|
||||
|
||||
void cc2420_set_receiver(void (* recv)(const struct radio_driver *d));
|
||||
static int cc2420_prepare(const void *data, unsigned short len);
|
||||
static int cc2420_transmit(unsigned short len);
|
||||
static int cc2420_send(const void *data, unsigned short len);
|
||||
|
||||
static int cc2420_receiving_packet(void);
|
||||
static int pending_packet(void);
|
||||
static int cc2420_cca(void);
|
||||
|
||||
signed char cc2420_last_rssi;
|
||||
uint8_t cc2420_last_correlation;
|
||||
|
||||
const struct radio_driver cc2420_driver =
|
||||
{
|
||||
cc2420_init,
|
||||
cc2420_prepare,
|
||||
cc2420_transmit,
|
||||
cc2420_send,
|
||||
cc2420_read,
|
||||
cc2420_set_receiver,
|
||||
cc2420_cca,
|
||||
cc2420_receiving_packet,
|
||||
pending_packet,
|
||||
cc2420_on,
|
||||
cc2420_off,
|
||||
};
|
||||
|
@ -257,13 +270,7 @@ set_txpower(uint8_t power)
|
|||
#define FIFOP_THR(n) ((n) & 0x7f)
|
||||
#define RXBPF_LOCUR (1 << 13);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
cc2420_set_receiver(void (* recv)(const struct radio_driver *))
|
||||
{
|
||||
receiver_callback = recv;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
int
|
||||
cc2420_init(void)
|
||||
{
|
||||
uint16_t reg;
|
||||
|
@ -315,10 +322,11 @@ cc2420_init(void)
|
|||
cc2420_set_channel(26);
|
||||
|
||||
process_start(&cc2420_process, NULL);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
cc2420_send(const void *payload, unsigned short payload_len)
|
||||
static int
|
||||
cc2420_transmit(unsigned short payload_len)
|
||||
{
|
||||
int i, txpower;
|
||||
uint8_t total_len;
|
||||
|
@ -328,6 +336,7 @@ cc2420_send(const void *payload, unsigned short payload_len)
|
|||
#if CC2420_CONF_CHECKSUM
|
||||
uint16_t checksum;
|
||||
#endif /* CC2420_CONF_CHECKSUM */
|
||||
|
||||
GET_LOCK();
|
||||
|
||||
txpower = 0;
|
||||
|
@ -338,32 +347,8 @@ cc2420_send(const void *payload, unsigned short payload_len)
|
|||
set_txpower(packetbuf_attr(PACKETBUF_ATTR_RADIO_TXPOWER) - 1);
|
||||
}
|
||||
|
||||
PRINTF("cc2420: sending %d bytes\n", payload_len);
|
||||
|
||||
RIMESTATS_ADD(lltx);
|
||||
|
||||
/* Wait for any previous transmission to finish. */
|
||||
while(status() & BV(CC2420_TX_ACTIVE));
|
||||
|
||||
/* Write packet to TX FIFO. */
|
||||
strobe(CC2420_SFLUSHTX);
|
||||
|
||||
#if CC2420_CONF_CHECKSUM
|
||||
checksum = crc16_data(payload, payload_len, 0);
|
||||
#endif /* CC2420_CONF_CHECKSUM */
|
||||
total_len = payload_len + AUX_LEN;
|
||||
FASTSPI_WRITE_FIFO(&total_len, 1);
|
||||
FASTSPI_WRITE_FIFO(payload, payload_len);
|
||||
#if CC2420_CONF_CHECKSUM
|
||||
FASTSPI_WRITE_FIFO(&checksum, CHECKSUM_LEN);
|
||||
#endif /* CC2420_CONF_CHECKSUM */
|
||||
|
||||
#if CC2420_CONF_TIMESTAMPS
|
||||
timestamp.authority_level = timesynch_authority_level();
|
||||
timestamp.time = timesynch_time();
|
||||
FASTSPI_WRITE_FIFO(×tamp, TIMESTAMP_LEN);
|
||||
#endif /* CC2420_CONF_TIMESTAMPS */
|
||||
|
||||
|
||||
/* The TX FIFO can only hold one packet. Make sure to not overrun
|
||||
* FIFO by waiting for transmission to start here and synchronizing
|
||||
* with the CC2420_TX_ACTIVE check in cc2420_send.
|
||||
|
@ -387,12 +372,6 @@ cc2420_send(const void *payload, unsigned short payload_len)
|
|||
|
||||
for(i = LOOP_20_SYMBOLS; i > 0; i--) {
|
||||
if(SFD_IS_1) {
|
||||
if(!(status() & BV(CC2420_TX_ACTIVE))) {
|
||||
/* SFD went high yet we are not transmitting!
|
||||
* => We started receiving a packet right now */
|
||||
return RADIO_TX_ERR;
|
||||
}
|
||||
|
||||
#if CC2420_CONF_TIMESTAMPS
|
||||
rtimer_clock_t txtime = timesynch_time();
|
||||
#endif /* CC2420_CONF_TIMESTAMPS */
|
||||
|
@ -435,7 +414,7 @@ cc2420_send(const void *payload, unsigned short payload_len)
|
|||
}
|
||||
|
||||
RELEASE_LOCK();
|
||||
return RADIO_TX_OK;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,7 +429,56 @@ cc2420_send(const void *payload, unsigned short payload_len)
|
|||
}
|
||||
|
||||
RELEASE_LOCK();
|
||||
return RADIO_TX_ERR; /* Transmission never started! */
|
||||
return -3; /* Transmission never started! */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
cc2420_prepare(const void *payload, unsigned short payload_len)
|
||||
{
|
||||
uint8_t total_len;
|
||||
#if CC2420_CONF_TIMESTAMPS
|
||||
struct timestamp timestamp;
|
||||
#endif /* CC2420_CONF_TIMESTAMPS */
|
||||
#if CC2420_CONF_CHECKSUM
|
||||
uint16_t checksum;
|
||||
#endif /* CC2420_CONF_CHECKSUM */
|
||||
GET_LOCK();
|
||||
|
||||
PRINTF("cc2420: sending %d bytes\n", payload_len);
|
||||
|
||||
RIMESTATS_ADD(lltx);
|
||||
|
||||
/* Wait for any previous transmission to finish. */
|
||||
while(status() & BV(CC2420_TX_ACTIVE));
|
||||
|
||||
/* Write packet to TX FIFO. */
|
||||
strobe(CC2420_SFLUSHTX);
|
||||
|
||||
#if CC2420_CONF_CHECKSUM
|
||||
checksum = crc16_data(payload, payload_len, 0);
|
||||
#endif /* CC2420_CONF_CHECKSUM */
|
||||
total_len = payload_len + AUX_LEN;
|
||||
FASTSPI_WRITE_FIFO(&total_len, 1);
|
||||
FASTSPI_WRITE_FIFO(payload, payload_len);
|
||||
#if CC2420_CONF_CHECKSUM
|
||||
FASTSPI_WRITE_FIFO(&checksum, CHECKSUM_LEN);
|
||||
#endif /* CC2420_CONF_CHECKSUM */
|
||||
|
||||
#if CC2420_CONF_TIMESTAMPS
|
||||
timestamp.authority_level = timesynch_authority_level();
|
||||
timestamp.time = timesynch_time();
|
||||
FASTSPI_WRITE_FIFO(×tamp, TIMESTAMP_LEN);
|
||||
#endif /* CC2420_CONF_TIMESTAMPS */
|
||||
|
||||
RELEASE_LOCK();
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
cc2420_send(const void *payload, unsigned short payload_len)
|
||||
{
|
||||
cc2420_prepare(payload, payload_len);
|
||||
return cc2420_transmit(payload_len);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
|
@ -534,8 +562,8 @@ cc2420_set_channel(int c)
|
|||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
cc2420_set_pan_addr(unsigned pan,
|
||||
unsigned addr,
|
||||
const uint8_t *ieee_addr)
|
||||
unsigned addr,
|
||||
const uint8_t *ieee_addr)
|
||||
{
|
||||
uint16_t f = 0;
|
||||
/*
|
||||
|
@ -572,10 +600,8 @@ int
|
|||
cc2420_interrupt(void)
|
||||
{
|
||||
#if CC2420_CONF_TIMESTAMPS
|
||||
if(!interrupt_time_set) {
|
||||
interrupt_time = timesynch_time();
|
||||
interrupt_time_set = 1;
|
||||
}
|
||||
interrupt_time = timesynch_time();
|
||||
interrupt_time_set = 1;
|
||||
#endif /* CC2420_CONF_TIMESTAMPS */
|
||||
|
||||
CLEAR_FIFOP_INT();
|
||||
|
@ -584,11 +610,16 @@ cc2420_interrupt(void)
|
|||
timetable_clear(&cc2420_timetable);
|
||||
TIMETABLE_TIMESTAMP(cc2420_timetable, "interrupt");
|
||||
#endif /* CC2420_TIMETABLE_PROFILING */
|
||||
|
||||
pending = 1;
|
||||
|
||||
cc2420_packets_seen++;
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
PROCESS_THREAD(cc2420_process, ev, data)
|
||||
{
|
||||
int len;
|
||||
PROCESS_BEGIN();
|
||||
|
||||
PRINTF("cc2420_process: started\n");
|
||||
|
@ -599,25 +630,28 @@ PROCESS_THREAD(cc2420_process, ev, data)
|
|||
TIMETABLE_TIMESTAMP(cc2420_timetable, "poll");
|
||||
#endif /* CC2420_TIMETABLE_PROFILING */
|
||||
|
||||
if(receiver_callback != NULL) {
|
||||
PRINTF("cc2420_process: calling receiver callback\n");
|
||||
receiver_callback(&cc2420_driver);
|
||||
pending = 0;
|
||||
|
||||
PRINTF("cc2420_process: calling receiver callback\n");
|
||||
|
||||
packetbuf_clear();
|
||||
len = cc2420_read(packetbuf_dataptr(), PACKETBUF_SIZE);
|
||||
if(len > 0) {
|
||||
packetbuf_set_datalen(len);
|
||||
NETSTACK_RDC.input();
|
||||
#if CC2420_TIMETABLE_PROFILING
|
||||
TIMETABLE_TIMESTAMP(cc2420_timetable, "end");
|
||||
timetable_aggregate_compute_detailed(&aggregate_time,
|
||||
&cc2420_timetable);
|
||||
&cc2420_timetable);
|
||||
timetable_clear(&cc2420_timetable);
|
||||
#endif /* CC2420_TIMETABLE_PROFILING */
|
||||
} else {
|
||||
PRINTF("cc2420_process not receiving function\n");
|
||||
flushrx();
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_END();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
static int
|
||||
cc2420_read(void *buf, unsigned short bufsize)
|
||||
{
|
||||
uint8_t footer[2];
|
||||
|
@ -630,12 +664,23 @@ cc2420_read(void *buf, unsigned short bufsize)
|
|||
#endif /* CC2420_CONF_TIMESTAMPS */
|
||||
|
||||
if(!FIFOP_IS_1) {
|
||||
/* If FIFO is 0, there is no packet in the RXFIFO. */
|
||||
/* If FIFOP is 0, there is no packet in the RXFIFO. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CC2420_CONF_TIMESTAMPS
|
||||
if(interrupt_time_set) {
|
||||
cc2420_time_of_arrival = interrupt_time;
|
||||
interrupt_time_set = 0;
|
||||
} else {
|
||||
cc2420_time_of_arrival = 0;
|
||||
}
|
||||
cc2420_time_of_departure = 0;
|
||||
#endif /* CC2420_CONF_TIMESTAMPS */
|
||||
GET_LOCK();
|
||||
|
||||
cc2420_packets_read++;
|
||||
|
||||
getrxbyte(&len);
|
||||
|
||||
if(len > CC2420_MAX_PACKET_LEN) {
|
||||
|
@ -647,6 +692,7 @@ cc2420_read(void *buf, unsigned short bufsize)
|
|||
}
|
||||
|
||||
if(len <= AUX_LEN) {
|
||||
printf("len <= AUX_LEN\n");
|
||||
flushrx();
|
||||
RIMESTATS_ADD(tooshort);
|
||||
RELEASE_LOCK();
|
||||
|
@ -654,6 +700,7 @@ cc2420_read(void *buf, unsigned short bufsize)
|
|||
}
|
||||
|
||||
if(len - AUX_LEN > bufsize) {
|
||||
printf("len - AUX_LEN > bufsize\n");
|
||||
flushrx();
|
||||
RIMESTATS_ADD(toolong);
|
||||
RELEASE_LOCK();
|
||||
|
@ -690,19 +737,12 @@ cc2420_read(void *buf, unsigned short bufsize)
|
|||
RIMESTATS_ADD(llrx);
|
||||
|
||||
#if CC2420_CONF_TIMESTAMPS
|
||||
if(interrupt_time_set) {
|
||||
cc2420_time_of_arrival = interrupt_time;
|
||||
cc2420_time_of_departure =
|
||||
t.time +
|
||||
setup_time_for_transmission +
|
||||
(total_time_for_transmission * (len - 2)) / total_transmission_len;
|
||||
|
||||
cc2420_authority_level_of_sender = t.authority_level;
|
||||
interrupt_time_set = 0;
|
||||
} else {
|
||||
/* Bypass timesynch */
|
||||
cc2420_authority_level_of_sender = timesynch_authority_level();
|
||||
}
|
||||
cc2420_time_of_departure =
|
||||
t.time +
|
||||
setup_time_for_transmission +
|
||||
(total_time_for_transmission * (len - 2)) / total_transmission_len;
|
||||
|
||||
cc2420_authority_level_of_sender = t.authority_level;
|
||||
|
||||
packetbuf_set_attr(PACKETBUF_ATTR_TIMESTAMP, t.time);
|
||||
#endif /* CC2420_CONF_TIMESTAMPS */
|
||||
|
@ -720,6 +760,7 @@ cc2420_read(void *buf, unsigned short bufsize)
|
|||
flushrx();
|
||||
} else if(FIFOP_IS_1) {
|
||||
/* Another packet has been received and needs attention. */
|
||||
/* printf("attention\n");*/
|
||||
process_poll(&cc2420_process);
|
||||
}
|
||||
|
||||
|
@ -768,3 +809,67 @@ cc2420_rssi(void)
|
|||
return rssi;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
cc2420_cca(void)
|
||||
{
|
||||
int cca;
|
||||
int radio_was_off = 0;
|
||||
|
||||
/* If the radio is locked by an underlying thread (because we are
|
||||
being invoked through an interrupt), we preted that the coast is
|
||||
clear (i.e., no packet is currently being transmitted by a
|
||||
neighbor). */
|
||||
if(locked) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!receive_on) {
|
||||
radio_was_off = 1;
|
||||
cc2420_on();
|
||||
}
|
||||
while(!(status() & BV(CC2420_RSSI_VALID))) {
|
||||
/* printf("cc2420_rssi: RSSI not valid.\n"); */
|
||||
}
|
||||
|
||||
cca = CCA_IS_1;
|
||||
|
||||
if(radio_was_off) {
|
||||
cc2420_off();
|
||||
}
|
||||
return cca;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
cc2420_receiving_packet(void)
|
||||
{
|
||||
return SFD_IS_1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int
|
||||
pending_packet(void)
|
||||
{
|
||||
return pending;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
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;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue