Contiki-NG
Loading...
Searching...
No Matches
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/* Status of the last command sent */
132volatile uint32_t last_cmd_status;
133/*---------------------------------------------------------------------------*/
134PROCESS(rf_core_process, "CC13xx / CC26xx RF driver");
135/*---------------------------------------------------------------------------*/
136#define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \
137 | RFC_PWR_PWMCLKEN_CPERAM_M | RFC_PWR_PWMCLKEN_FSCA_M \
138 | RFC_PWR_PWMCLKEN_PHA_M | RFC_PWR_PWMCLKEN_RAT_M \
139 | RFC_PWR_PWMCLKEN_RFERAM_M | RFC_PWR_PWMCLKEN_RFE_M \
140 | RFC_PWR_PWMCLKEN_MDMRAM_M | RFC_PWR_PWMCLKEN_MDM_M)
141/*---------------------------------------------------------------------------*/
142#define RF_CMD0 0x0607
143/*---------------------------------------------------------------------------*/
144uint8_t
146{
147 if(ti_lib_prcm_rf_ready()) {
148 return RF_CORE_ACCESSIBLE;
149 }
150 return RF_CORE_NOT_ACCESSIBLE;
151}
152/*---------------------------------------------------------------------------*/
153uint_fast8_t
154rf_core_send_cmd(uint32_t cmd, uint32_t *status)
155{
156 uint32_t timeout_count = 0;
157 bool interrupts_disabled;
158 bool is_radio_op = false;
159
160 /* reset the status variables to invalid values */
161 last_cmd_status = (uint32_t)-1;
162 *status = last_cmd_status;
163
164 /*
165 * If cmd is 4-byte aligned, then it's either a radio OP or an immediate
166 * command. Clear the status field if it's a radio OP
167 */
168 if((cmd & 0x03) == 0) {
169 uint32_t cmd_type;
170 cmd_type = ((rfc_command_t *)cmd)->commandNo & RF_CORE_COMMAND_TYPE_MASK;
171 if(cmd_type == RF_CORE_COMMAND_TYPE_IEEE_FG_RADIO_OP ||
172 cmd_type == RF_CORE_COMMAND_TYPE_RADIO_OP) {
173 is_radio_op = true;
174 ((rfc_radioOp_t *)cmd)->status = RF_CORE_RADIO_OP_STATUS_IDLE;
175 }
176 }
177
178 /*
179 * Make sure ContikiMAC doesn't turn us off from within an interrupt while
180 * we are accessing RF Core registers
181 */
182 interrupts_disabled = ti_lib_int_master_disable();
183
184 if(!rf_core_is_accessible()) {
185 PRINTF("rf_core_send_cmd: RF was off\n");
186 if(!interrupts_disabled) {
187 ti_lib_int_master_enable();
188 }
189 return RF_CORE_CMD_ERROR;
190 }
191
192 if(is_radio_op) {
193 uint16_t command_no = ((rfc_radioOp_t *)cmd)->commandNo;
194 if((command_no & RF_CORE_COMMAND_PROTOCOL_MASK) != RF_CORE_COMMAND_PROTOCOL_COMMON &&
195 (command_no & RF_CORE_COMMAND_TYPE_MASK) == RF_CORE_COMMAND_TYPE_RADIO_OP) {
196 last_radio_op = (rfc_radioOp_t *)cmd;
197 }
198 }
199
200 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd;
201 do {
202 last_cmd_status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA);
203 if(++timeout_count > 50000) {
204 PRINTF("rf_core_send_cmd: 0x%08lx Timeout\n", cmd);
205 if(!interrupts_disabled) {
206 ti_lib_int_master_enable();
207 }
208 *status = last_cmd_status;
209 return RF_CORE_CMD_ERROR;
210 }
211 } while((last_cmd_status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_PENDING);
212
213 if(!interrupts_disabled) {
214 ti_lib_int_master_enable();
215 }
216
217 /*
218 * If we reach here the command is no longer pending. It is either completed
219 * successfully or with error
220 */
221 *status = last_cmd_status;
222 return (last_cmd_status & RF_CORE_CMDSTA_RESULT_MASK) == RF_CORE_CMDSTA_DONE;
223}
224/*---------------------------------------------------------------------------*/
225uint_fast8_t
227{
228 volatile rfc_radioOp_t *command = (rfc_radioOp_t *)cmd;
229 uint32_t timeout_cnt = 0;
230
231 /*
232 * 0xn4nn=DONE, 0x0400=DONE_OK while all other "DONE" values means done
233 * but with some kind of error (ref. "Common radio operation status codes")
234 */
235 do {
236 if(++timeout_cnt > 500000) {
237 return RF_CORE_CMD_ERROR;
238 }
239 } while((command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
240 != RF_CORE_RADIO_OP_MASKED_STATUS_DONE);
241
242 last_cmd_status = command->status;
243 return (command->status & RF_CORE_RADIO_OP_MASKED_STATUS)
244 == RF_CORE_RADIO_OP_STATUS_DONE_OK;
245}
246/*---------------------------------------------------------------------------*/
247uint32_t
249{
250 return last_cmd_status;
251}
252/*---------------------------------------------------------------------------*/
253static int
254fs_powerdown(void)
255{
256 rfc_CMD_FS_POWERDOWN_t cmd;
257 uint32_t cmd_status;
258
259 rf_core_init_radio_op((rfc_radioOp_t *)&cmd, sizeof(cmd), CMD_FS_POWERDOWN);
260
261 if(rf_core_send_cmd((uint32_t)&cmd, &cmd_status) != RF_CORE_CMD_OK) {
262 PRINTF("fs_powerdown: CMDSTA=0x%08lx\n", cmd_status);
263 return RF_CORE_CMD_ERROR;
264 }
265
266 if(rf_core_wait_cmd_done(&cmd) != RF_CORE_CMD_OK) {
267 PRINTF("fs_powerdown: CMDSTA=0x%08lx, status=0x%04x\n",
268 cmd_status, cmd.status);
269 return RF_CORE_CMD_ERROR;
270 }
271
272 return RF_CORE_CMD_OK;
273}
274/*---------------------------------------------------------------------------*/
275int
277{
278 uint32_t cmd_status;
279 bool interrupts_disabled = ti_lib_int_master_disable();
280
281 ti_lib_int_pend_clear(INT_RFC_CPE_0);
282 ti_lib_int_pend_clear(INT_RFC_CPE_1);
283 ti_lib_int_disable(INT_RFC_CPE_0);
284 ti_lib_int_disable(INT_RFC_CPE_1);
285
286 /* Enable RF Core power domain */
287 ti_lib_prcm_power_domain_on(PRCM_DOMAIN_RFCORE);
288 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
289 != PRCM_DOMAIN_POWER_ON);
290
291 ti_lib_prcm_domain_enable(PRCM_DOMAIN_RFCORE);
292 ti_lib_prcm_load_set();
293 while(!ti_lib_prcm_load_get());
294
295 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
296 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
297 ti_lib_int_enable(INT_RFC_CPE_0);
298 ti_lib_int_enable(INT_RFC_CPE_1);
299
300 if(!interrupts_disabled) {
301 ti_lib_int_master_enable();
302 }
303
304 rf_switch_power_up();
305
306 /* Let CPE boot */
307 HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK;
308
309 /* Turn on additional clocks on boot */
310 HWREG(RFC_DBELL_BASE + RFC_DBELL_O_RFACKIFG) = 0;
311 HWREG(RFC_DBELL_BASE+RFC_DBELL_O_CMDR) =
312 CMDR_DIR_CMD_2BYTE(RF_CMD0,
313 RFC_PWR_PWMCLKEN_MDMRAM | RFC_PWR_PWMCLKEN_RFERAM);
314
315 /* Send ping (to verify RFCore is ready and alive) */
316 if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_PING), &cmd_status) != RF_CORE_CMD_OK) {
317 PRINTF("rf_core_power_up: CMD_PING fail, CMDSTA=0x%08lx\n", cmd_status);
318 return RF_CORE_CMD_ERROR;
319 }
320
321 return RF_CORE_CMD_OK;
322}
323/*---------------------------------------------------------------------------*/
324uint8_t
326{
327 uint32_t cmd_status;
328 rfc_CMD_SYNC_START_RAT_t cmd_start;
329
330 /* Start radio timer (RAT) */
331 rf_core_init_radio_op((rfc_radioOp_t *)&cmd_start, sizeof(cmd_start), CMD_SYNC_START_RAT);
332
333 /* copy the value and send back */
334 cmd_start.rat0 = rat_offset;
335
336 if(rf_core_send_cmd((uint32_t)&cmd_start, &cmd_status) != RF_CORE_CMD_OK) {
337 PRINTF("rf_core_get_rat_rtc_offset: SYNC_START_RAT fail, CMDSTA=0x%08lx\n",
338 cmd_status);
339 return RF_CORE_CMD_ERROR;
340 }
341
342 /* Wait until done (?) */
343 if(rf_core_wait_cmd_done(&cmd_start) != RF_CORE_CMD_OK) {
344 PRINTF("rf_core_cmd_ok: SYNC_START_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
345 cmd_status, cmd_start.status);
346 return RF_CORE_CMD_ERROR;
347 }
348
349 return RF_CORE_CMD_OK;
350}
351/*---------------------------------------------------------------------------*/
352uint8_t
354{
355 rfc_CMD_SYNC_STOP_RAT_t cmd_stop;
356 uint32_t cmd_status;
357
358 rf_core_init_radio_op((rfc_radioOp_t *)&cmd_stop, sizeof(cmd_stop), CMD_SYNC_STOP_RAT);
359
360 int ret = rf_core_send_cmd((uint32_t)&cmd_stop, &cmd_status);
361 if(ret != RF_CORE_CMD_OK) {
362 PRINTF("rf_core_get_rat_rtc_offset: SYNC_STOP_RAT fail, ret %d CMDSTA=0x%08lx\n",
363 ret, cmd_status);
364 return ret;
365 }
366
367 /* Wait until done */
368 ret = rf_core_wait_cmd_done(&cmd_stop);
369 if(ret != RF_CORE_CMD_OK) {
370 PRINTF("rf_core_cmd_ok: SYNC_STOP_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
371 cmd_status, cmd_stop.status);
372 return ret;
373 }
374
375 if(!rat_offset_known) {
376 /* save the offset, but only if this is the first time */
377 rat_offset_known = true;
378 rat_offset = cmd_stop.rat0;
379 }
380
381 return RF_CORE_CMD_OK;
382}
383/*---------------------------------------------------------------------------*/
384void
386{
387 bool interrupts_disabled = ti_lib_int_master_disable();
388 ti_lib_int_disable(INT_RFC_CPE_0);
389 ti_lib_int_disable(INT_RFC_CPE_1);
390
392 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
393 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0;
394
395 /* need to send FS_POWERDOWN or analog components will use power */
396 fs_powerdown();
397 }
398
400
401 /* Shut down the RFCORE clock domain in the MCU VD */
402 ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE);
403 ti_lib_prcm_load_set();
404 while(!ti_lib_prcm_load_get());
405
406 /* Turn off RFCORE PD */
407 ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE);
408 while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE)
409 != PRCM_DOMAIN_POWER_OFF);
410
411 rf_switch_power_down();
412
413 ti_lib_int_pend_clear(INT_RFC_CPE_0);
414 ti_lib_int_pend_clear(INT_RFC_CPE_1);
415 ti_lib_int_enable(INT_RFC_CPE_0);
416 ti_lib_int_enable(INT_RFC_CPE_1);
417 if(!interrupts_disabled) {
418 ti_lib_int_master_enable();
419 }
420}
421/*---------------------------------------------------------------------------*/
422uint8_t
424{
425 uint8_t rv = RF_CORE_CMD_ERROR;
426 chip_type_t chip_type = ti_lib_chipinfo_get_chip_type();
427
428 if(chip_type == CHIP_TYPE_CC2650) {
429 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
430 rv = RF_CORE_CMD_OK;
431 } else if(chip_type == CHIP_TYPE_CC2630) {
432 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE2;
433 rv = RF_CORE_CMD_OK;
434 } else if(chip_type == CHIP_TYPE_CC1310) {
435 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE3;
436 rv = RF_CORE_CMD_OK;
437 } else if(chip_type == CHIP_TYPE_CC1350) {
438 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5;
439 rv = RF_CORE_CMD_OK;
440#if CPU_FAMILY_CC26X0R2
441 } else if(chip_type == CHIP_TYPE_CC2640R2) {
442 HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE1;
443 rv = RF_CORE_CMD_OK;
444#endif
445 }
446
447 return rv;
448}
449/*---------------------------------------------------------------------------*/
450uint8_t
452{
453 if(rf_core_power_up() != RF_CORE_CMD_OK) {
454 PRINTF("rf_core_boot: rf_core_power_up() failed\n");
455
457
458 return RF_CORE_CMD_ERROR;
459 }
460
461 if(rf_core_start_rat() != RF_CORE_CMD_OK) {
462 PRINTF("rf_core_boot: rf_core_start_rat() failed\n");
463
465
466 return RF_CORE_CMD_ERROR;
467 }
468
469 return RF_CORE_CMD_OK;
470}
471/*---------------------------------------------------------------------------*/
472uint8_t
474{
475 if(rf_core_stop_rat() != RF_CORE_CMD_OK) {
476 PRINTF("rf_core_restart_rat: rf_core_stop_rat() failed\n");
477 /* Don't bail out here, still try to start it */
478 }
479
480 if(rf_core_start_rat() != RF_CORE_CMD_OK) {
481 PRINTF("rf_core_restart_rat: rf_core_start_rat() failed\n");
482
484
485 return RF_CORE_CMD_ERROR;
486 }
487
488 return RF_CORE_CMD_OK;
489}
490/*---------------------------------------------------------------------------*/
491void
493{
494 bool interrupts_disabled;
495 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
496
497 /* We are already turned on by the caller, so this should not happen */
498 if(!rf_core_is_accessible()) {
499 PRINTF("setup_interrupts: No access\n");
500 return;
501 }
502
503 /* Disable interrupts */
504 interrupts_disabled = ti_lib_int_master_disable();
505
506 /* Set all interrupt channels to CPE0 channel, error to CPE1 */
507 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;
508
509 /* Acknowledge configured interrupts */
510 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
511
512 /* Clear interrupt flags, active low clear(?) */
513 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
514
515 ti_lib_int_pend_clear(INT_RFC_CPE_0);
516 ti_lib_int_pend_clear(INT_RFC_CPE_1);
517 ti_lib_int_enable(INT_RFC_CPE_0);
518 ti_lib_int_enable(INT_RFC_CPE_1);
519
520 if(!interrupts_disabled) {
521 ti_lib_int_master_enable();
522 }
523}
524/*---------------------------------------------------------------------------*/
525void
527{
528 uint32_t irq = 0;
529 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
530
531 if(!rf_core_poll_mode) {
532 irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE;
533 }
534
535 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = enabled_irqs;
536 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs | irq;
537}
538/*---------------------------------------------------------------------------*/
539void
541{
542 const uint32_t enabled_irqs = rf_core_poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
543 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
544}
545/*---------------------------------------------------------------------------*/
546rfc_radioOp_t *
548{
549 return last_radio_op;
550}
551/*---------------------------------------------------------------------------*/
552void
553rf_core_init_radio_op(rfc_radioOp_t *op, uint16_t len, uint16_t command)
554{
555 memset(op, 0, len);
556
557 op->commandNo = command;
558 op->condition.rule = COND_NEVER;
559}
560/*---------------------------------------------------------------------------*/
561void
563{
564 primary_mode = mode;
565}
566/*---------------------------------------------------------------------------*/
567void
569{
570 if(primary_mode) {
571 if(primary_mode->abort) {
572 primary_mode->abort();
573 }
574 }
575}
576/*---------------------------------------------------------------------------*/
577uint8_t
579{
580 if(primary_mode) {
581 if(primary_mode->restore) {
582 return primary_mode->restore();
583 }
584 }
585
586 return RF_CORE_CMD_ERROR;
587}
588/*---------------------------------------------------------------------------*/
589uint8_t
591{
592 rat_last_value = HWREG(RFC_RAT_BASE + RATCNT);
593
594 ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_TIMER_INTERVAL,
595 rat_overflow_check_timer_cb, NULL);
596
597 return 1;
598}
599/*---------------------------------------------------------------------------*/
600uint8_t
602{
603 uint32_t rat_current_value;
604 uint8_t interrupts_disabled;
605
606 /* Bail out if the RF is not on */
607 if(primary_mode == NULL || !primary_mode->is_on()) {
608 return 0;
609 }
610
611 interrupts_disabled = ti_lib_int_master_disable();
612
613 rat_current_value = HWREG(RFC_RAT_BASE + RATCNT);
614 if(rat_current_value + RAT_RANGE / 4 < rat_last_value) {
615 /* Overflow detected */
616 rat_last_overflow = RTIMER_NOW();
617 rat_overflow_counter++;
618 }
619 rat_last_value = rat_current_value;
620
621 if(!interrupts_disabled) {
622 ti_lib_int_master_enable();
623 }
624
625 return 1;
626}
627/*---------------------------------------------------------------------------*/
628static void
629rat_overflow_check_timer_cb(void *unused)
630{
631 uint8_t success = 0;
632 uint8_t was_off = 0;
633
634 if(primary_mode != NULL) {
635
636 if(!primary_mode->is_on()) {
637 was_off = 1;
638 if(NETSTACK_RADIO.on() != RF_CORE_CMD_OK) {
639 PRINTF("overflow: on() failed\n");
640 ctimer_set(&rat_overflow_timer, CLOCK_SECOND,
641 rat_overflow_check_timer_cb, NULL);
642 return;
643 }
644 }
645
646 success = rf_core_check_rat_overflow();
647
648 if(was_off) {
649 NETSTACK_RADIO.off();
650 }
651 }
652
653 if(success) {
654 /* Retry after half of the interval */
655 ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_TIMER_INTERVAL,
656 rat_overflow_check_timer_cb, NULL);
657 } else {
658 /* Retry sooner */
659 ctimer_set(&rat_overflow_timer, CLOCK_SECOND,
660 rat_overflow_check_timer_cb, NULL);
661 }
662}
663/*---------------------------------------------------------------------------*/
664uint32_t
665rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
666{
667 uint64_t rat_timestamp64;
668 uint32_t adjusted_overflow_counter;
669 uint8_t was_off = 0;
670
671 if(primary_mode == NULL) {
672 PRINTF("rf_core_convert_rat_to_rtimer: not initialized\n");
673 return 0;
674 }
675
676 if(!primary_mode->is_on()) {
677 was_off = 1;
678 NETSTACK_RADIO.on();
679 }
680
682
683 if(was_off) {
684 NETSTACK_RADIO.off();
685 }
686
687 adjusted_overflow_counter = rat_overflow_counter;
688
689 /* if the timestamp is large and the last oveflow was recently,
690 assume that the timestamp refers to the time before the overflow */
691 if(rat_timestamp > (uint32_t)(RAT_RANGE * 3 / 4)) {
692 if(RTIMER_CLOCK_LT(RTIMER_NOW(),
693 rat_last_overflow + RAT_OVERFLOW_PERIOD_SECONDS * RTIMER_SECOND / 4)) {
694 adjusted_overflow_counter--;
695 }
696 }
697
698 /* add the overflowed time to the timestamp */
699 rat_timestamp64 = rat_timestamp + RAT_RANGE * adjusted_overflow_counter;
700 /* correct timestamp so that it refers to the end of the SFD */
701 rat_timestamp64 += primary_mode->sfd_timestamp_offset;
702
703 return RADIO_TO_RTIMER(rat_timestamp64 - rat_offset);
704}
705/*---------------------------------------------------------------------------*/
706PROCESS_THREAD(rf_core_process, ev, data)
707{
708 int len;
709
711
712 while(1) {
713 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
714 do {
717 len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
718
719 if(len > 0) {
721
722 NETSTACK_MAC.input();
723 }
724 } while(len > 0);
725 }
726 PROCESS_END();
727}
728/*---------------------------------------------------------------------------*/
729static void
730rx_nok_isr(void)
731{
732}
733/*---------------------------------------------------------------------------*/
734void
735cc26xx_rf_cpe1_isr(void)
736{
737 PRINTF("RF Error\n");
738
739 if(!rf_core_is_accessible()) {
740 if(rf_core_power_up() != RF_CORE_CMD_OK) {
741 return;
742 }
743 }
744
745 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & IRQ_RX_BUF_FULL) {
746 PRINTF("\nRF: BUF_FULL\n\n");
747 /* make sure read_frame() will be called to make space in RX buffer */
748 process_poll(&rf_core_process);
749 /* Clear the IRQ_RX_BUF_FULL interrupt flag by writing zero to bit */
750 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ~(IRQ_RX_BUF_FULL);
751 }
752
753 /* Clear INTERNAL_ERROR interrupt flag */
754 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x7FFFFFFF;
755}
756/*---------------------------------------------------------------------------*/
757void
758cc26xx_rf_cpe0_isr(void)
759{
760 if(!rf_core_is_accessible()) {
761 PRINTF("RF ISR called but RF not ready... PANIC!!\n");
762 if(rf_core_power_up() != RF_CORE_CMD_OK) {
763 PRINTF("rf_core_power_up() failed\n");
764 return;
765 }
766 }
767
768 ti_lib_int_master_disable();
769
770 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_FRAME_IRQ) {
771 /* Clear the RX_ENTRY_DONE interrupt flag */
772 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFF7FFFFF;
773 process_poll(&rf_core_process);
774 }
775
776 if(RF_CORE_DEBUG_CRC) {
777 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_NOK_IRQ) {
778 /* Clear the RX_NOK interrupt flag */
779 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFDFFFF;
780 rx_nok_isr();
781 }
782 }
783
784 if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) &
785 (IRQ_LAST_FG_COMMAND_DONE | IRQ_LAST_COMMAND_DONE)) {
786 /* Clear the two TX-related interrupt flags */
787 HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0xFFFFFFF5;
788 }
789
790 ti_lib_int_master_enable();
791}
792/*---------------------------------------------------------------------------*/
793/** @} */
Default definitions of C compiler quirk work-arounds.
Header file for the energy estimation mechanism.
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:103
static void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition ctimer.h:137
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_THREAD(name, ev, data)
Define the body of a process.
Definition process.h:273
#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:375
void rf_core_primary_mode_abort()
Abort the currently running primary radio op.
Definition rf-core.c:568
void rf_core_cmd_done_dis(void)
Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
Definition rf-core.c:540
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:553
uint8_t rf_core_stop_rat(void)
Stop the CM0 RAT synchronously.
Definition rf-core.c:353
void rf_core_power_down()
Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD.
Definition rf-core.c:385
uint32_t rf_core_cmd_status(void)
Get the status of the last issued radio command.
Definition rf-core.c:248
uint_fast8_t rf_core_send_cmd(uint32_t cmd, uint32_t *status)
Sends a command to the RF core.
Definition rf-core.c:154
uint8_t rf_core_is_accessible()
Check whether the RF core is accessible.
Definition rf-core.c:145
rfc_radioOp_t * rf_core_get_last_radio_op()
Returns a pointer to the most recent proto-dependent Radio Op.
Definition rf-core.c:547
int rf_core_power_up()
Turn on power to the RFC and boot it.
Definition rf-core.c:276
uint8_t rf_core_boot()
Boot the RF Core.
Definition rf-core.c:451
uint8_t rf_core_set_modesel()
Initialise RF APIs in the RF core.
Definition rf-core.c:423
uint_fast8_t rf_core_wait_cmd_done(void *cmd)
Block and wait for a Radio op to complete.
Definition rf-core.c:226
uint32_t rf_core_convert_rat_to_rtimer(uint32_t rat_timestamp)
Convert from RAT timestamp to rtimer ticks.
Definition rf-core.c:665
void rf_core_cmd_done_en(bool fg)
Enable interrupt on command done.
Definition rf-core.c:526
uint8_t rf_core_restart_rat(void)
Restart the CM0 RAT.
Definition rf-core.c:473
void rf_core_primary_mode_register(const rf_core_primary_mode_t *mode)
Register a primary mode for radio operation.
Definition rf-core.c:562
void rf_core_setup_interrupts(void)
Setup RF core interrupts.
Definition rf-core.c:492
uint8_t rf_core_rat_init(void)
Initialize the RAT to RTC conversion machinery.
Definition rf-core.c:590
uint8_t rf_core_primary_mode_restore()
Abort the currently running primary radio op.
Definition rf-core.c:578
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:601
uint8_t rf_core_start_rat(void)
Start the CM0 RAT.
Definition rf-core.c:325
#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:187
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:78
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.