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) 55 #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h) 56 #if defined(DeviceFamily_CC13X0) 57 #include "driverlib/rf_ieee_mailbox.h" 59 #include DeviceFamily_constructPath(driverlib/rf_ieee_mailbox.h) 62 #include <ti/drivers/rf/RF.h> 76 #define LOG_MODULE "Radio" 77 #define LOG_LEVEL LOG_LEVEL_NONE 79 #define CMD_FS_RETRIES 3 81 #define RF_EVENTS_CMD_DONE (RF_EventCmdDone | RF_EventLastCmdDone | \ 82 RF_EventFGCmdDone | RF_EventLastFGCmdDone) 84 #define CMD_STATUS(cmd) (CC_ACCESS_NOW(RF_Op, cmd).status) 86 #define CMD_HANDLE_OK(handle) (((handle) != RF_ALLOC_ERROR) && \ 87 ((handle) != RF_SCHEDULE_CMD_ERROR)) 89 #define EVENTS_CMD_DONE(events) (((events) & RF_EVENTS_CMD_DONE) != 0) 92 #define BLE_ADV_CHANNEL_MIN 37 93 #define BLE_ADV_CHANNEL_MAX 39 96 #define NUM_BLE_ADV_CHANNELS (BLE_ADV_CHANNEL_MAX - BLE_ADV_CHANNEL_MIN + 1) 99 #define SYNTH_RECAL_INTERVAL (CLOCK_SECOND * 60 * 3) 101 #define SYNTH_RECAL_JITTER (CLOCK_SECOND * 10) 103 static struct etimer synth_recal_timer;
105 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X0_CC26X0) 106 typedef rfc_CMD_BLE_ADV_NC_t ble_cmd_adv_nc_t;
107 #elif (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X2_CC26X2) 108 typedef rfc_CMD_BLE5_ADV_NC_t ble_cmd_adv_nc_t;
111 static RF_Object rf_netstack;
113 #if RF_CONF_BLE_BEACON_ENABLE 114 static RF_Object rf_ble;
117 static RF_CmdHandle cmd_rx_handle;
120 static volatile bool rx_buf_full;
122 static rfc_CMD_SYNC_STOP_RAT_t netstack_cmd_stop_rat;
123 static rfc_CMD_SYNC_START_RAT_t netstack_cmd_start_rat;
125 simplelink_radio_mode_t *radio_mode;
128 cmd_rx_cb(RF_Handle client, RF_CmdHandle command, RF_EventMask events)
134 if(radio_mode->poll_mode) {
138 if(events & RF_EventRxEntryDone) {
142 if(events & RF_EventRxBufFull) {
148 static inline clock_time_t
149 synth_recal_interval(
void)
155 return SYNTH_RECAL_INTERVAL + (
random_rand() % SYNTH_RECAL_JITTER) - (SYNTH_RECAL_JITTER / 2);
159 cmd_rx_is_active(
void)
165 const uint16_t status = CMD_STATUS(netstack_cmd_rx);
166 return (status == ACTIVE) ||
173 const bool is_active = cmd_rx_is_active();
176 CMD_STATUS(netstack_cmd_rx) = DONE_STOPPED;
177 RF_cancelCmd(&rf_netstack, cmd_rx_handle, RF_ABORT_GRACEFULLY);
181 return (uint_fast8_t)is_active;
185 cmd_rx_restore(uint_fast8_t rx_key)
187 const bool was_active = (rx_key != 0) ?
true :
false;
193 RF_ScheduleCmdParams sched_params;
194 RF_ScheduleCmdParams_init(&sched_params);
196 sched_params.priority = RF_PriorityNormal;
197 sched_params.endTime = 0;
198 sched_params.allowDelay = RF_AllowDelayAny;
200 CMD_STATUS(netstack_cmd_rx) = PENDING;
202 cmd_rx_handle = RF_scheduleCmd(
204 (RF_Op *)&netstack_cmd_rx,
207 RF_EventRxEntryDone | RF_EventRxBufFull);
209 if(!CMD_HANDLE_OK(cmd_rx_handle)) {
210 LOG_ERR(
"Unable to restore RX command, handle=%d status=0x%04x",
211 cmd_rx_handle, CMD_STATUS(netstack_cmd_rx));
212 return RF_RESULT_ERROR;
222 RF_flushCmd(&rf_netstack, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY);
223 #if RF_CONF_BLE_BEACON_ENABLE 224 RF_flushCmd(&rf_ble, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY);
228 RF_ScheduleCmdParams sched_params;
229 RF_ScheduleCmdParams_init(&sched_params);
231 sched_params.priority = RF_PriorityNormal;
232 sched_params.endTime = 0;
233 sched_params.allowDelay = RF_AllowDelayAny;
235 CMD_STATUS(netstack_cmd_stop_rat) = PENDING;
239 (RF_Op *)&netstack_cmd_stop_rat,
245 RF_yield(&rf_netstack);
246 #if RF_CONF_BLE_BEACON_ENABLE 250 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
261 RF_ScheduleCmdParams sched_params;
264 RF_ScheduleCmdParams_init(&sched_params);
266 sched_params.priority = RF_PriorityNormal;
267 sched_params.endTime = 0;
268 sched_params.allowDelay = RF_AllowDelayAny;
270 CMD_STATUS(netstack_cmd_stop_rat) = PENDING;
274 (RF_Op *)&netstack_cmd_stop_rat,
280 RF_ScheduleCmdParams_init(&sched_params);
282 sched_params.priority = RF_PriorityNormal;
283 sched_params.endTime = 0;
284 sched_params.allowDelay = RF_AllowDelayAny;
286 netstack_cmd_start_rat.rat0 = 0;
287 CMD_STATUS(netstack_cmd_start_rat) = PENDING;
291 (RF_Op *)&netstack_cmd_start_rat,
301 rf_set_tx_power(RF_Handle handle, RF_TxPowerTable_Entry *table, int8_t dbm)
303 const RF_Stat stat = RF_setTxPower(handle, RF_TxPowerTable_findValue(table, dbm));
305 return (stat == RF_StatSuccess)
311 rf_get_tx_power(RF_Handle handle, RF_TxPowerTable_Entry *table, int8_t *dbm)
313 *dbm = RF_TxPowerTable_findPowerLevel(table, RF_getTxPower(handle));
315 return (*dbm != RF_TxPowerTable_INVALID_DBM)
321 netstack_open(RF_Params *params)
323 netstack_cmd_stop_rat.commandNo = CMD_SYNC_STOP_RAT;
324 netstack_cmd_stop_rat.condition.rule = COND_NEVER;
325 netstack_cmd_start_rat.commandNo = CMD_SYNC_START_RAT;
326 netstack_cmd_start_rat.condition.rule = COND_NEVER;
327 return RF_open(&rf_netstack, &netstack_mode, (RF_RadioSetup *)&netstack_cmd_radio_setup, params);
331 netstack_sched_fs(
void)
333 const uint_fast8_t rx_key = cmd_rx_disable();
343 #if (RF_MODE == RF_MODE_2_4_GHZ) 345 cmd_rx_restore(rx_key);
350 if(radio_mode->poll_mode) {
355 RF_ScheduleCmdParams sched_params;
356 RF_ScheduleCmdParams_init(&sched_params);
358 sched_params.priority = RF_PriorityNormal;
359 sched_params.endTime = 0;
360 sched_params.allowDelay = RF_AllowDelayAny;
362 CMD_STATUS(netstack_cmd_fs) = PENDING;
364 RF_CmdHandle fs_handle = RF_scheduleCmd(
366 (RF_Op *)&netstack_cmd_fs,
371 cmd_rx_restore(rx_key);
373 if(!CMD_HANDLE_OK(fs_handle)) {
374 LOG_ERR(
"Unable to schedule FS command, handle=%d status=0x%04x\n",
375 fs_handle, CMD_STATUS(netstack_cmd_fs));
376 return RF_RESULT_ERROR;
387 bool synth_error =
false;
388 uint8_t num_tries = 0;
391 CMD_STATUS(netstack_cmd_fs) = PENDING;
395 (RF_Op *)&netstack_cmd_fs,
400 synth_error = (EVENTS_CMD_DONE(events)) && (CMD_STATUS(netstack_cmd_fs) == ERROR_SYNTH_PROG);
402 }
while(synth_error && (num_tries++ < CMD_FS_RETRIES));
404 cmd_rx_restore(rx_key);
406 return (CMD_STATUS(netstack_cmd_fs) == DONE_OK)
413 netstack_sched_ieee_tx(uint16_t payload_length,
bool ack_request)
416 RF_EventMask tx_events = 0;
418 RF_ScheduleCmdParams sched_params;
419 RF_ScheduleCmdParams_init(&sched_params);
421 sched_params.priority = RF_PriorityNormal;
422 sched_params.endTime = 0;
423 sched_params.allowDelay = RF_AllowDelayAny;
425 const bool rx_is_active = cmd_rx_is_active();
426 const bool rx_needed = (ack_request && !rx_is_active);
434 res = netstack_sched_rx(
false);
435 if(res != RF_RESULT_OK) {
440 CMD_STATUS(netstack_cmd_tx) = PENDING;
442 RF_CmdHandle tx_handle = RF_scheduleCmd(
444 (RF_Op *)&netstack_cmd_tx,
449 if(!CMD_HANDLE_OK(tx_handle)) {
450 LOG_ERR(
"Unable to schedule TX command, handle=%d status=0x%04x\n",
451 tx_handle, CMD_STATUS(netstack_cmd_tx));
452 return RF_RESULT_ERROR;
456 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
458 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
462 if(radio_mode->poll_mode) {
463 const uint16_t frame_length = payload_length + RADIO_PHY_HEADER_LEN + RADIO_PHY_OVERHEAD;
465 US_TO_RTIMERTICKS(RADIO_BYTE_AIR_TIME * frame_length + 300));
467 tx_events = RF_pendCmd(&rf_netstack, tx_handle, 0);
476 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
478 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
481 if(radio_mode->poll_mode) {
482 if(CMD_STATUS(netstack_cmd_tx) != IEEE_DONE_OK) {
483 LOG_ERR(
"Pending on scheduled TX command generated error, status=0x%04x\n",
484 CMD_STATUS(netstack_cmd_tx));
485 return RF_RESULT_ERROR;
488 if(!EVENTS_CMD_DONE(tx_events)) {
489 LOG_ERR(
"Pending on TX comand generated error, events=0x%08llx status=0x%04x\n",
490 tx_events, CMD_STATUS(netstack_cmd_tx));
491 return RF_RESULT_ERROR;
499 netstack_sched_prop_tx(uint16_t payload_length)
501 RF_EventMask tx_events = 0;
503 RF_ScheduleCmdParams sched_params;
504 RF_ScheduleCmdParams_init(&sched_params);
506 sched_params.priority = RF_PriorityNormal;
507 sched_params.endTime = 0;
508 sched_params.allowDelay = RF_AllowDelayAny;
510 CMD_STATUS(netstack_cmd_tx) = PENDING;
512 RF_CmdHandle tx_handle = RF_scheduleCmd(
514 (RF_Op *)&netstack_cmd_tx,
519 if(!CMD_HANDLE_OK(tx_handle)) {
520 LOG_ERR(
"Unable to schedule TX command, handle=%d status=0x%04x\n",
521 tx_handle, CMD_STATUS(netstack_cmd_tx));
522 return RF_RESULT_ERROR;
529 const bool rx_key = cmd_rx_disable();
532 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
534 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
538 if(radio_mode->poll_mode) {
539 const uint16_t frame_length = payload_length + RADIO_PHY_HEADER_LEN + RADIO_PHY_OVERHEAD;
541 US_TO_RTIMERTICKS(RADIO_BYTE_AIR_TIME * frame_length + 1200));
543 tx_events = RF_pendCmd(&rf_netstack, tx_handle, 0);
546 cmd_rx_restore(rx_key);
549 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
551 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
554 if(radio_mode->poll_mode) {
555 if(CMD_STATUS(netstack_cmd_tx) != PROP_DONE_OK) {
556 LOG_ERR(
"Pending on scheduled TX command generated error, status=0x%04x\n",
557 CMD_STATUS(netstack_cmd_tx));
558 return RF_RESULT_ERROR;
561 if(!EVENTS_CMD_DONE(tx_events)) {
562 LOG_ERR(
"Pending on scheduled TX command generated error, events=0x%08llx status=0x%04x\n",
563 tx_events, CMD_STATUS(netstack_cmd_tx));
564 return RF_RESULT_ERROR;
572 netstack_sched_rx(
bool start)
574 if(cmd_rx_is_active()) {
575 LOG_WARN(
"Already in RX when scheduling RX\n");
579 RF_ScheduleCmdParams sched_params;
582 RF_ScheduleCmdParams_init(&sched_params);
584 sched_params.priority = RF_PriorityNormal;
585 sched_params.endTime = 0;
586 sched_params.allowDelay = RF_AllowDelayAny;
588 netstack_cmd_start_rat.rat0 = 0;
589 CMD_STATUS(netstack_cmd_start_rat) = PENDING;
593 (RF_Op *)&netstack_cmd_start_rat,
599 RF_ScheduleCmdParams_init(&sched_params);
601 sched_params.priority = RF_PriorityNormal;
602 sched_params.endTime = 0;
603 sched_params.allowDelay = RF_AllowDelayAny;
605 CMD_STATUS(netstack_cmd_rx) = PENDING;
607 cmd_rx_handle = RF_scheduleCmd(
609 (RF_Op *)&netstack_cmd_rx,
612 RF_EventRxEntryDone | RF_EventRxBufFull);
614 if(!CMD_HANDLE_OK(cmd_rx_handle)) {
615 LOG_ERR(
"Unable to schedule RX command, handle=%d status=0x%04x\n",
616 cmd_rx_handle, CMD_STATUS(netstack_cmd_rx));
617 return RF_RESULT_ERROR;
620 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
624 if(!radio_mode->poll_mode) {
633 netstack_stop_rx(
void)
635 if(!cmd_rx_is_active()) {
636 LOG_WARN(
"RX not active when stopping RX\n");
640 CMD_STATUS(netstack_cmd_rx) = DONE_STOPPED;
641 const RF_Stat stat = RF_cancelCmd(&rf_netstack, cmd_rx_handle, RF_ABORT_GRACEFULLY);
644 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
646 return (stat == RF_StatSuccess)
652 ble_open(RF_Params *params)
654 #if RF_CONF_BLE_BEACON_ENABLE 655 return RF_open(&rf_ble, &ble_mode, (RF_RadioSetup *)&ble_cmd_radio_setup, params);
658 return (RF_Handle)NULL;
662 #if RF_CONF_BLE_BEACON_ENABLE 664 init_ble_adv_array(ble_cmd_adv_nc_t *ble_adv_array, uint8_t bm_channel)
666 RF_Op *first_ble_adv = NULL;
667 ble_cmd_adv_nc_t *cmd_adv_37 = &ble_adv_array[0];
668 ble_cmd_adv_nc_t *cmd_adv_38 = &ble_adv_array[1];
669 ble_cmd_adv_nc_t *cmd_adv_39 = &ble_adv_array[2];
672 if(bm_channel & BLE_ADV_CHANNEL_37) {
674 memcpy(cmd_adv_37, &ble_cmd_adv_nc,
sizeof(ble_cmd_adv_nc));
676 cmd_adv_37->channel = 37;
678 cmd_adv_37->whitening.init = 0x65;
685 if(bm_channel & BLE_ADV_CHANNEL_38) {
686 cmd_adv_37->pNextOp = (RF_Op *)cmd_adv_38;
687 cmd_adv_37->condition.rule = COND_ALWAYS;
688 }
else if(bm_channel & BLE_ADV_CHANNEL_39) {
689 cmd_adv_37->pNextOp = (RF_Op *)cmd_adv_39;
690 cmd_adv_37->condition.rule = COND_ALWAYS;
692 cmd_adv_37->pNextOp = NULL;
693 cmd_adv_37->condition.rule = COND_NEVER;
697 first_ble_adv = (RF_Op *)cmd_adv_37;
701 if(bm_channel & BLE_ADV_CHANNEL_38) {
702 memcpy(cmd_adv_38, &ble_cmd_adv_nc,
sizeof(ble_cmd_adv_nc));
704 cmd_adv_38->channel = 38;
706 cmd_adv_38->whitening.init = 0x66;
712 if(bm_channel & BLE_ADV_CHANNEL_39) {
713 cmd_adv_38->pNextOp = (RF_Op *)cmd_adv_39;
714 cmd_adv_38->condition.rule = COND_ALWAYS;
716 cmd_adv_38->pNextOp = NULL;
717 cmd_adv_38->condition.rule = COND_NEVER;
724 if(first_ble_adv == NULL) {
725 first_ble_adv = (RF_Op *)cmd_adv_38;
730 if(bm_channel & BLE_ADV_CHANNEL_39) {
731 memcpy(cmd_adv_39, &ble_cmd_adv_nc,
sizeof(ble_cmd_adv_nc));
733 cmd_adv_39->channel = 39;
735 cmd_adv_39->whitening.init = 0x67;
738 cmd_adv_39->pNextOp = NULL;
739 cmd_adv_39->condition.rule = COND_NEVER;
745 if(first_ble_adv == NULL) {
746 first_ble_adv = (RF_Op *)cmd_adv_39;
750 return first_ble_adv;
755 ble_sched_beacons(uint8_t bm_channel)
757 #if RF_CONF_BLE_BEACON_ENABLE 763 ble_cmd_adv_nc_t ble_cmd_adv_nc_array[NUM_BLE_ADV_CHANNELS];
765 RF_Op *initial_adv = NULL;
766 RF_ScheduleCmdParams sched_params;
767 RF_CmdHandle beacon_handle;
768 RF_EventMask beacon_events;
769 rf_result_t rf_result;
772 if((bm_channel & BLE_ADV_CHANNEL_ALL) == 0) {
776 initial_adv = init_ble_adv_array(ble_cmd_adv_nc_array, bm_channel);
778 if(initial_adv == NULL) {
779 LOG_ERR(
"Initializing BLE Advertisement chain failed\n");
780 return RF_RESULT_ERROR;
783 RF_ScheduleCmdParams_init(&sched_params);
784 sched_params.priority = RF_PriorityNormal;
785 sched_params.endTime = 0;
786 sched_params.allowDelay = RF_AllowDelayAny;
794 beacon_handle = RF_scheduleCmd(
801 if(!CMD_HANDLE_OK(beacon_handle)) {
802 LOG_ERR(
"Unable to schedule BLE Beacon command, handle=%d status=0x%04x\n",
803 beacon_handle, CMD_STATUS(ble_cmd_adv_nc));
805 return RF_RESULT_ERROR;
809 rf_result = cmd_rx_restore(cmd_rx_disable());
812 beacon_events = RF_pendCmd(&rf_ble, beacon_handle, 0);
814 if(rf_result != RF_RESULT_OK) {
815 LOG_ERR(
"Rescheduling CMD_RX failed when BLE advertising\n");
817 return RF_RESULT_ERROR;
820 if(!EVENTS_CMD_DONE(beacon_events)) {
821 LOG_ERR(
"Pending on scheduled BLE Beacon command generated error, events=0x%08llx status=0x%04x\n",
822 beacon_events, CMD_STATUS(ble_cmd_adv_nc));
824 return RF_RESULT_ERROR;
830 return RF_RESULT_ERROR;
834 PROCESS(rf_sched_process,
"RF Scheduler Process");
844 (ev == PROCESS_EVENT_TIMER));
849 clock_time_t interval = synth_recal_interval();
850 LOG_INFO(
"Starting synth re-calibration timer, next timeout %lu\n", interval);
854 if(ev == PROCESS_EVENT_POLL) {
866 LOG_ERR(
"RX buffer full, restart RX status=0x%04x\n", CMD_STATUS(netstack_cmd_rx));
871 netstack_sched_rx(
false);
877 NETSTACK_MAC.
input();
880 }
while(NETSTACK_RADIO.pending_packet());
884 if((ev == PROCESS_EVENT_TIMER) &&
886 clock_time_t interval = synth_recal_interval();
887 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.
Header file of the generic radio mode API.
#define RTIMER_BUSYWAIT_UNTIL(cond, max_time)
Busy-wait until a condition for at most max_time.
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.