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 94 typedef ChipType_t chip_type_t;
97 static 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) 111 static int32_t rat_offset;
112 static bool rat_offset_known;
115 static uint32_t rat_last_value;
118 static struct ctimer rat_overflow_timer;
119 static volatile uint32_t rat_overflow_counter;
120 static rtimer_clock_t rat_last_overflow;
122 static void rat_overflow_check_timer_cb(
void *);
124 volatile int8_t rf_core_last_rssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
125 volatile uint8_t rf_core_last_corr_lqi = 0;
126 volatile uint32_t rf_core_last_packet_timestamp = 0;
129 uint8_t rf_core_poll_mode = 0;
132 volatile bool rf_core_rx_is_full =
false;
134 PROCESS(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;
164 if((cmd & 0x03) == 0) {
166 cmd_type = ((rfc_command_t *)cmd)->commandNo & RF_CORE_COMMAND_TYPE_MASK;
167 if(cmd_type == RF_CORE_COMMAND_TYPE_IEEE_FG_RADIO_OP ||
168 cmd_type == RF_CORE_COMMAND_TYPE_RADIO_OP) {
170 ((rfc_radioOp_t *)cmd)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
178 interrupts_disabled = ti_lib_int_master_disable();
181 PRINTF(
"rf_core_send_cmd: RF was off\n");
182 if(!interrupts_disabled) {
183 ti_lib_int_master_enable();
185 return RF_CORE_CMD_ERROR;
189 uint16_t command_no = ((rfc_radioOp_t *)cmd)->commandNo;
190 if((command_no & RF_CORE_COMMAND_PROTOCOL_MASK) != RF_CORE_COMMAND_PROTOCOL_COMMON &&
191 (command_no & RF_CORE_COMMAND_TYPE_MASK) == RF_CORE_COMMAND_TYPE_RADIO_OP) {
192 last_radio_op = (rfc_radioOp_t *)cmd;
196 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd;
198 *status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
199 if(++timeout_count > 50000) {
200 PRINTF(
"rf_core_send_cmd: 0x%08lx Timeout\n", cmd);
201 if(!interrupts_disabled) {
202 ti_lib_int_master_enable();
204 return RF_CORE_CMD_ERROR;
206 }
while((*status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_PENDING);
208 if(!interrupts_disabled) {
209 ti_lib_int_master_enable();
216 return (*status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_DONE;
222 volatile rfc_radioOp_t *command = (rfc_radioOp_t *)cmd;
223 uint32_t timeout_cnt = 0;
230 if(++timeout_cnt > 500000) {
231 return RF_CORE_CMD_ERROR;
233 }
while((command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
234 != RF_CORE_RADIO_OP_MASKED_STATUS_DONE);
236 return (command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
237 == RF_CORE_RADIO_OP_STATUS_DONE_OK;
243 rfc_CMD_FS_POWERDOWN_t cmd;
249 PRINTF(
"fs_powerdown: CMDSTA=0x%08lx\n", cmd_status);
250 return RF_CORE_CMD_ERROR;
254 PRINTF(
"fs_powerdown: CMDSTA=0x%08lx, status=0x%04x\n",
255 cmd_status, cmd.status);
256 return RF_CORE_CMD_ERROR;
259 return RF_CORE_CMD_OK;
266 bool interrupts_disabled = ti_lib_int_master_disable();
268 ti_lib_int_pend_clear(INT_RFC_CPE_0);
269 ti_lib_int_pend_clear(INT_RFC_CPE_1);
270 ti_lib_int_disable(INT_RFC_CPE_0);
271 ti_lib_int_disable(INT_RFC_CPE_1);
274 ti_lib_prcm_power_domain_on(PRCM_DOMAIN_RFCORE);
275 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
276 != PRCM_DOMAIN_POWER_ON);
278 ti_lib_prcm_domain_enable(PRCM_DOMAIN_RFCORE);
279 ti_lib_prcm_load_set();
280 while(!ti_lib_prcm_load_get());
282 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
283 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
284 ti_lib_int_enable(INT_RFC_CPE_0);
285 ti_lib_int_enable(INT_RFC_CPE_1);
287 if(!interrupts_disabled) {
288 ti_lib_int_master_enable();
291 rf_switch_power_up();
294 HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK;
297 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
298 HWREG(RFC_DBELL_BASE+RFC_DBELL_O_CMDR) =
299 CMDR_DIR_CMD_2BYTE(RF_CMD0,
300 RFC_PWR_PWMCLKEN_MDMRAM | RFC_PWR_PWMCLKEN_RFERAM);
303 if(
rf_core_send_cmd(CMDR_DIR_CMD(CMD_PING), &cmd_status) != RF_CORE_CMD_OK) {
304 PRINTF(
"rf_core_power_up: CMD_PING fail, CMDSTA=0x%08lx\n", cmd_status);
305 return RF_CORE_CMD_ERROR;
308 return RF_CORE_CMD_OK;
315 rfc_CMD_SYNC_START_RAT_t cmd_start;
321 cmd_start.rat0 = rat_offset;
324 PRINTF(
"rf_core_get_rat_rtc_offset: SYNC_START_RAT fail, CMDSTA=0x%08lx\n",
326 return RF_CORE_CMD_ERROR;
331 PRINTF(
"rf_core_cmd_ok: SYNC_START_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
332 cmd_status, cmd_start.status);
333 return RF_CORE_CMD_ERROR;
336 return RF_CORE_CMD_OK;
342 rfc_CMD_SYNC_STOP_RAT_t cmd_stop;
348 if(ret != RF_CORE_CMD_OK) {
349 PRINTF(
"rf_core_get_rat_rtc_offset: SYNC_STOP_RAT fail, ret %d CMDSTA=0x%08lx\n",
356 if(ret != RF_CORE_CMD_OK) {
357 PRINTF(
"rf_core_cmd_ok: SYNC_STOP_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
358 cmd_status, cmd_stop.status);
362 if(!rat_offset_known) {
364 rat_offset_known =
true;
365 rat_offset = cmd_stop.rat0;
368 return RF_CORE_CMD_OK;
374 bool interrupts_disabled = ti_lib_int_master_disable();
375 ti_lib_int_disable(INT_RFC_CPE_0);
376 ti_lib_int_disable(INT_RFC_CPE_1);
379 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
380 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
389 ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE);
390 ti_lib_prcm_load_set();
391 while(!ti_lib_prcm_load_get());
394 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE);
395 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
396 != PRCM_DOMAIN_POWER_OFF);
398 rf_switch_power_down();
400 ti_lib_int_pend_clear(INT_RFC_CPE_0);
401 ti_lib_int_pend_clear(INT_RFC_CPE_1);
402 ti_lib_int_enable(INT_RFC_CPE_0);
403 ti_lib_int_enable(INT_RFC_CPE_1);
404 if(!interrupts_disabled) {
405 ti_lib_int_master_enable();
412 uint8_t rv = RF_CORE_CMD_ERROR;
413 chip_type_t chip_type = ti_lib_chipinfo_get_chip_type();
415 if(chip_type == CHIP_TYPE_CC2650) {
416 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
418 }
else if(chip_type == CHIP_TYPE_CC2630) {
419 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE2;
421 }
else if(chip_type == CHIP_TYPE_CC1310) {
422 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE3;
424 }
else if(chip_type == CHIP_TYPE_CC1350) {
425 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
427 #if CPU_FAMILY_CC26X0R2 428 }
else if(chip_type == CHIP_TYPE_CC2640R2) {
429 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE1;
441 PRINTF(
"rf_core_boot: rf_core_power_up() failed\n");
445 return RF_CORE_CMD_ERROR;
449 PRINTF(
"rf_core_boot: rf_core_start_rat() failed\n");
453 return RF_CORE_CMD_ERROR;
456 return RF_CORE_CMD_OK;
463 PRINTF(
"rf_core_restart_rat: rf_core_stop_rat() failed\n");
468 PRINTF(
"rf_core_restart_rat: rf_core_start_rat() failed\n");
472 return RF_CORE_CMD_ERROR;
475 return RF_CORE_CMD_OK;
481 bool interrupts_disabled;
482 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
486 PRINTF(
"setup_interrupts: No access\n");
491 interrupts_disabled = ti_lib_int_master_disable();
494 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;
497 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
500 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
502 ti_lib_int_pend_clear(INT_RFC_CPE_0);
503 ti_lib_int_pend_clear(INT_RFC_CPE_1);
504 ti_lib_int_enable(INT_RFC_CPE_0);
505 ti_lib_int_enable(INT_RFC_CPE_1);
507 if(!interrupts_disabled) {
508 ti_lib_int_master_enable();
516 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
518 if(!rf_core_poll_mode) {
519 irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE;
522 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = enabled_irqs;
523 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs | irq;
529 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
530 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
536 return last_radio_op;
544 op->commandNo = command;
545 op->condition.rule = COND_NEVER;
558 if(primary_mode->
abort) {
559 primary_mode->
abort();
569 return primary_mode->
restore();
573 return RF_CORE_CMD_ERROR;
579 rat_last_value = HWREG(RFC_RAT_BASE + RATCNT);
581 ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_TIMER_INTERVAL,
582 rat_overflow_check_timer_cb, NULL);
590 uint32_t rat_current_value;
591 uint8_t interrupts_disabled;
594 if(primary_mode == NULL || !primary_mode->
is_on()) {
598 interrupts_disabled = ti_lib_int_master_disable();
600 rat_current_value = HWREG(RFC_RAT_BASE + RATCNT);
601 if(rat_current_value + RAT_RANGE / 4 < rat_last_value) {
604 rat_overflow_counter++;
606 rat_last_value = rat_current_value;
608 if(!interrupts_disabled) {
609 ti_lib_int_master_enable();
616 rat_overflow_check_timer_cb(
void *unused)
621 if(primary_mode != NULL) {
623 if(!primary_mode->
is_on()) {
625 if(NETSTACK_RADIO.on() != RF_CORE_CMD_OK) {
626 PRINTF(
"overflow: on() failed\n");
628 rat_overflow_check_timer_cb, NULL);
636 NETSTACK_RADIO.off();
642 ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_TIMER_INTERVAL,
643 rat_overflow_check_timer_cb, NULL);
647 rat_overflow_check_timer_cb, NULL);
654 uint64_t rat_timestamp64;
655 uint32_t adjusted_overflow_counter;
658 if(primary_mode == NULL) {
659 PRINTF(
"rf_core_convert_rat_to_rtimer: not initialized\n");
663 if(!primary_mode->
is_on()) {
671 NETSTACK_RADIO.off();
674 adjusted_overflow_counter = rat_overflow_counter;
678 if(rat_timestamp > (uint32_t)(RAT_RANGE * 3 / 4)) {
680 rat_last_overflow + RAT_OVERFLOW_PERIOD_SECONDS * RTIMER_SECOND / 4)) {
681 adjusted_overflow_counter--;
686 rat_timestamp64 = rat_timestamp + RAT_RANGE * adjusted_overflow_counter;
690 return RADIO_TO_RTIMER(rat_timestamp64 - rat_offset);
709 NETSTACK_MAC.
input();
722 cc26xx_rf_cpe1_isr(
void)
724 PRINTF(
"RF Error\n");
732 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_RX_BUF_FULL) {
733 PRINTF(
"\nRF: BUF_FULL\n\n");
735 rf_core_rx_is_full =
true;
739 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ~(IRQ_RX_BUF_FULL);
743 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x7FFFFFFF;
747 cc26xx_rf_cpe0_isr(
void)
750 printf(
"RF ISR called but RF not ready... PANIC!!\n");
752 PRINTF(
"rf_core_power_up() failed\n");
757 ti_lib_int_master_disable();
759 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_FRAME_IRQ) {
761 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFF7FFFFF;
765 if(RF_CORE_DEBUG_CRC) {
766 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_NOK_IRQ) {
768 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFDFFFF;
773 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) &
774 (IRQ_LAST_FG_COMMAND_DONE | IRQ_LAST_COMMAND_DONE)) {
776 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFFFFF5;
779 ti_lib_int_master_enable();
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
#define PROCESS(name, strname)
Declare a process.
Header file with macros which rename TI CC26xxware functions.
void packetbuf_clear(void)
Clear and reset the packetbuf.
Header file for the energy estimation mechanism
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
rfc_radioOp_t * rf_core_get_last_radio_op()
Returns a pointer to the most recent proto-dependent Radio Op.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PROCESS_END()
Define the end of a process.
int rf_core_power_up()
Turn on power to the RFC and boot it.
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
Header file for the CC13xx/CC26xx RF core driver.
void rf_core_primary_mode_abort()
Abort the currently running primary radio op.
int16_t sfd_timestamp_offset
Offset of the end of SFD when compared to the radio HW-generated timestamp.
#define RTIMER_NOW()
Get the current clock time.
uint32_t rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
Convert from RAT timestamp to rtimer ticks.
#define CLOCK_SECOND
A second, measured in system clock time.
void(* input)(void)
Callback for getting notified of incoming packet.
void rf_core_primary_mode_register(const rf_core_primary_mode_t *mode)
Register a primary mode for radio operation.
A data strcuture representing the radio's primary mode of operation.
uint8_t(* is_on)(void)
A pointer to a function that checks if the radio is on.
void process_poll(struct process *p)
Request a process to be polled.
uint8_t rf_core_rat_init(void)
Initialize the RAT to RTC conversion machinery.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
void rf_core_cmd_done_dis(void)
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
Header file for the Contiki process interface.
uint8_t(* restore)(void)
A pointer to a function that will restore the previous radio op.
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_primary_mode_restore()
Abort the currently running primary radio op.
Header file with definitions related to RF switch support.
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
void(* abort)(void)
A pointer to a function used to abort the current radio op.
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
Header file for the Packet buffer (packetbuf) management
void rf_core_setup_interrupts(void)
Setup RF core interrupts.
Include file for the Contiki low-layer network stack (NETSTACK)
uint8_t rf_core_start_rat(void)
Start the CM0 RAT.
void watchdog_periodic(void)
Writes the WDT clear sequence.
uint8_t rf_core_restart_rat(void)
Restart the CM0 RAT.
Default definitions of C compiler quirk work-arounds.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
uint8_t rf_core_boot()
Boot the RF Core.
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
uint8_t rf_core_stop_rat(void)
Stop the CM0 RAT synchronously.
uint8_t rf_core_check_rat_overflow(void)
Check if RAT overflow has occured and increment the overflow counter if so.
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.