40 #include "sys/clock.h"
55 #define CHECKSUM_LEN 2
58 #define UDMA_TX_FLAGS (UDMA_CHCTL_ARBSIZE_128 | UDMA_CHCTL_XFERMODE_AUTO \
59 | UDMA_CHCTL_SRCSIZE_8 | UDMA_CHCTL_DSTSIZE_8 \
60 | UDMA_CHCTL_SRCINC_8 | UDMA_CHCTL_DSTINC_NONE)
62 #define UDMA_RX_FLAGS (UDMA_CHCTL_ARBSIZE_128 | UDMA_CHCTL_XFERMODE_AUTO \
63 | UDMA_CHCTL_SRCSIZE_8 | UDMA_CHCTL_DSTSIZE_8 \
64 | UDMA_CHCTL_SRCINC_NONE | UDMA_CHCTL_DSTINC_8)
70 #define UDMA_RX_SIZE_THRESHOLD 3
75 #define PRINTF(...) printf(__VA_ARGS__)
81 #define RX_ACTIVE 0x80
82 #define RF_MUST_RESET 0x40
87 #define CRC_BIT_MASK 0x80
88 #define LQI_BIT_MASK 0x7F
90 #define RSSI_OFFSET 73
93 #define ONOFF_TIME RTIMER_ARCH_SECOND / 3125
96 #ifndef CC2538_RF_CONF_SNIFFER_USB
97 #define CC2538_RF_CONF_SNIFFER_USB 0
100 #if CC2538_RF_CONF_SNIFFER
101 static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 };
103 #if CC2538_RF_CONF_SNIFFER_USB
105 #define write_byte(b) usb_serial_writeb(b)
106 #define flush() usb_serial_flush()
108 #include "dev/uart.h"
109 #define write_byte(b) uart_write_byte(CC2538_RF_CONF_SNIFFER_UART, b)
114 #define write_byte(b)
118 #ifdef CC2538_RF_CONF_AUTOACK
119 #define CC2538_RF_AUTOACK CC2538_RF_CONF_AUTOACK
121 #define CC2538_RF_AUTOACK 1
124 static uint8_t rf_flags;
127 static int off(
void);
130 typedef struct output_config {
135 static const output_config_t output_power[] = {
152 #define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t))
155 #define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].power)
156 #define OUTPUT_POWER_MAX (output_power[0].power)
158 PROCESS(cc2538_rf_process,
"cc2538 RF driver");
169 return ((chan - CC2538_RF_CHANNEL_MIN) / CC2538_RF_CHANNEL_SPACING
170 + CC2538_RF_CHANNEL_MIN);
180 set_channel(uint8_t channel)
182 PRINTF(
"RF: Set Channel\n");
184 if((channel < CC2538_RF_CHANNEL_MIN) || (channel > CC2538_RF_CHANNEL_MAX)) {
185 return CC2538_RF_CHANNEL_SET_ERROR;
191 + (channel - CC2538_RF_CHANNEL_MIN) * CC2538_RF_CHANNEL_SPACING);
194 return (int8_t) channel;
204 set_pan_id(uint16_t pan)
217 set_short_addr(uint16_t addr)
247 if((rf_flags & WAS_OFF) == WAS_OFF) {
248 rf_flags &= ~WAS_OFF;
257 get_cca_threshold(
void)
282 for(i = 0; i < OUTPUT_CONFIG_COUNT; i++) {
283 if(reg_val >= output_power[i].txpower_val) {
284 return output_power[i].power;
287 return OUTPUT_POWER_MIN;
301 for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) {
302 if(power <= output_power[i].power) {
310 set_frame_filtering(uint8_t enable)
320 set_auto_ack(uint8_t enable)
348 cca = CC2538_RF_CCA_CLEAR;
350 cca = CC2538_RF_CCA_BUSY;
354 if((rf_flags & WAS_OFF) == WAS_OFF) {
355 rf_flags &= ~WAS_OFF;
367 if(!(rf_flags & RX_ACTIVE)) {
371 rf_flags |= RX_ACTIVE;
374 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
393 rf_flags &= ~RX_ACTIVE;
395 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
402 PRINTF(
"RF: Init\n");
404 if(rf_flags & RF_ON) {
421 REG(ANA_REGS_IVCTRL) = 0x0B;
430 #if CC2538_RF_AUTOACK
435 #if CC2538_RF_CONF_SNIFFER
448 set_channel(CC2538_RF_CHANNEL);
484 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
490 prepare(
const void *payload,
unsigned short payload_len)
494 PRINTF(
"RF: Prepare 0x%02x bytes\n", payload_len + CHECKSUM_LEN);
502 if((rf_flags & RX_ACTIVE) == 0) {
508 PRINTF(
"RF: data = ");
513 PRINTF(
"<uDMA payload>");
517 (uint32_t)(payload) + payload_len - 1);
535 for(i = 0; i < payload_len; i++) {
537 PRINTF(
"%02x", ((
unsigned char *)(payload))[i]);
546 transmit(
unsigned short transmit_len)
549 int ret = RADIO_TX_ERR;
552 PRINTF(
"RF: Transmit\n");
554 if(!(rf_flags & RX_ACTIVE)) {
558 while(RTIMER_CLOCK_LT(
RTIMER_NOW(), t0 + ONOFF_TIME));
561 if(channel_clear() == CC2538_RF_CCA_BUSY) {
562 RIMESTATS_ADD(contentiondrop);
563 return RADIO_TX_COLLISION;
571 RIMESTATS_ADD(contentiondrop);
572 return RADIO_TX_COLLISION;
576 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
577 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
583 && (counter++ < 3)) {
588 PRINTF(
"RF: TX never active.\n");
596 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
597 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
599 if(rf_flags & WAS_OFF) {
600 rf_flags &= ~WAS_OFF;
610 send(
const void *payload,
unsigned short payload_len)
612 prepare(payload, payload_len);
613 return transmit(payload_len);
617 read(
void *buf,
unsigned short bufsize)
624 PRINTF(
"RF: Read\n");
634 if(len > CC2538_RF_MAX_PACKET_LEN) {
636 PRINTF(
"RF: bad sync\n");
638 RIMESTATS_ADD(badsynch);
643 if(len <= CC2538_RF_MIN_PACKET_LEN) {
644 PRINTF(
"RF: too short\n");
646 RIMESTATS_ADD(tooshort);
651 if(len - CHECKSUM_LEN > bufsize) {
652 PRINTF(
"RF: too long\n");
654 RIMESTATS_ADD(toolong);
660 PRINTF(
"RF: read (0x%02x bytes) = ", len);
665 PRINTF(
"<uDMA payload>");
669 (uint32_t)(buf) + len - 1);
684 for(i = 0; i < len; ++i) {
686 PRINTF(
"%02x", ((
unsigned char *)(buf))[i]);
694 PRINTF(
"%02x%02x\n", (uint8_t)rssi, crc_corr);
697 if(crc_corr & CRC_BIT_MASK) {
698 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
699 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_corr & LQI_BIT_MASK);
702 RIMESTATS_ADD(badcrc);
703 PRINTF(
"RF: Bad CRC\n");
708 #if CC2538_RF_CONF_SNIFFER
709 write_byte(magic[0]);
710 write_byte(magic[1]);
711 write_byte(magic[2]);
712 write_byte(magic[3]);
714 for(i = 0; i < len; ++i) {
715 write_byte(((
unsigned char *)(buf))[i]);
718 write_byte(crc_corr);
735 receiving_packet(
void)
737 PRINTF(
"RF: Receiving\n");
746 & (RFCORE_XREG_FSMSTAT1_TX_ACTIVE | RFCORE_XREG_FSMSTAT1_SFD))
747 == RFCORE_XREG_FSMSTAT1_SFD);
753 PRINTF(
"RF: Pending\n");
758 static radio_result_t
762 return RADIO_RESULT_INVALID_VALUE;
766 case RADIO_PARAM_POWER_MODE:
768 ? RADIO_POWER_MODE_OFF : RADIO_POWER_MODE_ON;
769 return RADIO_RESULT_OK;
770 case RADIO_PARAM_CHANNEL:
772 return RADIO_RESULT_OK;
773 case RADIO_PARAM_PAN_ID:
774 *value = get_pan_id();
775 return RADIO_RESULT_OK;
776 case RADIO_PARAM_16BIT_ADDR:
777 *value = get_short_addr();
778 return RADIO_RESULT_OK;
779 case RADIO_PARAM_RX_MODE:
785 *value |= RADIO_RX_MODE_AUTOACK;
787 return RADIO_RESULT_OK;
788 case RADIO_PARAM_TXPOWER:
789 *value = get_tx_power();
790 return RADIO_RESULT_OK;
791 case RADIO_PARAM_CCA_THRESHOLD:
792 *value = get_cca_threshold();
793 return RADIO_RESULT_OK;
794 case RADIO_PARAM_RSSI:
796 return RADIO_RESULT_OK;
797 case RADIO_CONST_CHANNEL_MIN:
798 *value = CC2538_RF_CHANNEL_MIN;
799 return RADIO_RESULT_OK;
800 case RADIO_CONST_CHANNEL_MAX:
801 *value = CC2538_RF_CHANNEL_MAX;
802 return RADIO_RESULT_OK;
803 case RADIO_CONST_TXPOWER_MIN:
804 *value = OUTPUT_POWER_MIN;
805 return RADIO_RESULT_OK;
806 case RADIO_CONST_TXPOWER_MAX:
807 *value = OUTPUT_POWER_MAX;
808 return RADIO_RESULT_OK;
810 return RADIO_RESULT_NOT_SUPPORTED;
814 static radio_result_t
818 case RADIO_PARAM_POWER_MODE:
819 if(value == RADIO_POWER_MODE_ON) {
821 return RADIO_RESULT_OK;
823 if(value == RADIO_POWER_MODE_OFF) {
825 return RADIO_RESULT_OK;
827 return RADIO_RESULT_INVALID_VALUE;
828 case RADIO_PARAM_CHANNEL:
829 if(value < CC2538_RF_CHANNEL_MIN ||
830 value > CC2538_RF_CHANNEL_MAX) {
831 return RADIO_RESULT_INVALID_VALUE;
833 if(set_channel(value) == CC2538_RF_CHANNEL_SET_ERROR) {
834 return RADIO_RESULT_ERROR;
836 return RADIO_RESULT_OK;
837 case RADIO_PARAM_PAN_ID:
838 set_pan_id(value & 0xffff);
839 return RADIO_RESULT_OK;
840 case RADIO_PARAM_16BIT_ADDR:
841 set_short_addr(value & 0xffff);
842 return RADIO_RESULT_OK;
843 case RADIO_PARAM_RX_MODE:
845 RADIO_RX_MODE_AUTOACK)) {
846 return RADIO_RESULT_INVALID_VALUE;
850 set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
852 return RADIO_RESULT_OK;
853 case RADIO_PARAM_TXPOWER:
854 if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
855 return RADIO_RESULT_INVALID_VALUE;
859 return RADIO_RESULT_OK;
860 case RADIO_PARAM_CCA_THRESHOLD:
861 set_cca_threshold(value);
862 return RADIO_RESULT_OK;
864 return RADIO_RESULT_NOT_SUPPORTED;
868 static radio_result_t
869 get_object(radio_param_t param,
void *dest,
size_t size)
874 if(param == RADIO_PARAM_64BIT_ADDR) {
875 if(size != 8 || !dest) {
876 return RADIO_RESULT_INVALID_VALUE;
880 for(i = 0; i < 8; i++) {
884 return RADIO_RESULT_OK;
886 return RADIO_RESULT_NOT_SUPPORTED;
889 static radio_result_t
890 set_object(radio_param_t param,
const void *src,
size_t size)
894 if(param == RADIO_PARAM_64BIT_ADDR) {
895 if(size != 8 || !src) {
896 return RADIO_RESULT_INVALID_VALUE;
899 for(i = 0; i < 8; i++) {
903 return RADIO_RESULT_OK;
905 return RADIO_RESULT_NOT_SUPPORTED;
949 NETSTACK_RDC.input();
953 if(rf_flags & RF_MUST_RESET) {
974 ENERGEST_ON(ENERGEST_TYPE_IRQ);
981 ENERGEST_OFF(ENERGEST_TYPE_IRQ);
1003 ENERGEST_ON(ENERGEST_TYPE_IRQ);
1009 rf_flags |= RF_MUST_RESET;
1016 ENERGEST_OFF(ENERGEST_TYPE_IRQ);
1022 set_frame_filtering(p);
uint8_t udma_channel_get_mode(uint8_t channel)
Retrieve the current mode for a channel.
#define RFCORE_XREG_RSSI_RSSI_VAL
RSSI estimate.
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
#define RFCORE_XREG_RSSISTAT_RSSI_VALID
RSSI value is valid.
#define RFCORE_XREG_CCACTRL0
CCA threshold.
void process_poll(struct process *p)
Request a process to be polled.
void udma_channel_sw_request(uint8_t channel)
Generate a software trigger to start a transfer.
#define RFCORE_XREG_RFERRM_RFERRM
RF error interrupt mask.
#define RFCORE_XREG_CCACTRL0_CCA_THR
Clear-channel-assessment.
#define RFCORE_XREG_FRMFILT0_FRAME_FILTER_EN
Enables frame filtering.
#define RFCORE_XREG_RSSI
RSSI status register.
#define RFCORE_XREG_RFERRM
RF error interrupt mask.
#define PROCESS_BEGIN()
Define the beginning of a process.
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Header file for the radio API
#define RFCORE_SFR_RFERRF_RXOVERF
RX FIFO overflowed.
#define CC2538_RF_CONF_RX_DMA_CHAN
RAM -> RF DMA channel.
#define RFCORE_SFR_RFIRQF0
RF interrupt flags.
#define RFCORE_XREG_TXFILTCFG
TX filter configuration.
Header file for the Rime buffer (packetbuf) management
#define RFCORE_XREG_RFIRQM0_FIFOP
RX FIFO exceeded threshold.
void udma_set_channel_src(uint8_t channel, uint32_t src_end)
Sets the channels source address.
void cc2538_rf_set_promiscous_mode(char p)
Turn promiscous mode on or off.
#define NVIC_INT_RF_ERR
RF Core Error.
#define NULL
The null pointer.
The structure of a device driver for a radio in Contiki.
#define SYS_CTRL_DCGCRFC
RF Core clocks - PM0.
#define CC2538_RF_CSP_ISTXON()
Send a TX ON command strobe to the CSP.
int(* pending_packet)(void)
Check if the radio driver has just received a packet.
Header file with register, macro and function declarations for the cc2538 micro-DMA controller module...
#define RFCORE_XREG_FIFOPCTRL
FIFOP threshold.
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
#define RFCORE_XREG_FRMCTRL0
Frame handling.
void nvic_interrupt_enable(uint32_t intr)
Enables interrupt intr.
struct radio_driver cc2538_rf_driver
The NETSTACK data structure for the cc2538 RF driver.
void cc2538_rf_rx_tx_isr(void)
The cc2538 RF RX/TX ISR.
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
#define RFCORE_XREG_RSSISTAT
RSSI valid status register.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
void udma_channel_enable(uint8_t channel)
Enables a uDMA channel.
#define SYS_CTRL_SCGCRFC
RF Core clocks - Sleep mode.
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
#define RFCORE_XREG_FRMCTRL0_AUTOACK
Transmit ACK frame enable.
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
#define RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE
FIFO and FFCTRL status.
Header file with register manipulation macro definitions.
Header file for the energy estimation mechanism
#define CC2538_RF_CSP_ISRXON()
Send an RX ON command strobe to the CSP.
#define RFCORE_XREG_RXENABLE
RX enabling.
#define RFCORE_XREG_RFIRQM0
RF interrupt masks.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PROCESS_END()
Define the end of a process.
int(* channel_clear)(void)
Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not...
#define RFCORE_FFSM_PAN_ID1
Local address information.
Header file for the cc2538 System Control driver.
Header file for the real-time timer module.
#define RFCORE_XREG_FSMSTAT1_TX_ACTIVE
Status signal - TX states.
#define RFCORE_XREG_FSMSTAT1
Radio status register.
int(* on)(void)
Turn the radio on.
#define NVIC_INT_RF_RXTX
RF Core Rx/Tx.
#define RFCORE_XREG_RXENABLE_RXENMASK
Enables the receiver.
#define RFCORE_FFSM_PAN_ID0
Local address information.
void udma_set_channel_dst(uint8_t channel, uint32_t dst_end)
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
#define RFCORE_FFSM_SHORT_ADDR1
Local address information.
void udma_channel_mask_set(uint8_t channel)
Disable peripheral triggers for a uDMA channel.
#define RFCORE_XREG_AGCCTRL1
AGC reference level.
void udma_set_channel_control_word(uint8_t channel, uint32_t ctrl)
Configure the channel's control word.
#define RFCORE_XREG_FRMCTRL0_AUTOCRC
Auto CRC generation / checking.
#define RFCORE_XREG_FSMSTAT1_FIFO
FIFO status.
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
#define RFCORE_XREG_FSMSTAT1_SFD
SFD was sent/received.
#define CC2538_RF_CSP_ISFLUSHRX()
Flush the RX FIFO.
#define PROCESS(name, strname)
Declare a process.
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
#define CC2538_RF_CONF_RX_USE_DMA
RF RX over DMA.
#define RFCORE_SFR_RFDATA
TX/RX FIFO data.
void packetbuf_clear(void)
Clear and reset the packetbuf.
void process_start(struct process *p, process_data_t data)
Start a process.
#define RFCORE_FFSM_EXT_ADDR0
Local address information.
#define RTIMER_NOW()
Get the current clock time.
Top-level header file for cc2538 RF Core registers.
#define CC2538_RF_CSP_ISFLUSHTX()
Flush the TX FIFO.
#define RFCORE_XREG_FRMFILT0
Frame filtering control.
#define SYS_CTRL_RCGCRFC
RF Core clocks - active mode.
#define RFCORE_FFSM_SHORT_ADDR0
Local address information.
#define RFCORE_XREG_TXPOWER
Controls the output power.
#define CC2538_RF_CSP_ISRFOFF()
Send a RF OFF command strobe to the CSP.
Header file for the cc2538 RF driver.
#define RFCORE_SFR_RFERRF
RF error interrupt flags.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
#define RFCORE_XREG_FREQCTRL_FREQ
Frequency control word.
#define RFCORE_XREG_FREQCTRL
Controls the RF frequency.
Header file for Rime statistics
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
void cc2538_rf_err_isr(void)
The cc2538 RF Error ISR.
Header file for cc2538's UART-like I/O over USB.
#define udma_xfer_size(len)
Calculate the value of the xfersize field in the control structure.
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
#define RFCORE_XREG_SRCMATCH
Source address matching.
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
#define CC2538_RF_CONF_TX_USE_DMA
RF TX over DMA.
#define RFCORE_XREG_FSMSTAT1_FIFOP
FIFOP status.
#define RFCORE_XREG_FSMSTAT0
Radio status register.
int(* read)(void *buf, unsigned short buf_len)
Read a received packet into a buffer.
int(* off)(void)
Turn the radio off.
Include file for the Contiki low-layer network stack (NETSTACK)
#define RFCORE_XREG_FSMSTAT1_CCA
Clear channel assessment.
Header file for the Rime address representation
#define CC2538_RF_CONF_TX_DMA_CHAN
RF -> RAM DMA channel.