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 int32_t rat_offset = 0;
104 static bool rat_offset_known =
false;
107 volatile bool rx_is_full =
false;
109 PROCESS(rf_core_process,
"CC13xx / CC26xx RF driver");
111 #define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \ 112 | RFC_PWR_PWMCLKEN_CPERAM_M | RFC_PWR_PWMCLKEN_FSCA_M \ 113 | RFC_PWR_PWMCLKEN_PHA_M | RFC_PWR_PWMCLKEN_RAT_M \ 114 | RFC_PWR_PWMCLKEN_RFERAM_M | RFC_PWR_PWMCLKEN_RFE_M \ 115 | RFC_PWR_PWMCLKEN_MDMRAM_M | RFC_PWR_PWMCLKEN_MDM_M) 117 #define RF_CMD0 0x0607 122 if(ti_lib_prcm_rf_ready()) {
123 return RF_CORE_ACCESSIBLE;
125 return RF_CORE_NOT_ACCESSIBLE;
131 uint32_t timeout_count = 0;
132 bool interrupts_disabled;
133 bool is_radio_op =
false;
139 if((cmd & 0x03) == 0) {
141 cmd_type = ((rfc_command_t *)cmd)->commandNo & RF_CORE_COMMAND_TYPE_MASK;
142 if(cmd_type == RF_CORE_COMMAND_TYPE_IEEE_FG_RADIO_OP ||
143 cmd_type == RF_CORE_COMMAND_TYPE_RADIO_OP) {
145 ((rfc_radioOp_t *)cmd)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
153 interrupts_disabled = ti_lib_int_master_disable();
156 PRINTF(
"rf_core_send_cmd: RF was off\n");
157 if(!interrupts_disabled) {
158 ti_lib_int_master_enable();
160 return RF_CORE_CMD_ERROR;
164 uint16_t command_no = ((rfc_radioOp_t *)cmd)->commandNo;
165 if((command_no & RF_CORE_COMMAND_PROTOCOL_MASK) != RF_CORE_COMMAND_PROTOCOL_COMMON &&
166 (command_no & RF_CORE_COMMAND_TYPE_MASK) == RF_CORE_COMMAND_TYPE_RADIO_OP) {
167 last_radio_op = (rfc_radioOp_t *)cmd;
171 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd;
173 *status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
174 if(++timeout_count > 50000) {
175 PRINTF(
"rf_core_send_cmd: 0x%08lx Timeout\n", cmd);
176 if(!interrupts_disabled) {
177 ti_lib_int_master_enable();
179 return RF_CORE_CMD_ERROR;
181 }
while((*status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_PENDING);
183 if(!interrupts_disabled) {
184 ti_lib_int_master_enable();
191 return (*status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_DONE;
197 volatile rfc_radioOp_t *command = (rfc_radioOp_t *)cmd;
198 uint32_t timeout_cnt = 0;
205 if(++timeout_cnt > 500000) {
206 return RF_CORE_CMD_ERROR;
208 }
while((command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
209 != RF_CORE_RADIO_OP_MASKED_STATUS_DONE);
211 return (command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
212 == RF_CORE_RADIO_OP_STATUS_DONE_OK;
218 rfc_CMD_FS_POWERDOWN_t cmd;
224 PRINTF(
"fs_powerdown: CMDSTA=0x%08lx\n", cmd_status);
225 return RF_CORE_CMD_ERROR;
229 PRINTF(
"fs_powerdown: CMDSTA=0x%08lx, status=0x%04x\n",
230 cmd_status, cmd.status);
231 return RF_CORE_CMD_ERROR;
234 return RF_CORE_CMD_OK;
241 bool interrupts_disabled = ti_lib_int_master_disable();
243 ti_lib_int_pend_clear(INT_RFC_CPE_0);
244 ti_lib_int_pend_clear(INT_RFC_CPE_1);
245 ti_lib_int_disable(INT_RFC_CPE_0);
246 ti_lib_int_disable(INT_RFC_CPE_1);
249 ti_lib_prcm_power_domain_on(PRCM_DOMAIN_RFCORE);
250 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
251 != PRCM_DOMAIN_POWER_ON);
253 ti_lib_prcm_domain_enable(PRCM_DOMAIN_RFCORE);
254 ti_lib_prcm_load_set();
255 while(!ti_lib_prcm_load_get());
257 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
258 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
259 ti_lib_int_enable(INT_RFC_CPE_0);
260 ti_lib_int_enable(INT_RFC_CPE_1);
262 if(!interrupts_disabled) {
263 ti_lib_int_master_enable();
266 rf_switch_power_up();
269 HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK;
272 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
273 HWREG(RFC_DBELL_BASE+RFC_DBELL_O_CMDR) =
274 CMDR_DIR_CMD_2BYTE(RF_CMD0,
275 RFC_PWR_PWMCLKEN_MDMRAM | RFC_PWR_PWMCLKEN_RFERAM);
278 if(
rf_core_send_cmd(CMDR_DIR_CMD(CMD_PING), &cmd_status) != RF_CORE_CMD_OK) {
279 PRINTF(
"rf_core_power_up: CMD_PING fail, CMDSTA=0x%08lx\n", cmd_status);
280 return RF_CORE_CMD_ERROR;
283 return RF_CORE_CMD_OK;
290 rfc_CMD_SYNC_START_RAT_t cmd_start;
296 cmd_start.rat0 = rat_offset;
299 PRINTF(
"rf_core_get_rat_rtc_offset: SYNC_START_RAT fail, CMDSTA=0x%08lx\n",
301 return RF_CORE_CMD_ERROR;
306 PRINTF(
"rf_core_cmd_ok: SYNC_START_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
307 cmd_status, cmd_start.status);
308 return RF_CORE_CMD_ERROR;
311 return RF_CORE_CMD_OK;
317 rfc_CMD_SYNC_STOP_RAT_t cmd_stop;
323 if(ret != RF_CORE_CMD_OK) {
324 PRINTF(
"rf_core_get_rat_rtc_offset: SYNC_STOP_RAT fail, ret %d CMDSTA=0x%08lx\n",
331 if(ret != RF_CORE_CMD_OK) {
332 PRINTF(
"rf_core_cmd_ok: SYNC_STOP_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
333 cmd_status, cmd_stop.status);
337 if(!rat_offset_known) {
339 rat_offset_known =
true;
340 rat_offset = cmd_stop.rat0;
343 return RF_CORE_CMD_OK;
349 bool interrupts_disabled = ti_lib_int_master_disable();
350 ti_lib_int_disable(INT_RFC_CPE_0);
351 ti_lib_int_disable(INT_RFC_CPE_1);
354 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
355 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
364 ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE);
365 ti_lib_prcm_load_set();
366 while(!ti_lib_prcm_load_get());
369 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE);
370 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
371 != PRCM_DOMAIN_POWER_OFF);
373 rf_switch_power_down();
375 ti_lib_int_pend_clear(INT_RFC_CPE_0);
376 ti_lib_int_pend_clear(INT_RFC_CPE_1);
377 ti_lib_int_enable(INT_RFC_CPE_0);
378 ti_lib_int_enable(INT_RFC_CPE_1);
379 if(!interrupts_disabled) {
380 ti_lib_int_master_enable();
387 uint8_t rv = RF_CORE_CMD_ERROR;
388 chip_type_t chip_type = ti_lib_chipinfo_get_chip_type();
390 if(chip_type == CHIP_TYPE_CC2650) {
391 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
393 }
else if(chip_type == CHIP_TYPE_CC2630) {
394 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE2;
396 }
else if(chip_type == CHIP_TYPE_CC1310) {
397 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE3;
399 }
else if(chip_type == CHIP_TYPE_CC1350) {
400 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
411 PRINTF(
"rf_core_boot: rf_core_power_up() failed\n");
415 return RF_CORE_CMD_ERROR;
419 PRINTF(
"rf_core_boot: rf_core_start_rat() failed\n");
423 return RF_CORE_CMD_ERROR;
426 return RF_CORE_CMD_OK;
433 PRINTF(
"rf_core_restart_rat: rf_core_stop_rat() failed\n");
438 PRINTF(
"rf_core_restart_rat: rf_core_start_rat() failed\n");
442 return RF_CORE_CMD_ERROR;
445 return RF_CORE_CMD_OK;
451 bool interrupts_disabled;
452 const uint32_t enabled_irqs = poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
456 PRINTF(
"setup_interrupts: No access\n");
461 interrupts_disabled = ti_lib_int_master_disable();
464 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;
467 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
470 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
472 ti_lib_int_pend_clear(INT_RFC_CPE_0);
473 ti_lib_int_pend_clear(INT_RFC_CPE_1);
474 ti_lib_int_enable(INT_RFC_CPE_0);
475 ti_lib_int_enable(INT_RFC_CPE_1);
477 if(!interrupts_disabled) {
478 ti_lib_int_master_enable();
485 uint32_t irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE;
486 const uint32_t enabled_irqs = poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
488 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = enabled_irqs;
489 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs | irq;
495 const uint32_t enabled_irqs = poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
496 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
502 return last_radio_op;
510 op->commandNo = command;
511 op->condition.rule = COND_NEVER;
524 if(primary_mode->
abort) {
525 primary_mode->
abort();
535 return primary_mode->
restore();
539 return RF_CORE_CMD_ERROR;
558 NETSTACK_MAC.
input();
571 cc26xx_rf_cpe1_isr(
void)
573 PRINTF(
"RF Error\n");
581 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_RX_BUF_FULL) {
582 PRINTF(
"\nRF: BUF_FULL\n\n");
588 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ~(IRQ_RX_BUF_FULL);
592 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x7FFFFFFF;
596 cc26xx_rf_cpe0_isr(
void)
599 printf(
"RF ISR called but RF not ready... PANIC!!\n");
601 PRINTF(
"rf_core_power_up() failed\n");
606 ti_lib_int_master_disable();
608 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_FRAME_IRQ) {
610 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFF7FFFFF;
614 if(RF_CORE_DEBUG_CRC) {
615 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_NOK_IRQ) {
617 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFDFFFF;
622 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) &
623 (IRQ_LAST_FG_COMMAND_DONE | IRQ_LAST_COMMAND_DONE)) {
625 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFFFFF5;
628 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.
void rf_core_setup_interrupts(bool poll_mode)
Setup RF core interrupts.
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.
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.
void rf_core_cmd_done_dis(bool poll_mode)
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
A data strcuture representing the radio's primary mode of operation.
void process_poll(struct process *p)
Request a process to be polled.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
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.
void rf_core_cmd_done_en(bool fg, bool poll_mode)
Enable interrupt on command done.
Header file for the Packet buffer (packetbuf) management
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 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.
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.