41 #include "dev/watchdog.h" 49 #include "lib/random.h" 51 #include <ti/devices/DeviceFamily.h> 52 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h) 53 #include DeviceFamily_constructPath(driverlib/rf_mailbox.h) 54 #include DeviceFamily_constructPath(driverlib/rf_ble_mailbox.h) 56 #include <ti/drivers/rf/RF.h> 69 #define LOG_MODULE "Radio" 70 #define LOG_LEVEL LOG_LEVEL_NONE 72 #define CMD_FS_RETRIES 3 74 #define RF_EVENTS_CMD_DONE (RF_EventCmdDone | RF_EventLastCmdDone | \ 75 RF_EventFGCmdDone | RF_EventLastFGCmdDone) 77 #define CMD_STATUS(cmd) (CC_ACCESS_NOW(RF_Op, cmd).status) 79 #define CMD_HANDLE_OK(handle) (((handle) != RF_ALLOC_ERROR) && \ 80 ((handle) != RF_SCHEDULE_CMD_ERROR)) 82 #define EVENTS_CMD_DONE(events) (((events) & RF_EVENTS_CMD_DONE) != 0) 85 #define BLE_ADV_CHANNEL_MIN 37 86 #define BLE_ADV_CHANNEL_MAX 39 89 #define NUM_BLE_ADV_CHANNELS (BLE_ADV_CHANNEL_MAX - BLE_ADV_CHANNEL_MIN + 1) 92 #define SYNTH_RECAL_INTERVAL (CLOCK_SECOND * 60 * 3) 94 #define SYNTH_RECAL_JITTER (CLOCK_SECOND * 10) 96 static struct etimer synth_recal_timer;
98 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X0_CC26X0) 99 typedef rfc_CMD_BLE_ADV_NC_t ble_cmd_adv_nc_t;
100 #elif (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X2_CC26X2) 101 typedef rfc_CMD_BLE5_ADV_NC_t ble_cmd_adv_nc_t;
104 static RF_Object rf_netstack;
106 #if RF_CONF_BLE_BEACON_ENABLE 107 static RF_Object rf_ble;
110 static RF_CmdHandle cmd_rx_handle;
113 static volatile bool rx_buf_full;
116 cmd_rx_cb(RF_Handle client, RF_CmdHandle command, RF_EventMask events)
122 if(events & RF_EventRxEntryDone) {
126 if(events & RF_EventRxBufFull) {
132 static inline clock_time_t
133 synth_recal_interval(
void)
139 return SYNTH_RECAL_INTERVAL + (
random_rand() % SYNTH_RECAL_JITTER) - (SYNTH_RECAL_JITTER / 2);
143 cmd_rx_is_active(
void)
149 const uint16_t status = CMD_STATUS(netstack_cmd_rx);
150 return (status == ACTIVE) ||
157 const bool is_active = cmd_rx_is_active();
160 CMD_STATUS(netstack_cmd_rx) = DONE_STOPPED;
161 RF_cancelCmd(&rf_netstack, cmd_rx_handle, RF_ABORT_GRACEFULLY);
165 return (uint_fast8_t)is_active;
169 cmd_rx_restore(uint_fast8_t rx_key)
171 const bool was_active = (rx_key != 0) ?
true :
false;
177 RF_ScheduleCmdParams sched_params;
178 RF_ScheduleCmdParams_init(&sched_params);
180 sched_params.priority = RF_PriorityNormal;
181 sched_params.endTime = 0;
182 sched_params.allowDelay = RF_AllowDelayAny;
184 CMD_STATUS(netstack_cmd_rx) = PENDING;
186 cmd_rx_handle = RF_scheduleCmd(
188 (RF_Op *)&netstack_cmd_rx,
191 RF_EventRxEntryDone | RF_EventRxBufFull);
193 if(!CMD_HANDLE_OK(cmd_rx_handle)) {
194 LOG_ERR(
"Unable to restore RX command, handle=%d status=0x%04x",
195 cmd_rx_handle, CMD_STATUS(netstack_cmd_rx));
196 return RF_RESULT_ERROR;
206 RF_flushCmd(&rf_netstack, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY);
207 #if RF_CONF_BLE_BEACON_ENABLE 208 RF_flushCmd(&rf_ble, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY);
212 RF_yield(&rf_netstack);
213 #if RF_CONF_BLE_BEACON_ENABLE 217 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
226 rf_set_tx_power(RF_Handle handle, RF_TxPowerTable_Entry *table, int8_t dbm)
228 const RF_Stat stat = RF_setTxPower(handle, RF_TxPowerTable_findValue(table, dbm));
230 return (stat == RF_StatSuccess)
236 rf_get_tx_power(RF_Handle handle, RF_TxPowerTable_Entry *table, int8_t *dbm)
238 *dbm = RF_TxPowerTable_findPowerLevel(table, RF_getTxPower(handle));
240 return (*dbm != RF_TxPowerTable_INVALID_DBM)
246 netstack_open(RF_Params *params)
248 return RF_open(&rf_netstack, &netstack_mode, (RF_RadioSetup *)&netstack_cmd_radio_setup, params);
252 netstack_sched_fs(
void)
254 const uint_fast8_t rx_key = cmd_rx_disable();
264 #if (RF_MODE == RF_CORE_MODE_2_4_GHZ) 266 cmd_rx_restore(rx_key);
272 bool synth_error =
false;
273 uint8_t num_tries = 0;
276 CMD_STATUS(netstack_cmd_fs) = PENDING;
280 (RF_Op *)&netstack_cmd_fs,
285 synth_error = (EVENTS_CMD_DONE(events)) && (CMD_STATUS(netstack_cmd_fs) == ERROR_SYNTH_PROG);
287 }
while(synth_error && (num_tries++ < CMD_FS_RETRIES));
289 cmd_rx_restore(rx_key);
291 return (CMD_STATUS(netstack_cmd_fs) == DONE_OK)
297 netstack_sched_ieee_tx(
bool ack_request)
301 RF_ScheduleCmdParams sched_params;
302 RF_ScheduleCmdParams_init(&sched_params);
304 sched_params.priority = RF_PriorityNormal;
305 sched_params.endTime = 0;
306 sched_params.allowDelay = RF_AllowDelayAny;
308 const bool rx_is_active = cmd_rx_is_active();
309 const bool rx_needed = (ack_request && !rx_is_active);
317 res = netstack_sched_rx(
false);
318 if(res != RF_RESULT_OK) {
323 CMD_STATUS(netstack_cmd_tx) = PENDING;
325 RF_CmdHandle tx_handle = RF_scheduleCmd(
327 (RF_Op *)&netstack_cmd_tx,
332 if(!CMD_HANDLE_OK(tx_handle)) {
333 LOG_ERR(
"Unable to schedule TX command, handle=%d status=0x%04x\n",
334 tx_handle, CMD_STATUS(netstack_cmd_tx));
335 return RF_RESULT_ERROR;
339 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
341 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
345 RF_EventMask tx_events = RF_pendCmd(&rf_netstack, tx_handle, 0);
353 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
355 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
358 if(!EVENTS_CMD_DONE(tx_events)) {
359 LOG_ERR(
"Pending on TX comand generated error, events=0x%08llx status=0x%04x\n",
360 tx_events, CMD_STATUS(netstack_cmd_tx));
361 return RF_RESULT_ERROR;
368 netstack_sched_prop_tx(
void)
370 RF_ScheduleCmdParams sched_params;
371 RF_ScheduleCmdParams_init(&sched_params);
373 sched_params.priority = RF_PriorityNormal;
374 sched_params.endTime = 0;
375 sched_params.allowDelay = RF_AllowDelayAny;
377 CMD_STATUS(netstack_cmd_tx) = PENDING;
379 RF_CmdHandle tx_handle = RF_scheduleCmd(
381 (RF_Op *)&netstack_cmd_tx,
386 if(!CMD_HANDLE_OK(tx_handle)) {
387 LOG_ERR(
"Unable to schedule TX command, handle=%d status=0x%04x\n",
388 tx_handle, CMD_STATUS(netstack_cmd_tx));
389 return RF_RESULT_ERROR;
396 const bool rx_key = cmd_rx_disable();
399 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
401 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
405 RF_EventMask tx_events = RF_pendCmd(&rf_netstack, tx_handle, 0);
407 cmd_rx_restore(rx_key);
410 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
412 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
415 if(!EVENTS_CMD_DONE(tx_events)) {
416 LOG_ERR(
"Pending on scheduled TX command generated error, events=0x%08llx status=0x%04x\n",
417 tx_events, CMD_STATUS(netstack_cmd_tx));
418 return RF_RESULT_ERROR;
425 netstack_sched_rx(
bool start)
427 if(cmd_rx_is_active()) {
428 LOG_WARN(
"Already in RX when scheduling RX\n");
432 RF_ScheduleCmdParams sched_params;
433 RF_ScheduleCmdParams_init(&sched_params);
435 sched_params.priority = RF_PriorityNormal;
436 sched_params.endTime = 0;
437 sched_params.allowDelay = RF_AllowDelayAny;
439 CMD_STATUS(netstack_cmd_rx) = PENDING;
441 cmd_rx_handle = RF_scheduleCmd(
443 (RF_Op *)&netstack_cmd_rx,
446 RF_EventRxEntryDone | RF_EventRxBufFull);
448 if(!CMD_HANDLE_OK(cmd_rx_handle)) {
449 LOG_ERR(
"Unable to schedule RX command, handle=%d status=0x%04x\n",
450 cmd_rx_handle, CMD_STATUS(netstack_cmd_rx));
451 return RF_RESULT_ERROR;
454 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
465 netstack_stop_rx(
void)
467 if(!cmd_rx_is_active()) {
468 LOG_WARN(
"RX not active when stopping RX\n");
472 CMD_STATUS(netstack_cmd_rx) = DONE_STOPPED;
473 const RF_Stat stat = RF_cancelCmd(&rf_netstack, cmd_rx_handle, RF_ABORT_GRACEFULLY);
476 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
478 return (stat == RF_StatSuccess)
484 ble_open(RF_Params *params)
486 #if RF_CONF_BLE_BEACON_ENABLE 487 return RF_open(&rf_ble, &ble_mode, (RF_RadioSetup *)&ble_cmd_radio_setup, params);
490 return (RF_Handle)NULL;
494 #if RF_CONF_BLE_BEACON_ENABLE 496 init_ble_adv_array(ble_cmd_adv_nc_t *ble_adv_array, uint8_t bm_channel)
498 RF_Op *first_ble_adv = NULL;
499 ble_cmd_adv_nc_t *cmd_adv_37 = &ble_adv_array[0];
500 ble_cmd_adv_nc_t *cmd_adv_38 = &ble_adv_array[1];
501 ble_cmd_adv_nc_t *cmd_adv_39 = &ble_adv_array[2];
504 if(bm_channel & BLE_ADV_CHANNEL_37) {
506 memcpy(cmd_adv_37, &ble_cmd_adv_nc,
sizeof(ble_cmd_adv_nc));
508 cmd_adv_37->channel = 37;
510 cmd_adv_37->whitening.init = 0x65;
517 if(bm_channel & BLE_ADV_CHANNEL_38) {
518 cmd_adv_37->pNextOp = (RF_Op *)cmd_adv_38;
519 cmd_adv_37->condition.rule = COND_ALWAYS;
520 }
else if(bm_channel & BLE_ADV_CHANNEL_39) {
521 cmd_adv_37->pNextOp = (RF_Op *)cmd_adv_39;
522 cmd_adv_37->condition.rule = COND_ALWAYS;
524 cmd_adv_37->pNextOp = NULL;
525 cmd_adv_37->condition.rule = COND_NEVER;
529 first_ble_adv = (RF_Op *)cmd_adv_37;
533 if(bm_channel & BLE_ADV_CHANNEL_38) {
534 memcpy(cmd_adv_38, &ble_cmd_adv_nc,
sizeof(ble_cmd_adv_nc));
536 cmd_adv_38->channel = 38;
538 cmd_adv_38->whitening.init = 0x66;
544 if(bm_channel & BLE_ADV_CHANNEL_39) {
545 cmd_adv_38->pNextOp = (RF_Op *)cmd_adv_39;
546 cmd_adv_38->condition.rule = COND_ALWAYS;
548 cmd_adv_38->pNextOp = NULL;
549 cmd_adv_38->condition.rule = COND_NEVER;
556 if(first_ble_adv == NULL) {
557 first_ble_adv = (RF_Op *)cmd_adv_38;
562 if(bm_channel & BLE_ADV_CHANNEL_39) {
563 memcpy(cmd_adv_39, &ble_cmd_adv_nc,
sizeof(ble_cmd_adv_nc));
565 cmd_adv_39->channel = 39;
567 cmd_adv_39->whitening.init = 0x67;
570 cmd_adv_39->pNextOp = NULL;
571 cmd_adv_39->condition.rule = COND_NEVER;
577 if(first_ble_adv == NULL) {
578 first_ble_adv = (RF_Op *)cmd_adv_39;
582 return first_ble_adv;
587 ble_sched_beacons(uint8_t bm_channel)
589 #if RF_CONF_BLE_BEACON_ENABLE 595 ble_cmd_adv_nc_t ble_cmd_adv_nc_array[NUM_BLE_ADV_CHANNELS];
597 RF_Op *initial_adv = NULL;
598 RF_ScheduleCmdParams sched_params;
599 RF_CmdHandle beacon_handle;
600 RF_EventMask beacon_events;
601 rf_result_t rf_result;
604 if((bm_channel & BLE_ADV_CHANNEL_ALL) == 0) {
608 initial_adv = init_ble_adv_array(ble_cmd_adv_nc_array, bm_channel);
610 if(initial_adv == NULL) {
611 LOG_ERR(
"Initializing BLE Advertisement chain failed\n");
612 return RF_RESULT_ERROR;
615 RF_ScheduleCmdParams_init(&sched_params);
616 sched_params.priority = RF_PriorityNormal;
617 sched_params.endTime = 0;
618 sched_params.allowDelay = RF_AllowDelayAny;
626 beacon_handle = RF_scheduleCmd(
633 if(!CMD_HANDLE_OK(beacon_handle)) {
634 LOG_ERR(
"Unable to schedule BLE Beacon command, handle=%d status=0x%04x\n",
635 beacon_handle, CMD_STATUS(ble_cmd_adv_nc));
637 return RF_RESULT_ERROR;
641 rf_result = cmd_rx_restore(cmd_rx_disable());
644 beacon_events = RF_pendCmd(&rf_ble, beacon_handle, 0);
646 if(rf_result != RF_RESULT_OK) {
647 LOG_ERR(
"Rescheduling CMD_RX failed when BLE advertising\n");
649 return RF_RESULT_ERROR;
652 if(!EVENTS_CMD_DONE(beacon_events)) {
653 LOG_ERR(
"Pending on scheduled BLE Beacon command generated error, events=0x%08llx status=0x%04x\n",
654 beacon_events, CMD_STATUS(ble_cmd_adv_nc));
656 return RF_RESULT_ERROR;
662 return RF_RESULT_ERROR;
666 PROCESS(rf_sched_process,
"RF Scheduler Process");
676 (ev == PROCESS_EVENT_TIMER));
681 clock_time_t interval = synth_recal_interval();
682 LOG_INFO(
"Starting synth re-calibration timer, next timeout %lu\n", interval);
686 if(ev == PROCESS_EVENT_POLL) {
698 LOG_ERR(
"RX buffer full, restart RX status=0x%04x\n", CMD_STATUS(netstack_cmd_rx));
703 netstack_sched_rx(
false);
709 NETSTACK_MAC.
input();
716 if((ev == PROCESS_EVENT_TIMER) &&
718 clock_time_t interval = synth_recal_interval();
719 LOG_DBG(
"Re-calibrate synth, next interval %lu\n", interval);
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
#define PROCESS(name, strname)
Declare a process.
void etimer_stop(struct etimer *et)
Stop a pending event timer.
static uint8_t rf_is_on(void)
Checks whether the RFC domain is accessible and the RFC is in IEEE RX.
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.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PROCESS_END()
Define the end of a process.
static void start(void)
Start measurement.
Header file of the CC13xx/CC26xx RF scheduler.
void(* input)(void)
Callback for getting notified of incoming packet.
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.
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
Header file of the CC13xx/CC26xx RF data queue.
Header file of RF settings for CC13xx/CC26xx.
Header file of common CC13xx/CC26xx RF functionality.
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
void watchdog_periodic(void)
Writes the WDT clear sequence.
Default definitions of C compiler quirk work-arounds.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
Header file for the logging system
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.