40#include "dev/watchdog.h"
51#include "hw_rfc_dbell.h"
52#include "hw_rfc_pwr.h"
55#include "driverlib/rf_mailbox.h"
56#include "driverlib/rf_common_cmd.h"
57#include "driverlib/rf_data_entry.h"
66#define PRINTF(...) printf(__VA_ARGS__)
71#ifdef RF_CORE_CONF_DEBUG_CRC
72#define RF_CORE_DEBUG_CRC RF_CORE_CONF_DEBUG_CRC
74#define RF_CORE_DEBUG_CRC DEBUG
78#define RX_FRAME_IRQ IRQ_RX_ENTRY_DONE
79#define ERROR_IRQ (IRQ_INTERNAL_ERROR | IRQ_RX_BUF_FULL)
80#define RX_NOK_IRQ IRQ_RX_NOK
84#define ENABLED_IRQS (RX_FRAME_IRQ | ERROR_IRQ | RX_NOK_IRQ)
86#define ENABLED_IRQS (RX_FRAME_IRQ | ERROR_IRQ)
89#define ENABLED_IRQS_POLL_MODE (ENABLED_IRQS & ~(RX_FRAME_IRQ | ERROR_IRQ))
91#define cc26xx_rf_cpe0_isr RFCCPE0IntHandler
92#define cc26xx_rf_cpe1_isr RFCCPE1IntHandler
94typedef ChipType_t chip_type_t;
97static rfc_radioOp_t *last_radio_op = NULL;
103#define RAT_RANGE 4294967296ull
105#define RAT_OVERFLOW_PERIOD_SECONDS (60 * 18)
108#define RAT_OVERFLOW_TIMER_INTERVAL (CLOCK_SECOND * RAT_OVERFLOW_PERIOD_SECONDS / 3)
111static int32_t rat_offset;
112static bool rat_offset_known;
115static uint32_t rat_last_value;
118static struct ctimer rat_overflow_timer;
119static volatile uint32_t rat_overflow_counter;
120static rtimer_clock_t rat_last_overflow;
122static void rat_overflow_check_timer_cb(
void *);
124volatile int8_t rf_core_last_rssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
125volatile uint8_t rf_core_last_corr_lqi = 0;
126volatile uint32_t rf_core_last_packet_timestamp = 0;
129uint8_t rf_core_poll_mode = 0;
132volatile uint32_t last_cmd_status;
134PROCESS(rf_core_process,
"CC13xx / CC26xx RF driver");
136#define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \
137 | RFC_PWR_PWMCLKEN_CPERAM_M | RFC_PWR_PWMCLKEN_FSCA_M \
138 | RFC_PWR_PWMCLKEN_PHA_M | RFC_PWR_PWMCLKEN_RAT_M \
139 | RFC_PWR_PWMCLKEN_RFERAM_M | RFC_PWR_PWMCLKEN_RFE_M \
140 | RFC_PWR_PWMCLKEN_MDMRAM_M | RFC_PWR_PWMCLKEN_MDM_M)
142#define RF_CMD0 0x0607
147 if(ti_lib_prcm_rf_ready()) {
148 return RF_CORE_ACCESSIBLE;
150 return RF_CORE_NOT_ACCESSIBLE;
156 uint32_t timeout_count = 0;
157 bool interrupts_disabled;
158 bool is_radio_op =
false;
161 last_cmd_status = (uint32_t)-1;
162 *status = last_cmd_status;
168 if((cmd & 0x03) == 0) {
170 cmd_type = ((rfc_command_t *)cmd)->commandNo & RF_CORE_COMMAND_TYPE_MASK;
171 if(cmd_type == RF_CORE_COMMAND_TYPE_IEEE_FG_RADIO_OP ||
172 cmd_type == RF_CORE_COMMAND_TYPE_RADIO_OP) {
174 ((rfc_radioOp_t *)cmd)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
182 interrupts_disabled = ti_lib_int_master_disable();
185 PRINTF(
"rf_core_send_cmd: RF was off\n");
186 if(!interrupts_disabled) {
187 ti_lib_int_master_enable();
189 return RF_CORE_CMD_ERROR;
193 uint16_t command_no = ((rfc_radioOp_t *)cmd)->commandNo;
194 if((command_no & RF_CORE_COMMAND_PROTOCOL_MASK) != RF_CORE_COMMAND_PROTOCOL_COMMON &&
195 (command_no & RF_CORE_COMMAND_TYPE_MASK) == RF_CORE_COMMAND_TYPE_RADIO_OP) {
196 last_radio_op = (rfc_radioOp_t *)cmd;
200 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd;
202 last_cmd_status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
203 if(++timeout_count > 50000) {
204 PRINTF(
"rf_core_send_cmd: 0x%08lx Timeout\n", cmd);
205 if(!interrupts_disabled) {
206 ti_lib_int_master_enable();
208 *status = last_cmd_status;
209 return RF_CORE_CMD_ERROR;
211 }
while((last_cmd_status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_PENDING);
213 if(!interrupts_disabled) {
214 ti_lib_int_master_enable();
221 *status = last_cmd_status;
222 return (last_cmd_status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_DONE;
228 volatile rfc_radioOp_t *command = (rfc_radioOp_t *)cmd;
229 uint32_t timeout_cnt = 0;
236 if(++timeout_cnt > 500000) {
237 return RF_CORE_CMD_ERROR;
239 }
while((command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
240 != RF_CORE_RADIO_OP_MASKED_STATUS_DONE);
242 last_cmd_status = command->status;
243 return (command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
244 == RF_CORE_RADIO_OP_STATUS_DONE_OK;
250 return last_cmd_status;
256 rfc_CMD_FS_POWERDOWN_t cmd;
262 PRINTF(
"fs_powerdown: CMDSTA=0x%08lx\n", cmd_status);
263 return RF_CORE_CMD_ERROR;
267 PRINTF(
"fs_powerdown: CMDSTA=0x%08lx, status=0x%04x\n",
268 cmd_status, cmd.status);
269 return RF_CORE_CMD_ERROR;
272 return RF_CORE_CMD_OK;
279 bool interrupts_disabled = ti_lib_int_master_disable();
281 ti_lib_int_pend_clear(INT_RFC_CPE_0);
282 ti_lib_int_pend_clear(INT_RFC_CPE_1);
283 ti_lib_int_disable(INT_RFC_CPE_0);
284 ti_lib_int_disable(INT_RFC_CPE_1);
287 ti_lib_prcm_power_domain_on(PRCM_DOMAIN_RFCORE);
288 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
289 != PRCM_DOMAIN_POWER_ON);
291 ti_lib_prcm_domain_enable(PRCM_DOMAIN_RFCORE);
292 ti_lib_prcm_load_set();
293 while(!ti_lib_prcm_load_get());
295 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
296 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
297 ti_lib_int_enable(INT_RFC_CPE_0);
298 ti_lib_int_enable(INT_RFC_CPE_1);
300 if(!interrupts_disabled) {
301 ti_lib_int_master_enable();
304 rf_switch_power_up();
307 HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK;
310 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
311 HWREG(RFC_DBELL_BASE+RFC_DBELL_O_CMDR) =
312 CMDR_DIR_CMD_2BYTE(RF_CMD0,
313 RFC_PWR_PWMCLKEN_MDMRAM | RFC_PWR_PWMCLKEN_RFERAM);
316 if(
rf_core_send_cmd(CMDR_DIR_CMD(CMD_PING), &cmd_status) != RF_CORE_CMD_OK) {
317 PRINTF(
"rf_core_power_up: CMD_PING fail, CMDSTA=0x%08lx\n", cmd_status);
318 return RF_CORE_CMD_ERROR;
321 return RF_CORE_CMD_OK;
328 rfc_CMD_SYNC_START_RAT_t cmd_start;
334 cmd_start.rat0 = rat_offset;
337 PRINTF(
"rf_core_get_rat_rtc_offset: SYNC_START_RAT fail, CMDSTA=0x%08lx\n",
339 return RF_CORE_CMD_ERROR;
344 PRINTF(
"rf_core_cmd_ok: SYNC_START_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
345 cmd_status, cmd_start.status);
346 return RF_CORE_CMD_ERROR;
349 return RF_CORE_CMD_OK;
355 rfc_CMD_SYNC_STOP_RAT_t cmd_stop;
361 if(ret != RF_CORE_CMD_OK) {
362 PRINTF(
"rf_core_get_rat_rtc_offset: SYNC_STOP_RAT fail, ret %d CMDSTA=0x%08lx\n",
369 if(ret != RF_CORE_CMD_OK) {
370 PRINTF(
"rf_core_cmd_ok: SYNC_STOP_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
371 cmd_status, cmd_stop.status);
375 if(!rat_offset_known) {
377 rat_offset_known =
true;
378 rat_offset = cmd_stop.rat0;
381 return RF_CORE_CMD_OK;
387 bool interrupts_disabled = ti_lib_int_master_disable();
388 ti_lib_int_disable(INT_RFC_CPE_0);
389 ti_lib_int_disable(INT_RFC_CPE_1);
392 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
393 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
402 ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE);
403 ti_lib_prcm_load_set();
404 while(!ti_lib_prcm_load_get());
407 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE);
408 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
409 != PRCM_DOMAIN_POWER_OFF);
411 rf_switch_power_down();
413 ti_lib_int_pend_clear(INT_RFC_CPE_0);
414 ti_lib_int_pend_clear(INT_RFC_CPE_1);
415 ti_lib_int_enable(INT_RFC_CPE_0);
416 ti_lib_int_enable(INT_RFC_CPE_1);
417 if(!interrupts_disabled) {
418 ti_lib_int_master_enable();
425 uint8_t rv = RF_CORE_CMD_ERROR;
426 chip_type_t chip_type = ti_lib_chipinfo_get_chip_type();
428 if(chip_type == CHIP_TYPE_CC2650) {
429 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
431 }
else if(chip_type == CHIP_TYPE_CC2630) {
432 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE2;
434 }
else if(chip_type == CHIP_TYPE_CC1310) {
435 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE3;
437 }
else if(chip_type == CHIP_TYPE_CC1350) {
438 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
440#if CPU_FAMILY_CC26X0R2
441 }
else if(chip_type == CHIP_TYPE_CC2640R2) {
442 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE1;
454 PRINTF(
"rf_core_boot: rf_core_power_up() failed\n");
458 return RF_CORE_CMD_ERROR;
462 PRINTF(
"rf_core_boot: rf_core_start_rat() failed\n");
466 return RF_CORE_CMD_ERROR;
469 return RF_CORE_CMD_OK;
476 PRINTF(
"rf_core_restart_rat: rf_core_stop_rat() failed\n");
481 PRINTF(
"rf_core_restart_rat: rf_core_start_rat() failed\n");
485 return RF_CORE_CMD_ERROR;
488 return RF_CORE_CMD_OK;
494 bool interrupts_disabled;
495 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
499 PRINTF(
"setup_interrupts: No access\n");
504 interrupts_disabled = ti_lib_int_master_disable();
507 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;
510 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
513 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
515 ti_lib_int_pend_clear(INT_RFC_CPE_0);
516 ti_lib_int_pend_clear(INT_RFC_CPE_1);
517 ti_lib_int_enable(INT_RFC_CPE_0);
518 ti_lib_int_enable(INT_RFC_CPE_1);
520 if(!interrupts_disabled) {
521 ti_lib_int_master_enable();
529 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
531 if(!rf_core_poll_mode) {
532 irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE;
535 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = enabled_irqs;
536 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs | irq;
542 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
543 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
549 return last_radio_op;
557 op->commandNo = command;
558 op->condition.rule = COND_NEVER;
571 if(primary_mode->
abort) {
572 primary_mode->
abort();
582 return primary_mode->
restore();
586 return RF_CORE_CMD_ERROR;
592 rat_last_value = HWREG(RFC_RAT_BASE + RATCNT);
594 ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_TIMER_INTERVAL,
595 rat_overflow_check_timer_cb, NULL);
603 uint32_t rat_current_value;
604 uint8_t interrupts_disabled;
607 if(primary_mode == NULL || !primary_mode->
is_on()) {
611 interrupts_disabled = ti_lib_int_master_disable();
613 rat_current_value = HWREG(RFC_RAT_BASE + RATCNT);
614 if(rat_current_value + RAT_RANGE / 4 < rat_last_value) {
617 rat_overflow_counter++;
619 rat_last_value = rat_current_value;
621 if(!interrupts_disabled) {
622 ti_lib_int_master_enable();
629rat_overflow_check_timer_cb(
void *unused)
634 if(primary_mode != NULL) {
636 if(!primary_mode->
is_on()) {
638 if(NETSTACK_RADIO.on() != RF_CORE_CMD_OK) {
639 PRINTF(
"overflow: on() failed\n");
641 rat_overflow_check_timer_cb, NULL);
649 NETSTACK_RADIO.off();
655 ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_TIMER_INTERVAL,
656 rat_overflow_check_timer_cb, NULL);
660 rat_overflow_check_timer_cb, NULL);
667 uint64_t rat_timestamp64;
668 uint32_t adjusted_overflow_counter;
671 if(primary_mode == NULL) {
672 PRINTF(
"rf_core_convert_rat_to_rtimer: not initialized\n");
676 if(!primary_mode->
is_on()) {
684 NETSTACK_RADIO.off();
687 adjusted_overflow_counter = rat_overflow_counter;
691 if(rat_timestamp > (uint32_t)(RAT_RANGE * 3 / 4)) {
693 rat_last_overflow + RAT_OVERFLOW_PERIOD_SECONDS *
RTIMER_SECOND / 4)) {
694 adjusted_overflow_counter--;
699 rat_timestamp64 = rat_timestamp + RAT_RANGE * adjusted_overflow_counter;
703 return RADIO_TO_RTIMER(rat_timestamp64 - rat_offset);
722 NETSTACK_MAC.
input();
735cc26xx_rf_cpe1_isr(
void)
737 PRINTF(
"RF Error\n");
745 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_RX_BUF_FULL) {
746 PRINTF(
"\nRF: BUF_FULL\n\n");
750 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ~(IRQ_RX_BUF_FULL);
754 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x7FFFFFFF;
758cc26xx_rf_cpe0_isr(
void)
761 PRINTF(
"RF ISR called but RF not ready... PANIC!!\n");
763 PRINTF(
"rf_core_power_up() failed\n");
768 ti_lib_int_master_disable();
770 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_FRAME_IRQ) {
772 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFF7FFFFF;
776 if(RF_CORE_DEBUG_CRC) {
777 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_NOK_IRQ) {
779 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFDFFFF;
784 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) &
785 (IRQ_LAST_FG_COMMAND_DONE | IRQ_LAST_COMMAND_DONE)) {
787 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFFFFF5;
790 ti_lib_int_master_enable();
Default definitions of C compiler quirk work-arounds.
Header file for the energy estimation mechanism.
void watchdog_periodic(void)
Writes the WDT clear sequence.
#define CLOCK_SECOND
A second, measured in system clock time.
static void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
void packetbuf_clear(void)
Clear and reset the packetbuf.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PROCESS_END()
Define the end of a process.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
void process_poll(struct process *p)
Request a process to be polled.
void rf_core_primary_mode_abort()
Abort the currently running primary radio op.
void rf_core_cmd_done_dis(void)
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
void rf_core_init_radio_op(rfc_radioOp_t *op, uint16_t len, uint16_t command)
Prepare a buffer to host a Radio Op.
uint8_t rf_core_stop_rat(void)
Stop the CM0 RAT synchronously.
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
uint32_t rf_core_cmd_status(void)
Get the status of the last issued radio command.
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
rfc_radioOp_t * rf_core_get_last_radio_op()
Returns a pointer to the most recent proto-dependent Radio Op.
int rf_core_power_up()
Turn on power to the RFC and boot it.
uint8_t rf_core_boot()
Boot the RF Core.
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.
uint32_t rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
Convert from RAT timestamp to rtimer ticks.
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
uint8_t rf_core_restart_rat(void)
Restart the CM0 RAT.
void rf_core_primary_mode_register(const rf_core_primary_mode_t *mode)
Register a primary mode for radio operation.
void rf_core_setup_interrupts(void)
Setup RF core interrupts.
uint8_t rf_core_rat_init(void)
Initialize the RAT to RTC conversion machinery.
uint8_t rf_core_primary_mode_restore()
Abort the currently running primary radio op.
uint8_t rf_core_check_rat_overflow(void)
Check if RAT overflow has occured and increment the overflow counter if so.
uint8_t rf_core_start_rat(void)
Start the CM0 RAT.
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
#define RTIMER_NOW()
Get the current clock time.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Header file for the Contiki process interface.
Header file for the CC13xx/CC26xx RF core driver.
Header file with definitions related to RF switch support.
void(* input)(void)
Callback for getting notified of incoming packet.
A data strcuture representing the radio's primary mode of operation.
void(* abort)(void)
A pointer to a function used to abort the current radio op.
int16_t sfd_timestamp_offset
Offset of the end of SFD when compared to the radio HW-generated timestamp.
uint8_t(* restore)(void)
A pointer to a function that will restore the previous radio op.
uint8_t(* is_on)(void)
A pointer to a function that checks if the radio is on.
Header file with macros which rename TI CC26xxware functions.