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) 55 #include <ti/drivers/rf/RF.h> 68 #define LOG_MODULE "Radio" 69 #define LOG_LEVEL LOG_LEVEL_NONE 73 #define CMD_FS_RETRIES 3 75 #define RF_EVENTS_CMD_DONE (RF_EventCmdDone | RF_EventLastCmdDone | \ 76 RF_EventFGCmdDone | RF_EventLastFGCmdDone) 78 #define CMD_STATUS(cmd) (CC_ACCESS_NOW(RF_Op, cmd).status) 80 #define CMD_HANDLE_OK(handle) (((handle) != RF_ALLOC_ERROR) && \ 81 ((handle) != RF_SCHEDULE_CMD_ERROR)) 83 #define EVENTS_CMD_DONE(events) (((events) & RF_EVENTS_CMD_DONE) != 0) 86 #define SYNTH_RECAL_INTERVAL (CLOCK_SECOND * 60 * 3) 88 #define SYNTH_RECAL_JITTER (CLOCK_SECOND * 10) 90 static struct etimer synth_recal_timer;
92 static RF_Object rf_netstack;
94 #if RF_CONF_BLE_BEACON_ENABLE 95 static RF_Object rf_ble;
98 static RF_CmdHandle cmd_rx_handle;
101 static volatile bool rx_buf_full;
104 cmd_rx_cb(RF_Handle client, RF_CmdHandle command, RF_EventMask events)
110 if(events & RF_EventRxEntryDone) {
114 if(events & RF_EventRxBufFull) {
120 static inline clock_time_t
121 synth_recal_interval(
void)
127 return SYNTH_RECAL_INTERVAL + (
random_rand() % SYNTH_RECAL_JITTER) - (SYNTH_RECAL_JITTER / 2);
131 cmd_rx_is_active(
void)
137 const uint16_t status = CMD_STATUS(netstack_cmd_rx);
138 return (status == ACTIVE) ||
145 const bool is_active = cmd_rx_is_active();
148 CMD_STATUS(netstack_cmd_rx) = DONE_STOPPED;
149 RF_cancelCmd(&rf_netstack, cmd_rx_handle, RF_ABORT_GRACEFULLY);
153 return (uint_fast8_t)is_active;
157 cmd_rx_restore(uint_fast8_t rx_key)
159 const bool was_active = (rx_key != 0) ?
true :
false;
165 RF_ScheduleCmdParams sched_params;
166 RF_ScheduleCmdParams_init(&sched_params);
168 sched_params.priority = RF_PriorityNormal;
169 sched_params.endTime = 0;
170 sched_params.allowDelay = RF_AllowDelayAny;
172 CMD_STATUS(netstack_cmd_rx) = PENDING;
174 cmd_rx_handle = RF_scheduleCmd(
176 (RF_Op *)&netstack_cmd_rx,
179 RF_EventRxEntryDone | RF_EventRxBufFull);
181 if(!CMD_HANDLE_OK(cmd_rx_handle)) {
182 LOG_ERR(
"Unable to restore RX command, handle=%d status=0x%04x",
183 cmd_rx_handle, CMD_STATUS(netstack_cmd_rx));
184 return RF_RESULT_ERROR;
194 RF_flushCmd(&rf_netstack, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY);
195 #if RF_CONF_BLE_BEACON_ENABLE 196 RF_flushCmd(&rf_ble, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY);
200 RF_yield(&rf_netstack);
201 #if RF_CONF_BLE_BEACON_ENABLE 205 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
214 rf_set_tx_power(RF_Handle handle, RF_TxPowerTable_Entry *table, int8_t dbm)
216 const RF_Stat stat = RF_setTxPower(handle, RF_TxPowerTable_findValue(table, dbm));
218 return (stat == RF_StatSuccess)
224 rf_get_tx_power(RF_Handle handle, RF_TxPowerTable_Entry *table, int8_t *dbm)
226 *dbm = RF_TxPowerTable_findPowerLevel(table, RF_getTxPower(handle));
228 return (*dbm != RF_TxPowerTable_INVALID_DBM)
234 netstack_open(RF_Params *params)
236 return RF_open(&rf_netstack, &netstack_mode, (RF_RadioSetup *)&netstack_cmd_radio_setup, params);
240 netstack_sched_fs(
void)
242 const uint_fast8_t rx_key = cmd_rx_disable();
252 #if (RF_MODE == RF_CORE_MODE_2_4_GHZ) 254 cmd_rx_restore(rx_key);
260 bool synth_error =
false;
261 uint8_t num_tries = 0;
264 CMD_STATUS(netstack_cmd_fs) = PENDING;
268 (RF_Op *)&netstack_cmd_fs,
273 synth_error = (EVENTS_CMD_DONE(events)) && (CMD_STATUS(netstack_cmd_fs) == ERROR_SYNTH_PROG);
275 }
while(synth_error && (num_tries++ < CMD_FS_RETRIES));
277 cmd_rx_restore(rx_key);
279 return (CMD_STATUS(netstack_cmd_fs) == DONE_OK)
285 netstack_sched_ieee_tx(
bool ack_request)
289 RF_ScheduleCmdParams sched_params;
290 RF_ScheduleCmdParams_init(&sched_params);
292 sched_params.priority = RF_PriorityNormal;
293 sched_params.endTime = 0;
294 sched_params.allowDelay = RF_AllowDelayAny;
296 const bool rx_is_active = cmd_rx_is_active();
297 const bool rx_needed = (ack_request && !rx_is_active);
305 res = netstack_sched_rx(
false);
306 if(res != RF_RESULT_OK) {
311 CMD_STATUS(netstack_cmd_tx) = PENDING;
313 RF_CmdHandle tx_handle = RF_scheduleCmd(
315 (RF_Op *)&netstack_cmd_tx,
320 if(!CMD_HANDLE_OK(tx_handle)) {
321 LOG_ERR(
"Unable to schedule TX command, handle=%d status=0x%04x\n",
322 tx_handle, CMD_STATUS(netstack_cmd_tx));
323 return RF_RESULT_ERROR;
327 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
329 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
333 RF_EventMask tx_events = RF_pendCmd(&rf_netstack, tx_handle, 0);
341 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
343 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
346 if(!EVENTS_CMD_DONE(tx_events)) {
347 LOG_ERR(
"Pending on TX comand generated error, events=0x%08llx status=0x%04x\n",
348 tx_events, CMD_STATUS(netstack_cmd_tx));
349 return RF_RESULT_ERROR;
356 netstack_sched_prop_tx(
void)
358 RF_ScheduleCmdParams sched_params;
359 RF_ScheduleCmdParams_init(&sched_params);
361 sched_params.priority = RF_PriorityNormal;
362 sched_params.endTime = 0;
363 sched_params.allowDelay = RF_AllowDelayAny;
365 CMD_STATUS(netstack_cmd_tx) = PENDING;
367 RF_CmdHandle tx_handle = RF_scheduleCmd(
369 (RF_Op *)&netstack_cmd_tx,
374 if(!CMD_HANDLE_OK(tx_handle)) {
375 LOG_ERR(
"Unable to schedule TX command, handle=%d status=0x%04x\n",
376 tx_handle, CMD_STATUS(netstack_cmd_tx));
377 return RF_RESULT_ERROR;
384 const bool rx_key = cmd_rx_disable();
387 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
389 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
393 RF_EventMask tx_events = RF_pendCmd(&rf_netstack, tx_handle, 0);
395 cmd_rx_restore(rx_key);
398 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
400 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
403 if(!EVENTS_CMD_DONE(tx_events)) {
404 LOG_ERR(
"Pending on scheduled TX command generated error, events=0x%08llx status=0x%04x\n",
405 tx_events, CMD_STATUS(netstack_cmd_tx));
406 return RF_RESULT_ERROR;
413 netstack_sched_rx(
bool start)
415 if(cmd_rx_is_active()) {
416 LOG_WARN(
"Already in RX when scheduling RX\n");
420 RF_ScheduleCmdParams sched_params;
421 RF_ScheduleCmdParams_init(&sched_params);
423 sched_params.priority = RF_PriorityNormal;
424 sched_params.endTime = 0;
425 sched_params.allowDelay = RF_AllowDelayAny;
427 CMD_STATUS(netstack_cmd_rx) = PENDING;
429 cmd_rx_handle = RF_scheduleCmd(
431 (RF_Op *)&netstack_cmd_rx,
434 RF_EventRxEntryDone | RF_EventRxBufFull);
436 if(!CMD_HANDLE_OK(cmd_rx_handle)) {
437 LOG_ERR(
"Unable to schedule RX command, handle=%d status=0x%04x\n",
438 cmd_rx_handle, CMD_STATUS(netstack_cmd_rx));
439 return RF_RESULT_ERROR;
442 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
453 netstack_stop_rx(
void)
455 if(!cmd_rx_is_active()) {
456 LOG_WARN(
"RX not active when stopping RX\n");
460 CMD_STATUS(netstack_cmd_rx) = DONE_STOPPED;
461 const RF_Stat stat = RF_cancelCmd(&rf_netstack, cmd_rx_handle, RF_ABORT_GRACEFULLY);
464 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
466 return (stat == RF_StatSuccess)
472 ble_open(RF_Params *params)
474 #if RF_CONF_BLE_BEACON_ENABLE 475 return RF_open(&rf_ble, &ble_mode, (RF_RadioSetup *)&ble_cmd_radio_setup, params);
478 return (RF_Handle)NULL;
483 ble_sched_beacon(RF_Callback cb, RF_EventMask bm_event)
485 #if RF_CONF_BLE_BEACON_ENABLE 486 RF_ScheduleCmdParams sched_params;
487 RF_ScheduleCmdParams_init(&sched_params);
489 sched_params.priority = RF_PriorityNormal;
490 sched_params.endTime = 0;
491 sched_params.allowDelay = RF_AllowDelayAny;
493 CMD_STATUS(ble_cmd_beacon) = PENDING;
495 RF_CmdHandle beacon_handle = RF_scheduleCmd(
497 (RF_Op *)&ble_cmd_beacon,
502 if(!CMD_HANDLE_OK(beacon_handle)) {
503 LOG_ERR(
"Unable to schedule BLE Beacon command, handle=%d status=0x%04x\n",
504 beacon_handle, CMD_STATUS(ble_cmd_beacon));
505 return RF_RESULT_ERROR;
508 const uint_fast8_t rx_key = cmd_rx_disable();
511 RF_EventMask beacon_events = RF_pendCmd(&rf_ble, beacon_handle, 0);
512 if(!EVENTS_CMD_DONE(beacon_events)) {
513 LOG_ERR(
"Pending on scheduled BLE Beacon command generated error, events=0x%08llx status=0x%04x\n",
514 beacon_events, CMD_STATUS(ble_cmd_beacon));
516 cmd_rx_restore(rx_key);
517 return RF_RESULT_ERROR;
520 cmd_rx_restore(rx_key);
524 return RF_RESULT_ERROR;
528 PROCESS(rf_sched_process,
"RF Scheduler Process");
538 (ev == PROCESS_EVENT_TIMER));
543 clock_time_t interval = synth_recal_interval();
544 LOG_INFO(
"Starting synth re-calibration timer, next timeout %lu\n", interval);
548 if(ev == PROCESS_EVENT_POLL) {
560 LOG_ERR(
"RX buffer full, restart RX status=0x%04x\n", CMD_STATUS(netstack_cmd_rx));
565 netstack_sched_rx(
false);
571 NETSTACK_MAC.
input();
578 if((ev == PROCESS_EVENT_TIMER) &&
580 clock_time_t interval = synth_recal_interval();
581 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.
static bool start(void)
Start measurement.
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 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.