39 #include "contiki-conf.h"
40 #include "dev/watchdog.h"
51 #include "hw_rfc_dbell.h"
52 #include "hw_rfc_pwr.h"
55 #include "rf-core/api/mailbox.h"
56 #include "rf-core/api/common_cmd.h"
57 #include "rf-core/api/ble_cmd.h"
58 #include "rf-core/api/ieee_cmd.h"
59 #include "rf-core/api/data_entry.h"
60 #include "rf-core/api/ble_mailbox.h"
61 #include "rf-core/api/ieee_mailbox.h"
62 #include "rf-core/api/prop_mailbox.h"
63 #include "rf-core/api/prop_cmd.h"
72 #define PRINTF(...) printf(__VA_ARGS__)
77 #ifdef RF_CORE_CONF_DEBUG_CRC
78 #define RF_CORE_DEBUG_CRC RF_CORE_CONF_DEBUG_CRC
80 #define RF_CORE_DEBUG_CRC DEBUG
84 #define RX_FRAME_IRQ IRQ_RX_ENTRY_DONE
85 #define ERROR_IRQ IRQ_INTERNAL_ERROR
86 #define RX_NOK_IRQ IRQ_RX_NOK
90 #define ENABLED_IRQS (RX_FRAME_IRQ | ERROR_IRQ | RX_NOK_IRQ)
92 #define ENABLED_IRQS (RX_FRAME_IRQ | ERROR_IRQ)
95 #define cc26xx_rf_cpe0_isr RFCCPE0IntHandler
96 #define cc26xx_rf_cpe1_isr RFCCPE1IntHandler
99 static rfc_radioOp_t *last_radio_op =
NULL;
104 PROCESS(rf_core_process,
"CC13xx / CC26xx RF driver");
106 #define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \
107 | RFC_PWR_PWMCLKEN_CPERAM_M)
112 if(ti_lib_prcm_rf_ready()) {
113 return RF_CORE_ACCESSIBLE;
115 return RF_CORE_NOT_ACCESSIBLE;
121 uint32_t timeout_count = 0;
122 bool interrupts_disabled;
123 bool is_radio_op =
false;
129 if((cmd & 0x03) == 0) {
131 cmd_type = ((rfc_command_t *)cmd)->commandNo & RF_CORE_COMMAND_TYPE_MASK;
132 if(cmd_type == RF_CORE_COMMAND_TYPE_IEEE_FG_RADIO_OP ||
133 cmd_type == RF_CORE_COMMAND_TYPE_RADIO_OP) {
135 ((rfc_radioOp_t *)cmd)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
143 interrupts_disabled = ti_lib_int_master_disable();
146 PRINTF(
"rf_core_send_cmd: RF was off\n");
147 if(!interrupts_disabled) {
148 ti_lib_int_master_enable();
150 return RF_CORE_CMD_ERROR;
154 uint16_t command_no = ((rfc_radioOp_t *)cmd)->commandNo;
155 if((command_no & RF_CORE_COMMAND_PROTOCOL_MASK) != RF_CORE_COMMAND_PROTOCOL_COMMON &&
156 (command_no & RF_CORE_COMMAND_TYPE_MASK) == RF_CORE_COMMAND_TYPE_RADIO_OP) {
157 last_radio_op = (rfc_radioOp_t *)cmd;
161 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd;
163 *status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
164 if(++timeout_count > 50000) {
165 PRINTF(
"rf_core_send_cmd: 0x%08lx Timeout\n", cmd);
166 if(!interrupts_disabled) {
167 ti_lib_int_master_enable();
169 return RF_CORE_CMD_ERROR;
171 }
while((*status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_PENDING);
173 if(!interrupts_disabled) {
174 ti_lib_int_master_enable();
181 return (*status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_DONE;
187 volatile rfc_radioOp_t *command = (rfc_radioOp_t *)cmd;
188 uint32_t timeout_cnt = 0;
195 if(++timeout_cnt > 500000) {
196 return RF_CORE_CMD_ERROR;
198 }
while((command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
199 != RF_CORE_RADIO_OP_MASKED_STATUS_DONE);
201 return (command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
202 == RF_CORE_RADIO_OP_STATUS_DONE_OK;
208 rfc_CMD_FS_POWERDOWN_t cmd;
214 PRINTF(
"fs_powerdown: CMDSTA=0x%08lx\n", cmd_status);
215 return RF_CORE_CMD_ERROR;
219 PRINTF(
"fs_powerdown: CMDSTA=0x%08lx, status=0x%04x\n",
220 cmd_status, cmd.status);
221 return RF_CORE_CMD_ERROR;
224 return RF_CORE_CMD_OK;
231 bool interrupts_disabled = ti_lib_int_master_disable();
233 ti_lib_int_pend_clear(INT_RF_CPE0);
234 ti_lib_int_pend_clear(INT_RF_CPE1);
235 ti_lib_int_disable(INT_RF_CPE0);
236 ti_lib_int_disable(INT_RF_CPE1);
239 ti_lib_prcm_power_domain_on(PRCM_DOMAIN_RFCORE);
240 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
241 != PRCM_DOMAIN_POWER_ON);
243 ti_lib_prcm_domain_enable(PRCM_DOMAIN_RFCORE);
244 ti_lib_prcm_load_set();
245 while(!ti_lib_prcm_load_get());
247 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
248 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
249 ti_lib_int_enable(INT_RF_CPE0);
250 ti_lib_int_enable(INT_RF_CPE1);
252 if(!interrupts_disabled) {
253 ti_lib_int_master_enable();
257 HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK;
260 if(
rf_core_send_cmd(CMDR_DIR_CMD(CMD_PING), &cmd_status) != RF_CORE_CMD_OK) {
261 PRINTF(
"rf_core_power_up: CMD_PING fail, CMDSTA=0x%08lx\n", cmd_status);
262 return RF_CORE_CMD_ERROR;
265 return RF_CORE_CMD_OK;
271 bool interrupts_disabled = ti_lib_int_master_disable();
272 ti_lib_int_disable(INT_RF_CPE0);
273 ti_lib_int_disable(INT_RF_CPE1);
276 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
277 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
284 ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE);
285 ti_lib_prcm_load_set();
286 while(!ti_lib_prcm_load_get());
289 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE);
290 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
291 != PRCM_DOMAIN_POWER_OFF);
293 ti_lib_int_pend_clear(INT_RF_CPE0);
294 ti_lib_int_pend_clear(INT_RF_CPE1);
295 ti_lib_int_enable(INT_RF_CPE0);
296 ti_lib_int_enable(INT_RF_CPE1);
297 if(!interrupts_disabled) {
298 ti_lib_int_master_enable();
305 uint8_t rv = RF_CORE_CMD_ERROR;
307 if(ti_lib_chipinfo_chip_family_is_cc26xx()) {
308 if(ti_lib_chipinfo_supports_ble() ==
true &&
309 ti_lib_chipinfo_supports_ieee_802_15_4() ==
true) {
311 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
313 }
else if(ti_lib_chipinfo_supports_ble() ==
false &&
314 ti_lib_chipinfo_supports_ieee_802_15_4() ==
true) {
316 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE2;
319 }
else if(ti_lib_chipinfo_chip_family_is_cc13xx()) {
320 if(ti_lib_chipinfo_supports_ble() ==
false &&
321 ti_lib_chipinfo_supports_ieee_802_15_4() ==
false) {
323 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE3;
339 PRINTF(
"rf_core_apply_patches: START_RAT fail, CMDSTA=0x%08lx\n",
341 return RF_CORE_CMD_ERROR;
344 return RF_CORE_CMD_OK;
351 PRINTF(
"rf_core_boot: rf_core_power_up() failed\n");
355 return RF_CORE_CMD_ERROR;
359 PRINTF(
"rf_core_boot: rf_core_start_rat() failed\n");
363 return RF_CORE_CMD_ERROR;
366 return RF_CORE_CMD_OK;
372 bool interrupts_disabled;
376 PRINTF(
"setup_interrupts: No access\n");
381 interrupts_disabled = ti_lib_int_master_disable();
384 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;
387 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS;
390 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
392 ti_lib_int_pend_clear(INT_RF_CPE0);
393 ti_lib_int_pend_clear(INT_RF_CPE1);
394 ti_lib_int_enable(INT_RF_CPE0);
395 ti_lib_int_enable(INT_RF_CPE1);
397 if(!interrupts_disabled) {
398 ti_lib_int_master_enable();
405 uint32_t irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE;
407 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ENABLED_IRQS;
408 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS | irq;
414 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS;
420 return last_radio_op;
428 op->commandNo = command;
429 op->condition.rule = COND_NEVER;
442 if(primary_mode->
abort) {
443 primary_mode->
abort();
453 return primary_mode->
restore();
457 return RF_CORE_CMD_ERROR;
476 NETSTACK_RDC.input();
486 RIMESTATS_ADD(badcrc);
487 PRINTF(
"RF: Bad CRC\n");
491 cc26xx_rf_cpe1_isr(
void)
493 ENERGEST_ON(ENERGEST_TYPE_IRQ);
495 PRINTF(
"RF Error\n");
504 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x7FFFFFFF;
506 ENERGEST_OFF(ENERGEST_TYPE_IRQ);
510 cc26xx_rf_cpe0_isr(
void)
512 ENERGEST_ON(ENERGEST_TYPE_IRQ);
515 printf(
"RF ISR called but RF not ready... PANIC!!\n");
517 PRINTF(
"rf_core_power_up() failed\n");
522 ti_lib_int_master_disable();
524 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_FRAME_IRQ) {
526 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFF7FFFFF;
530 if(RF_CORE_DEBUG_CRC) {
531 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_NOK_IRQ) {
533 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFDFFFF;
538 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) &
539 (IRQ_LAST_FG_COMMAND_DONE | IRQ_LAST_COMMAND_DONE)) {
541 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFFFFF5;
544 ti_lib_int_master_enable();
546 ENERGEST_OFF(ENERGEST_TYPE_IRQ);
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
void process_poll(struct process *p)
Request a process to be polled.
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
Header file with macros which rename TI CC26xxware functions.
uint8_t(* restore)(void)
A pointer to a function that will restore the previous radio op.
void packetbuf_clear(void)
Clear and reset the packetbuf.
Default definitions of C compiler quirk work-arounds.
#define PROCESS_END()
Define the end of a process.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
void rf_core_primary_mode_abort()
Abort the currently running primary radio op.
Header file for the energy estimation mechanism
Header file for the Rime buffer (packetbuf) management
void rf_core_setup_interrupts()
Setup RF core interrupts.
Header file for the CC13xx/CC26xx RF core driver.
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
#define NULL
The null pointer.
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
uint8_t rf_core_boot()
Boot the RF Core.
void watchdog_periodic(void)
Writes the WDT clear sequence.
void(* abort)(void)
A pointer to a function used to abort the current radio op.
int rf_core_power_up()
Turn on power to the RFC and boot it.
void rf_core_primary_mode_register(const rf_core_primary_mode_t *mode)
Register a primary mode for radio operation.
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Header file for the Contiki process interface.
#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.
Header file for Rime statistics
uint8_t rf_core_primary_mode_restore()
Abort the currently running primary radio op.
uint8_t rf_core_start_rat()
Start the CM0 RAT.
void rf_core_init_radio_op(rfc_radioOp_t *op, uint16_t len, uint16_t command)
Prepare a buffer to host a Radio Op.
void rf_core_cmd_done_dis()
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
Include file for the Contiki low-layer network stack (NETSTACK)
A data strcuture representing the radio's primary mode of operation.
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.
#define PROCESS_BEGIN()
Define the beginning of a process.