Contiki-NG
rf-core.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30/*---------------------------------------------------------------------------*/
31/**
32 * \addtogroup rf-core
33 * @{
34 *
35 * \file
36 * Implementation of the CC13xx/CC26xx RF core driver
37 */
38/*---------------------------------------------------------------------------*/
39#include "contiki.h"
40#include "dev/watchdog.h"
41#include "sys/process.h"
42#include "sys/energest.h"
43#include "sys/cc.h"
44#include "net/netstack.h"
45#include "net/packetbuf.h"
46#include "rf-core/rf-core.h"
47#include "rf-core/rf-switch.h"
48#include "ti-lib.h"
49/*---------------------------------------------------------------------------*/
50/* RF core and RF HAL API */
51#include "hw_rfc_dbell.h"
52#include "hw_rfc_pwr.h"
53/*---------------------------------------------------------------------------*/
54/* RF Core Mailbox API */
55#include "driverlib/rf_mailbox.h"
56#include "driverlib/rf_common_cmd.h"
57#include "driverlib/rf_data_entry.h"
58/*---------------------------------------------------------------------------*/
59#include <stdint.h>
60#include <stdbool.h>
61#include <stdio.h>
62#include <string.h>
63/*---------------------------------------------------------------------------*/
64#define DEBUG 0
65#if DEBUG
66#define PRINTF(...) printf(__VA_ARGS__)
67#else
68#define PRINTF(...)
69#endif
70/*---------------------------------------------------------------------------*/
71#ifdef RF_CORE_CONF_DEBUG_CRC
72#define RF_CORE_DEBUG_CRC RF_CORE_CONF_DEBUG_CRC
73#else
74#define RF_CORE_DEBUG_CRC DEBUG
75#endif
76/*---------------------------------------------------------------------------*/
77/* RF interrupts */
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
81
82/* Those IRQs are enabled all the time */
83#if RF_CORE_DEBUG_CRC
84#define ENABLED_IRQS (RX_FRAME_IRQ | ERROR_IRQ | RX_NOK_IRQ)
85#else
86#define ENABLED_IRQS (RX_FRAME_IRQ | ERROR_IRQ)
87#endif
88
89#define ENABLED_IRQS_POLL_MODE (ENABLED_IRQS & ~(RX_FRAME_IRQ | ERROR_IRQ))
90
91#define cc26xx_rf_cpe0_isr RFCCPE0IntHandler
92#define cc26xx_rf_cpe1_isr RFCCPE1IntHandler
93/*---------------------------------------------------------------------------*/
94typedef ChipType_t chip_type_t;
95/*---------------------------------------------------------------------------*/
96/* Remember the last Radio Op issued to the radio */
97static rfc_radioOp_t *last_radio_op = NULL;
98/*---------------------------------------------------------------------------*/
99/* A struct holding pointers to the primary mode's abort() and restore() */
100static const rf_core_primary_mode_t *primary_mode = NULL;
101/*---------------------------------------------------------------------------*/
102/* RAT has 32-bit register, overflows once 18 minutes */
103#define RAT_RANGE 4294967296ull
104/* approximate value */
105#define RAT_OVERFLOW_PERIOD_SECONDS (60 * 18)
106
107/* how often to check for the overflow, as a minimum */
108#define RAT_OVERFLOW_TIMER_INTERVAL (CLOCK_SECOND * RAT_OVERFLOW_PERIOD_SECONDS / 3)
109
110/* Radio timer (RAT) offset as compared to the rtimer counter (RTC) */
111static int32_t rat_offset;
112static bool rat_offset_known;
113
114/* Value during the last read of the RAT register */
115static uint32_t rat_last_value;
116
117/* For RAT overflow handling */
118static struct ctimer rat_overflow_timer;
119static volatile uint32_t rat_overflow_counter;
120static rtimer_clock_t rat_last_overflow;
121
122static void rat_overflow_check_timer_cb(void *);
123/*---------------------------------------------------------------------------*/
124volatile int8_t rf_core_last_rssi = RF_CORE_CMD_CCA_REQ_RSSI_UNKNOWN;
125volatile uint8_t rf_core_last_corr_lqi = 0;
126volatile uint32_t rf_core_last_packet_timestamp = 0;
127/*---------------------------------------------------------------------------*/
128/* Are we currently in poll mode? */
129uint8_t rf_core_poll_mode = 0;
130/*---------------------------------------------------------------------------*/
131/* Buffer full flag */
132volatile bool rf_core_rx_is_full = false;
133/* Status of the last command sent */
134volatile uint32_t last_cmd_status;
135/*---------------------------------------------------------------------------*/
136PROCESS(rf_core_process, "CC13xx / CC26xx RF driver");
137/*---------------------------------------------------------------------------*/
138#define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \
139 | RFC_PWR_PWMCLKEN_CPERAM_M | RFC_PWR_PWMCLKEN_FSCA_M \
140 | RFC_PWR_PWMCLKEN_PHA_M | RFC_PWR_PWMCLKEN_RAT_M \
141 | RFC_PWR_PWMCLKEN_RFERAM_M | RFC_PWR_PWMCLKEN_RFE_M \
142 | RFC_PWR_PWMCLKEN_MDMRAM_M | RFC_PWR_PWMCLKEN_MDM_M)
143/*---------------------------------------------------------------------------*/
144#define RF_CMD0 0x0607
145/*---------------------------------------------------------------------------*/
146uint8_t
148{
149 if(ti_lib_prcm_rf_ready()) {
150 return RF_CORE_ACCESSIBLE;
151 }
152 return RF_CORE_NOT_ACCESSIBLE;
153}
154/*---------------------------------------------------------------------------*/
155uint_fast8_t
156rf_core_send_cmd(uint32_t cmd, uint32_t *status)
157{
158 uint32_t timeout_count = 0;
159 bool interrupts_disabled;
160 bool is_radio_op = false;
161
162 /* reset the status variables to invalid values */
163 last_cmd_status = (uint32_t)-1;
164 *status = last_cmd_status;
165
166 /*
167 * If cmd is 4-byte aligned, then it's either a radio OP or an immediate
168 * command. Clear the status field if it's a radio OP
169 */
170 if((cmd & 0x03) == 0) {
171 uint32_t cmd_type;
172 cmd_type = ((rfc_command_t *)cmd)->commandNo & RF_CORE_COMMAND_TYPE_MASK;
173 if(cmd_type == RF_CORE_COMMAND_TYPE_IEEE_FG_RADIO_OP ||
174 cmd_type == RF_CORE_COMMAND_TYPE_RADIO_OP) {
175 is_radio_op = true;
176 ((rfc_radioOp_t *)cmd)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
177 }
178 }
179
180 /*
181 * Make sure ContikiMAC doesn't turn us off from within an interrupt while
182 * we are accessing RF Core registers
183 */
184 interrupts_disabled = ti_lib_int_master_disable();
185
186 if(!rf_core_is_accessible()) {
187 PRINTF("rf_core_send_cmd: RF was off\n");
188 if(!interrupts_disabled) {
189 ti_lib_int_master_enable();
190 }
191 return RF_CORE_CMD_ERROR;
192 }
193
194 if(is_radio_op) {
195 uint16_t command_no = ((rfc_radioOp_t *)cmd)->commandNo;
196 if((command_no & RF_CORE_COMMAND_PROTOCOL_MASK) != RF_CORE_COMMAND_PROTOCOL_COMMON &&
197 (command_no & RF_CORE_COMMAND_TYPE_MASK) == RF_CORE_COMMAND_TYPE_RADIO_OP) {
198 last_radio_op = (rfc_radioOp_t *)cmd;
199 }
200 }
201
202 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd;
203 do {
204 last_cmd_status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
205 if(++timeout_count > 50000) {
206 PRINTF("rf_core_send_cmd: 0x%08lx Timeout\n", cmd);
207 if(!interrupts_disabled) {
208 ti_lib_int_master_enable();
209 }
210 *status = last_cmd_status;
211 return RF_CORE_CMD_ERROR;
212 }
213 } while((last_cmd_status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_PENDING);
214
215 if(!interrupts_disabled) {
216 ti_lib_int_master_enable();
217 }
218
219 /*
220 * If we reach here the command is no longer pending. It is either completed
221 * successfully or with error
222 */
223 *status = last_cmd_status;
224 return (last_cmd_status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_DONE;
225}
226/*---------------------------------------------------------------------------*/
227uint_fast8_t
229{
230 volatile rfc_radioOp_t *command = (rfc_radioOp_t *)cmd;
231 uint32_t timeout_cnt = 0;
232
233 /*
234 * 0xn4nn=DONE, 0x0400=DONE_OK while all other "DONE" values means done
235 * but with some kind of error (ref. "Common radio operation status codes")
236 */
237 do {
238 if(++timeout_cnt > 500000) {
239 return RF_CORE_CMD_ERROR;
240 }
241 } while((command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
242 != RF_CORE_RADIO_OP_MASKED_STATUS_DONE);
243
244 last_cmd_status = command->status;
245 return (command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
246 == RF_CORE_RADIO_OP_STATUS_DONE_OK;
247}
248/*---------------------------------------------------------------------------*/
249uint32_t
251{
252 return last_cmd_status;
253}
254/*---------------------------------------------------------------------------*/
255static int
256fs_powerdown(void)
257{
258 rfc_CMD_FS_POWERDOWN_t cmd;
259 uint32_t cmd_status;
260
261 rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_FS_POWERDOWN);
262
263 if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) != RF_CORE_CMD_OK) {
264 PRINTF("fs_powerdown: CMDSTA=0x%08lx\n", cmd_status);
265 return RF_CORE_CMD_ERROR;
266 }
267
268 if(rf_core_wait_cmd_done(&cmd) != RF_CORE_CMD_OK) {
269 PRINTF("fs_powerdown: CMDSTA=0x%08lx, status=0x%04x\n",
270 cmd_status, cmd.status);
271 return RF_CORE_CMD_ERROR;
272 }
273
274 return RF_CORE_CMD_OK;
275}
276/*---------------------------------------------------------------------------*/
277int
279{
280 uint32_t cmd_status;
281 bool interrupts_disabled = ti_lib_int_master_disable();
282
283 ti_lib_int_pend_clear(INT_RFC_CPE_0);
284 ti_lib_int_pend_clear(INT_RFC_CPE_1);
285 ti_lib_int_disable(INT_RFC_CPE_0);
286 ti_lib_int_disable(INT_RFC_CPE_1);
287
288 /* Enable RF Core power domain */
289 ti_lib_prcm_power_domain_on(PRCM_DOMAIN_RFCORE);
290 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
291 != PRCM_DOMAIN_POWER_ON);
292
293 ti_lib_prcm_domain_enable(PRCM_DOMAIN_RFCORE);
294 ti_lib_prcm_load_set();
295 while(!ti_lib_prcm_load_get());
296
297 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
298 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
299 ti_lib_int_enable(INT_RFC_CPE_0);
300 ti_lib_int_enable(INT_RFC_CPE_1);
301
302 if(!interrupts_disabled) {
303 ti_lib_int_master_enable();
304 }
305
306 rf_switch_power_up();
307
308 /* Let CPE boot */
309 HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK;
310
311 /* Turn on additional clocks on boot */
312 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
313 HWREG(RFC_DBELL_BASE+RFC_DBELL_O_CMDR) =
314 CMDR_DIR_CMD_2BYTE(RF_CMD0,
315 RFC_PWR_PWMCLKEN_MDMRAM | RFC_PWR_PWMCLKEN_RFERAM);
316
317 /* Send ping (to verify RFCore is ready and alive) */
318 if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_PING), &cmd_status) != RF_CORE_CMD_OK) {
319 PRINTF("rf_core_power_up: CMD_PING fail, CMDSTA=0x%08lx\n", cmd_status);
320 return RF_CORE_CMD_ERROR;
321 }
322
323 return RF_CORE_CMD_OK;
324}
325/*---------------------------------------------------------------------------*/
326uint8_t
328{
329 uint32_t cmd_status;
330 rfc_CMD_SYNC_START_RAT_t cmd_start;
331
332 /* Start radio timer (RAT) */
333 rf_core_init_radio_op((rfc_radioOp_t *)&cmd_start, sizeof(cmd_start), CMD_SYNC_START_RAT);
334
335 /* copy the value and send back */
336 cmd_start.rat0 = rat_offset;
337
338 if(rf_core_send_cmd((uint32_t)&cmd_start, &cmd_status) != RF_CORE_CMD_OK) {
339 PRINTF("rf_core_get_rat_rtc_offset: SYNC_START_RAT fail, CMDSTA=0x%08lx\n",
340 cmd_status);
341 return RF_CORE_CMD_ERROR;
342 }
343
344 /* Wait until done (?) */
345 if(rf_core_wait_cmd_done(&cmd_start) != RF_CORE_CMD_OK) {
346 PRINTF("rf_core_cmd_ok: SYNC_START_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
347 cmd_status, cmd_start.status);
348 return RF_CORE_CMD_ERROR;
349 }
350
351 return RF_CORE_CMD_OK;
352}
353/*---------------------------------------------------------------------------*/
354uint8_t
356{
357 rfc_CMD_SYNC_STOP_RAT_t cmd_stop;
358 uint32_t cmd_status;
359
360 rf_core_init_radio_op((rfc_radioOp_t *)&cmd_stop, sizeof(cmd_stop), CMD_SYNC_STOP_RAT);
361
362 int ret = rf_core_send_cmd((uint32_t)&cmd_stop, &cmd_status);
363 if(ret != RF_CORE_CMD_OK) {
364 PRINTF("rf_core_get_rat_rtc_offset: SYNC_STOP_RAT fail, ret %d CMDSTA=0x%08lx\n",
365 ret, cmd_status);
366 return ret;
367 }
368
369 /* Wait until done */
370 ret = rf_core_wait_cmd_done(&cmd_stop);
371 if(ret != RF_CORE_CMD_OK) {
372 PRINTF("rf_core_cmd_ok: SYNC_STOP_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
373 cmd_status, cmd_stop.status);
374 return ret;
375 }
376
377 if(!rat_offset_known) {
378 /* save the offset, but only if this is the first time */
379 rat_offset_known = true;
380 rat_offset = cmd_stop.rat0;
381 }
382
383 return RF_CORE_CMD_OK;
384}
385/*---------------------------------------------------------------------------*/
386void
388{
389 bool interrupts_disabled = ti_lib_int_master_disable();
390 ti_lib_int_disable(INT_RFC_CPE_0);
391 ti_lib_int_disable(INT_RFC_CPE_1);
392
394 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
395 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
396
397 /* need to send FS_POWERDOWN or analog components will use power */
398 fs_powerdown();
399 }
400
402
403 /* Shut down the RFCORE clock domain in the MCU VD */
404 ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE);
405 ti_lib_prcm_load_set();
406 while(!ti_lib_prcm_load_get());
407
408 /* Turn off RFCORE PD */
409 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE);
410 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
411 != PRCM_DOMAIN_POWER_OFF);
412
413 rf_switch_power_down();
414
415 ti_lib_int_pend_clear(INT_RFC_CPE_0);
416 ti_lib_int_pend_clear(INT_RFC_CPE_1);
417 ti_lib_int_enable(INT_RFC_CPE_0);
418 ti_lib_int_enable(INT_RFC_CPE_1);
419 if(!interrupts_disabled) {
420 ti_lib_int_master_enable();
421 }
422}
423/*---------------------------------------------------------------------------*/
424uint8_t
426{
427 uint8_t rv = RF_CORE_CMD_ERROR;
428 chip_type_t chip_type = ti_lib_chipinfo_get_chip_type();
429
430 if(chip_type == CHIP_TYPE_CC2650) {
431 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
432 rv = RF_CORE_CMD_OK;
433 } else if(chip_type == CHIP_TYPE_CC2630) {
434 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE2;
435 rv = RF_CORE_CMD_OK;
436 } else if(chip_type == CHIP_TYPE_CC1310) {
437 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE3;
438 rv = RF_CORE_CMD_OK;
439 } else if(chip_type == CHIP_TYPE_CC1350) {
440 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
441 rv = RF_CORE_CMD_OK;
442#if CPU_FAMILY_CC26X0R2
443 } else if(chip_type == CHIP_TYPE_CC2640R2) {
444 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE1;
445 rv = RF_CORE_CMD_OK;
446#endif
447 }
448
449 return rv;
450}
451/*---------------------------------------------------------------------------*/
452uint8_t
454{
455 if(rf_core_power_up() != RF_CORE_CMD_OK) {
456 PRINTF("rf_core_boot: rf_core_power_up() failed\n");
457
459
460 return RF_CORE_CMD_ERROR;
461 }
462
463 if(rf_core_start_rat() != RF_CORE_CMD_OK) {
464 PRINTF("rf_core_boot: rf_core_start_rat() failed\n");
465
467
468 return RF_CORE_CMD_ERROR;
469 }
470
471 return RF_CORE_CMD_OK;
472}
473/*---------------------------------------------------------------------------*/
474uint8_t
476{
477 if(rf_core_stop_rat() != RF_CORE_CMD_OK) {
478 PRINTF("rf_core_restart_rat: rf_core_stop_rat() failed\n");
479 /* Don't bail out here, still try to start it */
480 }
481
482 if(rf_core_start_rat() != RF_CORE_CMD_OK) {
483 PRINTF("rf_core_restart_rat: rf_core_start_rat() failed\n");
484
486
487 return RF_CORE_CMD_ERROR;
488 }
489
490 return RF_CORE_CMD_OK;
491}
492/*---------------------------------------------------------------------------*/
493void
495{
496 bool interrupts_disabled;
497 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
498
499 /* We are already turned on by the caller, so this should not happen */
500 if(!rf_core_is_accessible()) {
501 PRINTF("setup_interrupts: No access\n");
502 return;
503 }
504
505 /* Disable interrupts */
506 interrupts_disabled = ti_lib_int_master_disable();
507
508 /* Set all interrupt channels to CPE0 channel, error to CPE1 */
509 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;
510
511 /* Acknowledge configured interrupts */
512 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
513
514 /* Clear interrupt flags, active low clear(?) */
515 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
516
517 ti_lib_int_pend_clear(INT_RFC_CPE_0);
518 ti_lib_int_pend_clear(INT_RFC_CPE_1);
519 ti_lib_int_enable(INT_RFC_CPE_0);
520 ti_lib_int_enable(INT_RFC_CPE_1);
521
522 if(!interrupts_disabled) {
523 ti_lib_int_master_enable();
524 }
525}
526/*---------------------------------------------------------------------------*/
527void
529{
530 uint32_t irq = 0;
531 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
532
533 if(!rf_core_poll_mode) {
534 irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE;
535 }
536
537 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = enabled_irqs;
538 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs | irq;
539}
540/*---------------------------------------------------------------------------*/
541void
543{
544 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
545 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
546}
547/*---------------------------------------------------------------------------*/
548rfc_radioOp_t *
550{
551 return last_radio_op;
552}
553/*---------------------------------------------------------------------------*/
554void
555rf_core_init_radio_op(rfc_radioOp_t *op, uint16_t len, uint16_t command)
556{
557 memset(op, 0, len);
558
559 op->commandNo = command;
560 op->condition.rule = COND_NEVER;
561}
562/*---------------------------------------------------------------------------*/
563void
565{
566 primary_mode = mode;
567}
568/*---------------------------------------------------------------------------*/
569void
571{
572 if(primary_mode) {
573 if(primary_mode->abort) {
574 primary_mode->abort();
575 }
576 }
577}
578/*---------------------------------------------------------------------------*/
579uint8_t
581{
582 if(primary_mode) {
583 if(primary_mode->restore) {
584 return primary_mode->restore();
585 }
586 }
587
588 return RF_CORE_CMD_ERROR;
589}
590/*---------------------------------------------------------------------------*/
591uint8_t
593{
594 rat_last_value = HWREG(RFC_RAT_BASE + RATCNT);
595
596 ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_TIMER_INTERVAL,
597 rat_overflow_check_timer_cb, NULL);
598
599 return 1;
600}
601/*---------------------------------------------------------------------------*/
602uint8_t
604{
605 uint32_t rat_current_value;
606 uint8_t interrupts_disabled;
607
608 /* Bail out if the RF is not on */
609 if(primary_mode == NULL || !primary_mode->is_on()) {
610 return 0;
611 }
612
613 interrupts_disabled = ti_lib_int_master_disable();
614
615 rat_current_value = HWREG(RFC_RAT_BASE + RATCNT);
616 if(rat_current_value + RAT_RANGE / 4 < rat_last_value) {
617 /* Overflow detected */
618 rat_last_overflow = RTIMER_NOW();
619 rat_overflow_counter++;
620 }
621 rat_last_value = rat_current_value;
622
623 if(!interrupts_disabled) {
624 ti_lib_int_master_enable();
625 }
626
627 return 1;
628}
629/*---------------------------------------------------------------------------*/
630static void
631rat_overflow_check_timer_cb(void *unused)
632{
633 uint8_t success = 0;
634 uint8_t was_off = 0;
635
636 if(primary_mode != NULL) {
637
638 if(!primary_mode->is_on()) {
639 was_off = 1;
640 if(NETSTACK_RADIO.on() != RF_CORE_CMD_OK) {
641 PRINTF("overflow: on() failed\n");
642 ctimer_set(&rat_overflow_timer, CLOCK_SECOND,
643 rat_overflow_check_timer_cb, NULL);
644 return;
645 }
646 }
647
648 success = rf_core_check_rat_overflow();
649
650 if(was_off) {
651 NETSTACK_RADIO.off();
652 }
653 }
654
655 if(success) {
656 /* Retry after half of the interval */
657 ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_TIMER_INTERVAL,
658 rat_overflow_check_timer_cb, NULL);
659 } else {
660 /* Retry sooner */
661 ctimer_set(&rat_overflow_timer, CLOCK_SECOND,
662 rat_overflow_check_timer_cb, NULL);
663 }
664}
665/*---------------------------------------------------------------------------*/
666uint32_t
667rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
668{
669 uint64_t rat_timestamp64;
670 uint32_t adjusted_overflow_counter;
671 uint8_t was_off = 0;
672
673 if(primary_mode == NULL) {
674 PRINTF("rf_core_convert_rat_to_rtimer: not initialized\n");
675 return 0;
676 }
677
678 if(!primary_mode->is_on()) {
679 was_off = 1;
680 NETSTACK_RADIO.on();
681 }
682
684
685 if(was_off) {
686 NETSTACK_RADIO.off();
687 }
688
689 adjusted_overflow_counter = rat_overflow_counter;
690
691 /* if the timestamp is large and the last oveflow was recently,
692 assume that the timestamp refers to the time before the overflow */
693 if(rat_timestamp > (uint32_t)(RAT_RANGE * 3 / 4)) {
694 if(RTIMER_CLOCK_LT(RTIMER_NOW(),
695 rat_last_overflow + RAT_OVERFLOW_PERIOD_SECONDS * RTIMER_SECOND / 4)) {
696 adjusted_overflow_counter--;
697 }
698 }
699
700 /* add the overflowed time to the timestamp */
701 rat_timestamp64 = rat_timestamp + RAT_RANGE * adjusted_overflow_counter;
702 /* correct timestamp so that it refers to the end of the SFD */
703 rat_timestamp64 += primary_mode->sfd_timestamp_offset;
704
705 return RADIO_TO_RTIMER(rat_timestamp64 - rat_offset);
706}
707/*---------------------------------------------------------------------------*/
708PROCESS_THREAD(rf_core_process, ev, data)
709{
710 int len;
711
713
714 while(1) {
715 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
716 do {
719 len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
720
721 if(len > 0) {
723
724 NETSTACK_MAC.input();
725 }
726 } while(len > 0);
727 }
728 PROCESS_END();
729}
730/*---------------------------------------------------------------------------*/
731static void
732rx_nok_isr(void)
733{
734}
735/*---------------------------------------------------------------------------*/
736void
737cc26xx_rf_cpe1_isr(void)
738{
739 PRINTF("RF Error\n");
740
741 if(!rf_core_is_accessible()) {
742 if(rf_core_power_up() != RF_CORE_CMD_OK) {
743 return;
744 }
745 }
746
747 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_RX_BUF_FULL) {
748 PRINTF("\nRF: BUF_FULL\n\n");
749 /* set a flag that the buffer is full*/
750 rf_core_rx_is_full = true;
751 /* make sure read_frame() will be called to make space in RX buffer */
752 process_poll(&rf_core_process);
753 /* Clear the IRQ_RX_BUF_FULL interrupt flag by writing zero to bit */
754 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ~(IRQ_RX_BUF_FULL);
755 }
756
757 /* Clear INTERNAL_ERROR interrupt flag */
758 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x7FFFFFFF;
759}
760/*---------------------------------------------------------------------------*/
761void
762cc26xx_rf_cpe0_isr(void)
763{
764 if(!rf_core_is_accessible()) {
765 PRINTF("RF ISR called but RF not ready... PANIC!!\n");
766 if(rf_core_power_up() != RF_CORE_CMD_OK) {
767 PRINTF("rf_core_power_up() failed\n");
768 return;
769 }
770 }
771
772 ti_lib_int_master_disable();
773
774 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_FRAME_IRQ) {
775 /* Clear the RX_ENTRY_DONE interrupt flag */
776 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFF7FFFFF;
777 process_poll(&rf_core_process);
778 }
779
780 if(RF_CORE_DEBUG_CRC) {
781 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_NOK_IRQ) {
782 /* Clear the RX_NOK interrupt flag */
783 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFDFFFF;
784 rx_nok_isr();
785 }
786 }
787
788 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) &
789 (IRQ_LAST_FG_COMMAND_DONE | IRQ_LAST_COMMAND_DONE)) {
790 /* Clear the two TX-related interrupt flags */
791 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFFFFF5;
792 }
793
794 ti_lib_int_master_enable();
795}
796/*---------------------------------------------------------------------------*/
797/** @} */
Default definitions of C compiler quirk work-arounds.
Header file for the energy estimation mechanism.
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1110
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:85
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:136
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:143
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:67
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:75
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
void rf_core_primary_mode_abort()
Abort the currently running primary radio op.
Definition: rf-core.c:570
void rf_core_cmd_done_dis(void)
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
Definition: rf-core.c:542
void rf_core_init_radio_op(rfc_radioOp_t *op, uint16_t len, uint16_t command)
Prepare a buffer to host a Radio Op.
Definition: rf-core.c:555
uint8_t rf_core_stop_rat(void)
Stop the CM0 RAT synchronously.
Definition: rf-core.c:355
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
Definition: rf-core.c:387
uint32_t rf_core_cmd_status(void)
Get the status of the last issued radio command.
Definition: rf-core.c:250
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
Definition: rf-core.c:156
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
Definition: rf-core.c:147
rfc_radioOp_t * rf_core_get_last_radio_op()
Returns a pointer to the most recent proto-dependent Radio Op.
Definition: rf-core.c:549
int rf_core_power_up()
Turn on power to the RFC and boot it.
Definition: rf-core.c:278
uint8_t rf_core_boot()
Boot the RF Core.
Definition: rf-core.c:453
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
Definition: rf-core.c:425
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.
Definition: rf-core.c:228
uint32_t rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
Convert from RAT timestamp to rtimer ticks.
Definition: rf-core.c:667
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
Definition: rf-core.c:528
uint8_t rf_core_restart_rat(void)
Restart the CM0 RAT.
Definition: rf-core.c:475
void rf_core_primary_mode_register(const rf_core_primary_mode_t *mode)
Register a primary mode for radio operation.
Definition: rf-core.c:564
void rf_core_setup_interrupts(void)
Setup RF core interrupts.
Definition: rf-core.c:494
uint8_t rf_core_rat_init(void)
Initialize the RAT to RTC conversion machinery.
Definition: rf-core.c:592
uint8_t rf_core_primary_mode_restore()
Abort the currently running primary radio op.
Definition: rf-core.c:580
uint8_t rf_core_check_rat_overflow(void)
Check if RAT overflow has occured and increment the overflow counter if so.
Definition: rf-core.c:603
uint8_t rf_core_start_rat(void)
Start the CM0 RAT.
Definition: rf-core.c:327
#define RTIMER_SECOND
Number of rtimer ticks for 1 second.
Definition: rtimer.h:112
#define RTIMER_NOW()
Get the current clock time.
Definition: rtimer.h:185
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Header file for the Contiki process interface.
Header file for the CC13xx/CC26xx RF core driver.
Header file with definitions related to RF switch support.
void(* input)(void)
Callback for getting notified of incoming packet.
Definition: mac.h:72
A data strcuture representing the radio's primary mode of operation.
Definition: rf-core.h:125
void(* abort)(void)
A pointer to a function used to abort the current radio op.
Definition: rf-core.h:129
int16_t sfd_timestamp_offset
Offset of the end of SFD when compared to the radio HW-generated timestamp.
Definition: rf-core.h:146
uint8_t(* restore)(void)
A pointer to a function that will restore the previous radio op.
Definition: rf-core.h:135
uint8_t(* is_on)(void)
A pointer to a function that checks if the radio is on.
Definition: rf-core.h:141
Header file with macros which rename TI CC26xxware functions.