Merge pull request #684 from kkrentz/cc2538-pr

Improvements to cc2538-rf.c
This commit is contained in:
George Oikonomou 2018-10-02 17:23:20 +01:00 committed by GitHub
commit 710019877e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 72 deletions

View File

@ -68,13 +68,10 @@
*/ */
#define UDMA_RX_SIZE_THRESHOLD 3 #define UDMA_RX_SIZE_THRESHOLD 3
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#include <stdio.h> /* Log configuration */
#define DEBUG 0 #include "sys/log.h"
#if DEBUG #define LOG_MODULE "cc2538-rf"
#define PRINTF(...) printf(__VA_ARGS__) #define LOG_LEVEL LOG_LEVEL_NONE
#else
#define PRINTF(...)
#endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Local RF Flags */ /* Local RF Flags */
#define RX_ACTIVE 0x80 #define RX_ACTIVE 0x80
@ -86,6 +83,7 @@
#define LQI_BIT_MASK 0x7F #define LQI_BIT_MASK 0x7F
/* RSSI Offset */ /* RSSI Offset */
#define RSSI_OFFSET 73 #define RSSI_OFFSET 73
#define RSSI_INVALID -128
/* 192 usec off -> on interval (RX Callib -> SFD Wait). We wait a bit more */ /* 192 usec off -> on interval (RX Callib -> SFD Wait). We wait a bit more */
#define ONOFF_TIME RTIMER_ARCH_SECOND / 3125 #define ONOFF_TIME RTIMER_ARCH_SECOND / 3125
@ -156,28 +154,19 @@ PROCESS(cc2538_rf_process, "cc2538 RF driver");
static uint8_t static uint8_t
get_channel() get_channel()
{ {
uint8_t chan = REG(RFCORE_XREG_FREQCTRL) & RFCORE_XREG_FREQCTRL_FREQ; return rf_channel;
return (chan - CC2538_RF_CHANNEL_MIN) / CC2538_RF_CHANNEL_SPACING
+ CC2538_RF_CHANNEL_MIN;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* \brief Set the current operating channel * \brief Set the current operating channel
* \param channel The desired channel as a value in [11,26] * \param channel The desired channel as a value in [11,26]
* \return Returns a value in [11,26] representing the current channel
* or a negative value if \e channel was out of bounds
*/ */
static int8_t static void
set_channel(uint8_t channel) set_channel(uint8_t channel)
{ {
uint8_t was_on = 0; uint8_t was_on = 0;
PRINTF("RF: Set Channel\n"); LOG_INFO("Set Channel\n");
if((channel < CC2538_RF_CHANNEL_MIN) || (channel > CC2538_RF_CHANNEL_MAX)) {
return CC2538_RF_CHANNEL_SET_ERROR;
}
/* Changes to FREQCTRL take effect after the next recalibration */ /* Changes to FREQCTRL take effect after the next recalibration */
@ -195,8 +184,6 @@ set_channel(uint8_t channel)
} }
rf_channel = channel; rf_channel = channel;
return (int8_t)channel;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static radio_value_t static radio_value_t
@ -244,10 +231,11 @@ get_rssi(void)
on(); on();
} }
/* Wait on RSSI_VALID */ /* Wait for a valid RSSI reading */
while((REG(RFCORE_XREG_RSSISTAT) & RFCORE_XREG_RSSISTAT_RSSI_VALID) == 0); do {
rssi = REG(RFCORE_XREG_RSSI);
rssi = (int8_t)(REG(RFCORE_XREG_RSSI) & RFCORE_XREG_RSSI_RSSI_VAL) - RSSI_OFFSET; } while(rssi == RSSI_INVALID);
rssi -= RSSI_OFFSET;
/* If we were off, turn back off */ /* If we were off, turn back off */
if(was_off) { if(was_off) {
@ -322,6 +310,16 @@ set_frame_filtering(uint8_t enable)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
set_shr_search(int enable)
{
if(enable) {
REG(RFCORE_XREG_FRMCTRL0) &= ~RFCORE_XREG_FRMCTRL0_RX_MODE;
} else {
REG(RFCORE_XREG_FRMCTRL0) |= RFCORE_XREG_FRMCTRL0_RX_MODE;
}
}
/*---------------------------------------------------------------------------*/
static void
mac_timer_init(void) mac_timer_init(void)
{ {
CLOCK_STABLE(); CLOCK_STABLE();
@ -403,7 +401,7 @@ channel_clear(void)
int cca; int cca;
uint8_t was_off = 0; uint8_t was_off = 0;
PRINTF("RF: CCA\n"); LOG_INFO("CCA\n");
/* If we are off, turn on first */ /* If we are off, turn on first */
if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) {
@ -431,7 +429,7 @@ channel_clear(void)
static int static int
on(void) on(void)
{ {
PRINTF("RF: On\n"); LOG_INFO("On\n");
if(!(rf_flags & RX_ACTIVE)) { if(!(rf_flags & RX_ACTIVE)) {
CC2538_RF_CSP_ISFLUSHRX(); CC2538_RF_CSP_ISFLUSHRX();
@ -447,7 +445,7 @@ on(void)
static int static int
off(void) off(void)
{ {
PRINTF("RF: Off\n"); LOG_INFO("Off\n");
/* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */ /* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */
while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
@ -470,7 +468,7 @@ off(void)
static int static int
init(void) init(void)
{ {
PRINTF("RF: Init\n"); LOG_INFO("Init\n");
if(rf_flags & RF_ON) { if(rf_flags & RF_ON) {
return 0; return 0;
@ -490,6 +488,7 @@ init(void)
REG(RFCORE_XREG_TXFILTCFG) = 0x09; /** TX anti-aliasing filter bandwidth */ REG(RFCORE_XREG_TXFILTCFG) = 0x09; /** TX anti-aliasing filter bandwidth */
REG(RFCORE_XREG_AGCCTRL1) = 0x15; /** AGC target value */ REG(RFCORE_XREG_AGCCTRL1) = 0x15; /** AGC target value */
REG(ANA_REGS_IVCTRL) = 0x0B; /** Bias currents */ REG(ANA_REGS_IVCTRL) = 0x0B; /** Bias currents */
REG(RFCORE_XREG_FSCAL1) = 0x01; /** Tune frequency calibration */
/* /*
* Defaults: * Defaults:
@ -513,6 +512,9 @@ init(void)
set_channel(rf_channel); set_channel(rf_channel);
/* Enable SHR search */
set_shr_search(1);
/* Acknowledge all RF Error interrupts */ /* Acknowledge all RF Error interrupts */
REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM; REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM;
NVIC_EnableIRQ(RF_ERR_IRQn); NVIC_EnableIRQ(RF_ERR_IRQn);
@ -545,8 +547,6 @@ init(void)
rf_flags |= RF_ON; rf_flags |= RF_ON;
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
return 1; return 1;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -555,7 +555,7 @@ prepare(const void *payload, unsigned short payload_len)
{ {
uint8_t i; uint8_t i;
PRINTF("RF: Prepare 0x%02x bytes\n", payload_len + CHECKSUM_LEN); LOG_INFO("Prepare 0x%02x bytes\n", payload_len + CHECKSUM_LEN);
/* /*
* When we transmit in very quick bursts, make sure previous transmission * When we transmit in very quick bursts, make sure previous transmission
@ -569,12 +569,12 @@ prepare(const void *payload, unsigned short payload_len)
CC2538_RF_CSP_ISFLUSHTX(); CC2538_RF_CSP_ISFLUSHTX();
PRINTF("RF: data = "); LOG_INFO("data = ");
/* Send the phy length byte first */ /* Send the phy length byte first */
REG(RFCORE_SFR_RFDATA) = payload_len + CHECKSUM_LEN; REG(RFCORE_SFR_RFDATA) = payload_len + CHECKSUM_LEN;
if(CC2538_RF_CONF_TX_USE_DMA) { if(CC2538_RF_CONF_TX_USE_DMA) {
PRINTF("<uDMA payload>"); LOG_INFO_("<uDMA payload>");
/* Set the transfer source's end address */ /* Set the transfer source's end address */
udma_set_channel_src(CC2538_RF_CONF_TX_DMA_CHAN, udma_set_channel_src(CC2538_RF_CONF_TX_DMA_CHAN,
@ -598,10 +598,10 @@ prepare(const void *payload, unsigned short payload_len)
} else { } else {
for(i = 0; i < payload_len; i++) { for(i = 0; i < payload_len; i++) {
REG(RFCORE_SFR_RFDATA) = ((unsigned char *)(payload))[i]; REG(RFCORE_SFR_RFDATA) = ((unsigned char *)(payload))[i];
PRINTF("%02x", ((unsigned char *)(payload))[i]); LOG_INFO_("%02x", ((unsigned char *)(payload))[i]);
} }
} }
PRINTF("\n"); LOG_INFO_("\n");
return 0; return 0;
} }
@ -614,7 +614,7 @@ transmit(unsigned short transmit_len)
rtimer_clock_t t0; rtimer_clock_t t0;
uint8_t was_off = 0; uint8_t was_off = 0;
PRINTF("RF: Transmit\n"); LOG_INFO("Transmit\n");
if(!(rf_flags & RX_ACTIVE)) { if(!(rf_flags & RX_ACTIVE)) {
t0 = RTIMER_NOW(); t0 = RTIMER_NOW();
@ -649,7 +649,7 @@ transmit(unsigned short transmit_len)
} }
if(!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE)) { if(!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE)) {
PRINTF("RF: TX never active.\n"); LOG_ERR("TX never active.\n");
CC2538_RF_CSP_ISFLUSHTX(); CC2538_RF_CSP_ISFLUSHTX();
ret = RADIO_TX_ERR; ret = RADIO_TX_ERR;
} else { } else {
@ -679,7 +679,7 @@ read(void *buf, unsigned short bufsize)
uint8_t i; uint8_t i;
uint8_t len; uint8_t len;
PRINTF("RF: Read\n"); LOG_INFO("Read\n");
if((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) == 0) { if((REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) == 0) {
return 0; return 0;
@ -691,33 +691,33 @@ read(void *buf, unsigned short bufsize)
/* Check for validity */ /* Check for validity */
if(len > CC2538_RF_MAX_PACKET_LEN) { if(len > CC2538_RF_MAX_PACKET_LEN) {
/* Oops, we must be out of sync. */ /* Oops, we must be out of sync. */
PRINTF("RF: bad sync\n"); LOG_ERR("RF: bad sync\n");
CC2538_RF_CSP_ISFLUSHRX(); CC2538_RF_CSP_ISFLUSHRX();
return 0; return 0;
} }
if(len <= CC2538_RF_MIN_PACKET_LEN) { if(len <= CC2538_RF_MIN_PACKET_LEN) {
PRINTF("RF: too short\n"); LOG_ERR("RF: too short\n");
CC2538_RF_CSP_ISFLUSHRX(); CC2538_RF_CSP_ISFLUSHRX();
return 0; return 0;
} }
if(len - CHECKSUM_LEN > bufsize) { if(len - CHECKSUM_LEN > bufsize) {
PRINTF("RF: too long\n"); LOG_ERR("RF: too long\n");
CC2538_RF_CSP_ISFLUSHRX(); CC2538_RF_CSP_ISFLUSHRX();
return 0; return 0;
} }
/* If we reach here, chances are the FIFO is holding a valid frame */ /* If we reach here, chances are the FIFO is holding a valid frame */
PRINTF("RF: read (0x%02x bytes) = ", len); LOG_INFO("read (0x%02x bytes) = ", len);
len -= CHECKSUM_LEN; len -= CHECKSUM_LEN;
/* Don't bother with uDMA for short frames (e.g. ACKs) */ /* Don't bother with uDMA for short frames (e.g. ACKs) */
if(CC2538_RF_CONF_RX_USE_DMA && len > UDMA_RX_SIZE_THRESHOLD) { if(CC2538_RF_CONF_RX_USE_DMA && len > UDMA_RX_SIZE_THRESHOLD) {
PRINTF("<uDMA payload>"); LOG_INFO_("<uDMA payload>");
/* Set the transfer destination's end address */ /* Set the transfer destination's end address */
udma_set_channel_dst(CC2538_RF_CONF_RX_DMA_CHAN, udma_set_channel_dst(CC2538_RF_CONF_RX_DMA_CHAN,
@ -738,7 +738,7 @@ read(void *buf, unsigned short bufsize)
} else { } else {
for(i = 0; i < len; ++i) { for(i = 0; i < len; ++i) {
((unsigned char *)(buf))[i] = REG(RFCORE_SFR_RFDATA); ((unsigned char *)(buf))[i] = REG(RFCORE_SFR_RFDATA);
PRINTF("%02x", ((unsigned char *)(buf))[i]); LOG_INFO_("%02x", ((unsigned char *)(buf))[i]);
} }
} }
@ -746,14 +746,14 @@ read(void *buf, unsigned short bufsize)
rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET; rssi = ((int8_t)REG(RFCORE_SFR_RFDATA)) - RSSI_OFFSET;
crc_corr = REG(RFCORE_SFR_RFDATA); crc_corr = REG(RFCORE_SFR_RFDATA);
PRINTF("%02x%02x\n", (uint8_t)rssi, crc_corr); LOG_INFO_("%02x%02x\n", (uint8_t)rssi, crc_corr);
/* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */ /* MS bit CRC OK/Not OK, 7 LS Bits, Correlation value */
if(crc_corr & CRC_BIT_MASK) { if(crc_corr & CRC_BIT_MASK) {
packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK); packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK);
} else { } else {
PRINTF("RF: Bad CRC\n"); LOG_ERR("Bad CRC\n");
CC2538_RF_CSP_ISFLUSHRX(); CC2538_RF_CSP_ISFLUSHRX();
return 0; return 0;
} }
@ -775,7 +775,7 @@ read(void *buf, unsigned short bufsize)
static int static int
receiving_packet(void) receiving_packet(void)
{ {
PRINTF("RF: Receiving\n"); LOG_INFO("Receiving\n");
/* /*
* SFD high while transmitting and receiving. * SFD high while transmitting and receiving.
@ -791,7 +791,7 @@ receiving_packet(void)
static int static int
pending_packet(void) pending_packet(void)
{ {
PRINTF("RF: Pending\n"); LOG_INFO("Pending\n");
return REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP; return REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP;
} }
@ -886,9 +886,7 @@ set_value(radio_param_t param, radio_value_t value)
value > CC2538_RF_CHANNEL_MAX) { value > CC2538_RF_CHANNEL_MAX) {
return RADIO_RESULT_INVALID_VALUE; return RADIO_RESULT_INVALID_VALUE;
} }
if(set_channel(value) == CC2538_RF_CHANNEL_SET_ERROR) { set_channel(value);
return RADIO_RESULT_ERROR;
}
return RADIO_RESULT_OK; return RADIO_RESULT_OK;
case RADIO_PARAM_PAN_ID: case RADIO_PARAM_PAN_ID:
set_pan_id(value & 0xffff); set_pan_id(value & 0xffff);
@ -924,6 +922,9 @@ set_value(radio_param_t param, radio_value_t value)
case RADIO_PARAM_CCA_THRESHOLD: case RADIO_PARAM_CCA_THRESHOLD:
set_cca_threshold(value); set_cca_threshold(value);
return RADIO_RESULT_OK; return RADIO_RESULT_OK;
case RADIO_PARAM_SHR_SEARCH:
set_shr_search(value);
return RADIO_RESULT_OK;
default: default:
return RADIO_RESULT_NOT_SUPPORTED; return RADIO_RESULT_NOT_SUPPORTED;
} }
@ -1085,7 +1086,7 @@ cc2538_rf_rx_tx_isr(void)
void void
cc2538_rf_err_isr(void) cc2538_rf_err_isr(void)
{ {
PRINTF("RF Error: 0x%08lx\n", REG(RFCORE_SFR_RFERRF)); LOG_ERR("Error 0x%08lx occurred\n", REG(RFCORE_SFR_RFERRF));
/* If the error is not an RX FIFO overflow, set a flag */ /* If the error is not an RX FIFO overflow, set a flag */
if(REG(RFCORE_SFR_RFERRF) != RFCORE_SFR_RFERRF_RXOVERF) { if(REG(RFCORE_SFR_RFERRF) != RFCORE_SFR_RFERRF_RXOVERF) {
@ -1097,10 +1098,5 @@ cc2538_rf_err_isr(void)
process_poll(&cc2538_rf_process); process_poll(&cc2538_rf_process);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void
cc2538_rf_set_promiscous_mode(char p)
{
set_frame_filtering(p);
}
/*---------------------------------------------------------------------------*/
/** @} */ /** @} */

View File

@ -56,7 +56,6 @@
#define CC2538_RF_CHANNEL_MIN 11 #define CC2538_RF_CHANNEL_MIN 11
#define CC2538_RF_CHANNEL_MAX 26 #define CC2538_RF_CHANNEL_MAX 26
#define CC2538_RF_CHANNEL_SPACING 5 #define CC2538_RF_CHANNEL_SPACING 5
#define CC2538_RF_CHANNEL_SET_ERROR -1
#define CC2538_RF_MAX_PACKET_LEN 127 #define CC2538_RF_MAX_PACKET_LEN 127
#define CC2538_RF_MIN_PACKET_LEN 4 #define CC2538_RF_MIN_PACKET_LEN 4
#define CC2538_RF_CCA_CLEAR 1 #define CC2538_RF_CCA_CLEAR 1
@ -113,7 +112,6 @@
*/ */
#define CC2538_RF_CSP_ISFLUSHRX() do { \ #define CC2538_RF_CSP_ISFLUSHRX() do { \
REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; \ REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; \
REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHRX; \
} while(0) } while(0)
/** /**
@ -121,7 +119,6 @@
*/ */
#define CC2538_RF_CSP_ISFLUSHTX() do { \ #define CC2538_RF_CSP_ISFLUSHTX() do { \
REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; \ REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; \
REG(RFCORE_SFR_RFST) = CC2538_RF_CSP_OP_ISFLUSHTX; \
} while(0) } while(0)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** The NETSTACK data structure for the cc2538 RF driver */ /** The NETSTACK data structure for the cc2538 RF driver */
@ -138,16 +135,6 @@ extern const struct radio_driver cc2538_rf_driver;
*/ */
void cc2538_rf_set_addr(uint16_t pan); void cc2538_rf_set_addr(uint16_t pan);
/**
* \brief Turn promiscous mode on or off
* \param p If promiscous mode should be on (1) or off (0)
*
* This function turns promiscous mode on or off. In promiscous mode,
* every received frame is returned from the RF core. In
* non-promiscous mode, only broadcast frames or frames with our
* address as the receive address are returned from the RF core.
*/
void cc2538_rf_set_promiscous_mode(char p);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#endif /* CC2538_RF_H__ */ #endif /* CC2538_RF_H__ */

View File

@ -170,6 +170,9 @@ enum {
* it needs to be used with radio.get_object()/set_object(). */ * it needs to be used with radio.get_object()/set_object(). */
RADIO_PARAM_LAST_PACKET_TIMESTAMP, RADIO_PARAM_LAST_PACKET_TIMESTAMP,
/* For enabling and disabling the SHR search */
RADIO_PARAM_SHR_SEARCH,
/* Constants (read only) */ /* Constants (read only) */
/* The lowest radio channel. */ /* The lowest radio channel. */