Contiki-NG
nrf52840-ieee.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020, Toshiba BRIL
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 nrf52840
33 * @{
34 *
35 * \addtogroup nrf52840-dev Device drivers
36 * @{
37 *
38 * \defgroup nrf52840-rf-ieee nRF52840 IEEE mode driver
39 *
40 * @{
41 *
42 * \file
43 * Implementation of the nRF52840 IEEE mode NETSTACK_RADIO driver
44 */
45/*---------------------------------------------------------------------------*/
46#include "contiki.h"
47#include "dev/radio.h"
48#include "sys/energest.h"
49#include "sys/int-master.h"
50#include "sys/critical.h"
51#include "net/netstack.h"
52#include "net/packetbuf.h"
53#include "net/mac/tsch/tsch.h"
54#include "nrf_radio.h"
55#include "nrf_ppi.h"
56#include "nrf_timer.h"
57#include "nrf_clock.h"
58
59#include <stdint.h>
60#include <stdbool.h>
61#include <string.h>
62/*---------------------------------------------------------------------------*/
63/*
64 * Log configuration
65 *
66 * NB: LOG_LEVEL_DBG should only be used to validate radio driver operation.
67 *
68 * Setting LOG_LEVEL to LOG_LEVEL_DBG will mess-up all MAC-layer ACK-related
69 * timings, including the time we spend waiting for an ACK and the time it
70 * takes us to transmit one. Expect all unicast communications to become
71 * erratic or to break altogether.
72 */
73#include "sys/log.h"
74
75#define LOG_MODULE "nRF52840 IEEE"
76#define LOG_LEVEL LOG_LEVEL_ERR
77/*---------------------------------------------------------------------------*/
78#define NRF52840_CCA_BUSY 0
79#define NRF52840_CCA_CLEAR 1
80/*---------------------------------------------------------------------------*/
81#define NRF52840_RECEIVING_NO 0
82#define NRF52840_RECEIVING_YES 1
83/*---------------------------------------------------------------------------*/
84#define NRF52840_PENDING_NO 0
85#define NRF52840_PENDING_YES 1
86/*---------------------------------------------------------------------------*/
87#define NRF52840_COMMAND_ERR 0
88#define NRF52840_COMMAND_OK 1
89/*---------------------------------------------------------------------------*/
90#define NRF52840_CHANNEL_MIN 11
91#define NRF52840_CHANNEL_MAX 26
92/*---------------------------------------------------------------------------*/
93#define ED_RSSISCALE 4
94/*---------------------------------------------------------------------------*/
95#define FCS_LEN 2
96#define MPDU_LEN 127
97/*
98 * The maximum number of bytes this driver can accept from the MAC layer for
99 * transmission or will deliver to the MAC layer after reception. Includes
100 * the MAC header and payload, but not the FCS.
101 */
102#define MAX_PAYLOAD_LEN (MPDU_LEN - FCS_LEN)
103
104#define ACK_MPDU_MIN_LEN 5
105#define ACK_PAYLOAD_MIN_LEN (ACK_MPDU_MIN_LEN - FCS_LEN)
106/*---------------------------------------------------------------------------*/
107/*
108 * The last frame's RSSI and LQI
109 *
110 * Unlike other radios that write RSSI and LQI in the FCS, the nrf52840
111 * only writes one value. This is a "hardware-reported" value, which needs
112 * converted to the .15.4 standard LQI scale using an 8-bit saturating
113 * multiplication by 4 (see the Product Spec). This value is based on the
114 * median of three RSSI samples taken during frame reception.
115 */
116static int8_t last_rssi;
117static uint8_t last_lqi;
118/*---------------------------------------------------------------------------*/
119PROCESS(nrf52840_ieee_rf_process, "nRF52840 IEEE RF driver");
120/*---------------------------------------------------------------------------*/
121#ifndef NRF52840_CCA_MODE
122#define NRF52840_CCA_MODE RADIO_CCACTRL_CCAMODE_CarrierAndEdMode
123#endif
124
125#ifndef NRF52840_CCA_ED_THRESHOLD
126#define NRF52840_CCA_ED_THRESHOLD 0x14
127#endif
128
129#ifndef NRF52840_CCA_CORR_THRESHOLD
130#define NRF52840_CCA_CORR_THRESHOLD 0x14
131#endif
132
133#ifndef NRF52840_CCA_CORR_COUNT
134#define NRF52840_CCA_CORR_COUNT 0x02
135#endif
136/*---------------------------------------------------------------------------*/
137/*
138 * .15.4-compliant CRC:
139 *
140 * Lenght 2, Initial value 0.
141 *
142 * Polynomial x^16 + x^12 + x^5 + 1
143 * CRCPOLY: 1 00010000 00100001
144 */
145#define CRC_IEEE802154_LEN 2
146#define CRC_IEEE802154_POLY 0x11021
147#define CRC_IEEE802154_INIT 0
148/*---------------------------------------------------------------------------*/
149#define SYMBOL_DURATION_USEC 16
150#define SYMBOL_DURATION_RTIMER 1
151#define BYTE_DURATION_RTIMER (SYMBOL_DURATION_RTIMER * 2)
152#define TXRU_DURATION_TIMER 3
153/*---------------------------------------------------------------------------*/
154typedef struct timestamps_s {
155 rtimer_clock_t sfd; /* Derived: 1 byte = 2 rtimer ticks before FRAMESTART */
156 rtimer_clock_t framestart; /* PPI Channel 0 */
157 rtimer_clock_t end; /* PPI pre-programmed Channel 27 */
158 rtimer_clock_t mpdu_duration; /* Calculated: PHR * 2 rtimer ticks */
159 uint8_t phr; /* PHR: The MPDU length in bytes */
160} timestamps_t;
161
162static volatile timestamps_t timestamps;
163/*---------------------------------------------------------------------------*/
164typedef struct tx_buf_s {
165 uint8_t phr;
166 uint8_t mpdu[MAX_PAYLOAD_LEN];
167} tx_buf_t;
168
169static tx_buf_t tx_buf;
170/*---------------------------------------------------------------------------*/
171typedef struct rx_buf_s {
172 uint8_t phr;
173 uint8_t mpdu[MPDU_LEN];
174 bool full; /* Used in interrupt / non-poll mode for additional state */
175} rx_buf_t;
176
177static rx_buf_t rx_buf;
178/*---------------------------------------------------------------------------*/
179typedef struct rf_cfg_s {
180 bool poll_mode;
181 nrf_radio_txpower_t txpower;
182 uint8_t channel;
183 uint8_t send_on_cca; /* Perform CCA before TX */
184 uint8_t cca_mode;
185 uint8_t cca_corr_threshold;
186 uint8_t cca_corr_count;
187 uint8_t ed_threshold;
188} rf_cfg_t;
189
190static volatile rf_cfg_t rf_config = {
191 .poll_mode = false,
192 .txpower = NRF_RADIO_TXPOWER_0DBM,
193 .send_on_cca = RADIO_TX_MODE_SEND_ON_CCA,
195 .cca_mode = NRF52840_CCA_MODE,
196 .cca_corr_threshold = NRF52840_CCA_CORR_THRESHOLD,
197 .cca_corr_count = NRF52840_CCA_CORR_COUNT,
198 .ed_threshold = NRF52840_CCA_ED_THRESHOLD,
199};
200/*---------------------------------------------------------------------------*/
201static bool
202phr_is_valid(uint8_t phr)
203{
204 if(phr < ACK_MPDU_MIN_LEN || phr > MPDU_LEN) {
205 return false;
206 }
207 return true;
208}
209/*---------------------------------------------------------------------------*/
210static bool
211radio_is_powered(void)
212{
213 return NRF_RADIO->POWER == 0 ? false : true;
214}
215/*---------------------------------------------------------------------------*/
216static uint8_t
217get_channel(void)
218{
219 return NRF_RADIO->FREQUENCY / 5 + 10;
220}
221/*---------------------------------------------------------------------------*/
222static void
223set_channel(uint8_t channel)
224{
225 NRF_RADIO->FREQUENCY = 5 * (channel - 10);
226}
227/*---------------------------------------------------------------------------*/
228static void
229cca_reconfigure(void)
230{
231 uint32_t ccactrl;
232
233 ccactrl = rf_config.cca_mode;
234 ccactrl |= rf_config.ed_threshold << RADIO_CCACTRL_CCAEDTHRES_Pos;
235 ccactrl |= rf_config.cca_corr_count << RADIO_CCACTRL_CCACORRCNT_Pos;
236 ccactrl |= rf_config.cca_corr_threshold << RADIO_CCACTRL_CCACORRTHRES_Pos;
237
238 NRF_RADIO->CCACTRL = ccactrl;
239}
240/*---------------------------------------------------------------------------*/
241static void
242crc_init(void)
243{
244 /*
245 * Initialise the CRC engine in .15.4 mode:
246 * - Length: 2 bytes
247 * - Polynomial:
248 * - Initial value: 0
249 */
250 nrf_radio_crc_configure(CRC_IEEE802154_LEN, NRF_RADIO_CRC_ADDR_IEEE802154,
251 CRC_IEEE802154_POLY);
252
253 nrf_radio_crcinit_set(CRC_IEEE802154_INIT);
254}
255/*---------------------------------------------------------------------------*/
256static void
257packet_init(void)
258{
259 /* Configure packet format for .15.4 */
260 nrf_radio_packet_conf_t conf;
261
262 memset(&conf, 0, sizeof(conf));
263
264 conf.lflen = 8; /* Length field, in bits */
265 conf.s1incl = false;
266 conf.plen = NRF_RADIO_PREAMBLE_LENGTH_32BIT_ZERO;
267 conf.crcinc = true;
268 conf.big_endian = false;
269 conf.whiteen = false;
270 conf.maxlen = MPDU_LEN;
271
272 nrf_radio_packet_configure(&conf);
273}
274/*---------------------------------------------------------------------------*/
275static void
276setup_interrupts(void)
277{
279 nrf_radio_int_mask_t interrupts = 0;
280
281 stat = critical_enter();
282
283 if(!rf_config.poll_mode) {
284 nrf_radio_event_clear(NRF_RADIO_EVENT_CRCOK);
285 nrf_radio_event_clear(NRF_RADIO_EVENT_CRCERROR);
286 interrupts |= NRF_RADIO_INT_CRCOK_MASK | NRF_RADIO_INT_CRCERROR_MASK;
287 }
288
289 /* Make sure all interrupts are disabled before we enable selectively */
290 nrf_radio_int_disable(0xFFFFFFFF);
291 NVIC_ClearPendingIRQ(RADIO_IRQn);
292
293 if(interrupts) {
294 nrf_radio_int_enable(interrupts);
295 NVIC_EnableIRQ(RADIO_IRQn);
296 } else {
297 /* No radio interrupts required. Make sure they are all off at the NVIC */
298 NVIC_DisableIRQ(RADIO_IRQn);
299 }
300
301 critical_exit(stat);
302}
303/*---------------------------------------------------------------------------*/
304/*
305 * Set up timestamping with PPI:
306 * - Enable the pre-programmed Channel 27: RADIO->END--->TIMER0->CAPTURE[2]
307 * - Programme Channel 0 for RADIO->FRAMESTART--->TIMER0->CAPTURE[3]
308 */
309static void
310setup_ppi_timestamping(void)
311{
312 nrf_ppi_channel_endpoint_setup(
313 NRF_PPI_CHANNEL0,
314 (uint32_t)nrf_radio_event_address_get(NRF_RADIO_EVENT_FRAMESTART),
315 (uint32_t)nrf_timer_task_address_get(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3));
316 nrf_ppi_channel_enable(NRF_PPI_CHANNEL0);
317 nrf_ppi_channel_enable(NRF_PPI_CHANNEL27);
318}
319/*---------------------------------------------------------------------------*/
320static void
321set_poll_mode(bool enable)
322{
323 rf_config.poll_mode = enable;
324 setup_interrupts();
325}
326/*---------------------------------------------------------------------------*/
327static void
328rx_buf_clear(void)
329{
330 memset(&rx_buf, 0, sizeof(rx_buf));
331}
332/*---------------------------------------------------------------------------*/
333static void
334rx_events_clear()
335{
336 nrf_radio_event_clear(NRF_RADIO_EVENT_FRAMESTART);
337 nrf_radio_event_clear(NRF_RADIO_EVENT_END);
338 nrf_radio_event_clear(NRF_RADIO_EVENT_CRCERROR);
339 nrf_radio_event_clear(NRF_RADIO_EVENT_CRCOK);
340}
341/*---------------------------------------------------------------------------*/
342/*
343 * Powering off the peripheral will reset all registers to default values
344 * This function here must be called at every power on to set the radio in a
345 * known state
346 */
347static void
348configure(void)
349{
350 nrf_radio_mode_set(NRF_RADIO_MODE_IEEE802154_250KBIT);
351
352 set_channel(rf_config.channel);
353
354 cca_reconfigure();
355
356 /* Initialise the CRC engine in .15.4 mode */
357 crc_init();
358
359 /* Initialise the packet format */
360 packet_init();
361
362 /*
363 * MODECNF: Fast ramp up, DTX=center
364 * The Nordic driver is using DTX=0, but this is against the PS (v1.1 p351)
365 */
366 nrf_radio_modecnf0_set(true, RADIO_MODECNF0_DTX_Center);
367}
368/*---------------------------------------------------------------------------*/
369static void
370power_on_and_configure(void)
371{
372 nrf_radio_power_set(true);
373 configure();
374}
375/*---------------------------------------------------------------------------*/
376/*
377 * The caller must first make sure the radio is powered and configured.
378 *
379 * When we enter this function we can be in one of the following states:
380 * - STATE_RX: We were already in RX. Do nothing
381 * - STATE_RXIDLE: A reception just finished and we reverted to RXIDLE.
382 * We just need to send the START task.
383 * - STATE_TXIDLE: A TX just finished and we reverted to TXIDLE.
384 * We just need to send the START task.
385 * - STATE_DISABLED: We just turned on. We need to request radio rampup
386 */
387static void
388enter_rx(void)
389{
390 nrf_radio_state_t curr_state = nrf_radio_state_get();
391
392 LOG_DBG("Enter RX, state=%u", curr_state);
393
394 /* Do nothing if we are already in RX */
395 if(curr_state == NRF_RADIO_STATE_RX) {
396 LOG_DBG_(". Was in RX");
397 LOG_DBG_("\n");
398 return;
399 }
400
401 /* Prepare the RX buffer */
402 nrf_radio_packetptr_set(&rx_buf);
403
404 /* Initiate PPI timestamping */
405 setup_ppi_timestamping();
406
407 /* Make sure the correct interrupts are enabled */
408 setup_interrupts();
409
410 nrf_radio_shorts_enable(NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK);
411 nrf_radio_shorts_enable(NRF_RADIO_SHORT_RXREADY_START_MASK);
412
413 if(curr_state != NRF_RADIO_STATE_RXIDLE) {
414 /* Clear EVENTS_RXREADY and trigger RXEN (which will trigger START) */
415 nrf_radio_event_clear(NRF_RADIO_EVENT_RXREADY);
416 nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN);
417 } else {
418 /* Trigger the Start task */
419 nrf_radio_task_trigger(NRF_RADIO_TASK_START);
420 }
421
422 LOG_DBG_("--->%u\n", nrf_radio_state_get());
423
424 LOG_DBG("PACKETPTR=0x%08lx (rx_buf @ 0x%08lx)\n",
425 (uint32_t)nrf_radio_packetptr_get(), (uint32_t)&rx_buf);
426}
427/*---------------------------------------------------------------------------*/
428/* Retrieve an RSSI sample. The radio must be in RX mode */
429static int8_t
430rssi_read(void)
431{
432 uint8_t rssi_sample;
433
434 nrf_radio_task_trigger(NRF_RADIO_TASK_RSSISTART);
435
436 while(nrf_radio_event_check(NRF_RADIO_EVENT_RSSIEND) == false);
437 nrf_radio_event_clear(NRF_RADIO_EVENT_RSSIEND);
438
439 rssi_sample = nrf_radio_rssi_sample_get();
440
441 return -((int8_t)rssi_sample);
442}
443/*---------------------------------------------------------------------------*/
444/*
445 * Convert the hardware-reported LQI to 802.15.4 range using an 8-bit
446 * saturating multiplication by 4, as per the Product Spec.
447 */
448static uint8_t
449lqi_convert_to_802154_scale(uint8_t lqi_hw)
450{
451 return (uint8_t)lqi_hw > 63 ? 255 : lqi_hw * ED_RSSISCALE;
452}
453/*---------------------------------------------------------------------------*/
454/* Netstack API functions */
455/*---------------------------------------------------------------------------*/
456static int
457on(void)
458{
459 LOG_DBG("On\n");
460
461 if(radio_is_powered() == false) {
462 LOG_DBG("Not powered\n");
463 power_on_and_configure();
464 }
465
466 enter_rx();
467
468 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
469 return NRF52840_COMMAND_OK;
470}
471/*---------------------------------------------------------------------------*/
472static int
473channel_clear(void)
474{
475 bool busy, idle;
476
477 LOG_DBG("channel_clear\n");
478
479 on();
480
481 /* Clear previous CCA-related events, if any */
482 nrf_radio_event_clear(NRF_RADIO_EVENT_CCABUSY);
483 nrf_radio_event_clear(NRF_RADIO_EVENT_CCAIDLE);
484 nrf_radio_event_clear(NRF_RADIO_EVENT_CCASTOPPED);
485
486 LOG_DBG("channel_clear: CCACTRL=0x%08lx\n", NRF_RADIO->CCACTRL);
487
488 /* We are now in RX. Send CCASTART */
489 nrf_radio_task_trigger(NRF_RADIO_TASK_CCASTART);
490
491 while((nrf_radio_event_check(NRF_RADIO_EVENT_CCABUSY) == false) &&
492 (nrf_radio_event_check(NRF_RADIO_EVENT_CCAIDLE) == false));
493
494 busy = nrf_radio_event_check(NRF_RADIO_EVENT_CCABUSY);
495 idle = nrf_radio_event_check(NRF_RADIO_EVENT_CCAIDLE);
496
497 LOG_DBG("channel_clear: I=%u, B=%u\n", idle, busy);
498
499 if(busy) {
500 return NRF52840_CCA_BUSY;
501 }
502
503 return NRF52840_CCA_CLEAR;
504}
505/*---------------------------------------------------------------------------*/
506static int
507init(void)
508{
509 LOG_DBG("Init\n");
510
511 last_rssi = 0;
512 last_lqi = 0;
513
514 timestamps.sfd = 0;
515 timestamps.framestart = 0;
516 timestamps.end = 0;
517 timestamps.mpdu_duration = 0;
518 timestamps.phr = 0;
519
520 /* Request the HF clock */
521 nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
522 nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART);
523 while(!nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED));
524 nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
525
526 /* Start the RF driver process */
527 process_start(&nrf52840_ieee_rf_process, NULL);
528
529 /* Prepare the RX buffer */
530 rx_buf_clear();
531
532 /* Power on the radio */
533 power_on_and_configure();
534
535 /* Set up initial state of poll mode. This will configure interrupts. */
536 set_poll_mode(rf_config.poll_mode);
537
538 return RADIO_TX_OK;
539}
540/*---------------------------------------------------------------------------*/
541static int
542prepare(const void *payload, unsigned short payload_len)
543{
544 LOG_DBG("Prepare %u bytes\n", payload_len);
545
546 if(payload_len > MAX_PAYLOAD_LEN) {
547 LOG_ERR("Too long: %u bytes, max %u\n", payload_len, MAX_PAYLOAD_LEN);
548 return RADIO_TX_ERR;
549 }
550
551 /* Populate the PHR. Packet length, including the FCS */
552 tx_buf.phr = (uint8_t)payload_len + FCS_LEN;
553
554 /* Copy the payload over */
555 memcpy(tx_buf.mpdu, payload, payload_len);
556
557 return RADIO_TX_OK;
558}
559/*---------------------------------------------------------------------------*/
560static int
561transmit(unsigned short transmit_len)
562{
563 int i;
564
565 LOG_DBG("TX %u bytes + FCS, channel=%u\n", transmit_len, get_channel());
566
567 if(transmit_len > MAX_PAYLOAD_LEN) {
568 LOG_ERR("TX: too long (%u bytes)\n", transmit_len);
569 return RADIO_TX_ERR;
570 }
571
572 on();
573
574 if(rf_config.send_on_cca) {
575 if(channel_clear() == NRF52840_CCA_BUSY) {
576 LOG_DBG("TX: Busy\n");
577 return RADIO_TX_COLLISION;
578 }
579 }
580
581 nrf_radio_txpower_set(rf_config.txpower);
582
583 /* When we reach here we are in state RX. Send a STOP to drop to RXIDLE */
584 nrf_radio_task_trigger(NRF_RADIO_TASK_STOP);
585 while(nrf_radio_state_get() != NRF_RADIO_STATE_RXIDLE);
586
587 LOG_DBG("Transmit: %u bytes=000000", tx_buf.phr);
588 for(i = 0; i < tx_buf.phr - 2; i++) {
589 LOG_DBG_(" %02x", tx_buf.mpdu[i]);
590 }
591 LOG_DBG_("\n");
592
593 LOG_DBG("TX Start. State %u", nrf_radio_state_get());
594
595 /* Pointer to the TX buffer in PACKETPTR before task START */
596 nrf_radio_packetptr_set(&tx_buf);
597
598 /* Clear TX-related events */
599 nrf_radio_event_clear(NRF_RADIO_EVENT_END);
600 nrf_radio_event_clear(NRF_RADIO_EVENT_PHYEND);
601 nrf_radio_event_clear(NRF_RADIO_EVENT_TXREADY);
602
603 /* No need to sample RSSI during TX */
604 nrf_radio_shorts_disable(NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK);
605
606 /* Start the transmission */
607 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
608
609 /* Enable the SHORT between TXREADY and START before triggering TXRU */
610 nrf_radio_shorts_enable(NRF_RADIO_SHORT_TXREADY_START_MASK);
611 nrf_radio_task_trigger(NRF_RADIO_TASK_TXEN);
612
613 /*
614 * With fast rampup, the transition between TX and READY (TXRU duration)
615 * takes 40us. This means we will be in TX mode in less than 3 rtimer ticks
616 * (3x16=42 us). After this duration, we can busy wait for TX to finish.
617 */
618 RTIMER_BUSYWAIT(TXRU_DURATION_TIMER);
619
620 LOG_DBG_("--->%u\n", nrf_radio_state_get());
621
622 /* Wait for TX to complete */
623 while(nrf_radio_state_get() == NRF_RADIO_STATE_TX);
624
625 LOG_DBG("TX: Done\n");
626
627 /*
628 * Enter RX.
629 * TX has finished and we are in state TXIDLE. enter_rx will handle the
630 * transition from any state to RX, so we don't need to do anything further
631 * here.
632 */
633 enter_rx();
634
635 /* We are now in RX */
636 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
637
638 return RADIO_TX_OK;
639}
640/*---------------------------------------------------------------------------*/
641static int
642send(const void *payload, unsigned short payload_len)
643{
644 prepare(payload, payload_len);
645 return transmit(payload_len);
646}
647/*---------------------------------------------------------------------------*/
648static int
649read_frame(void *buf, unsigned short bufsize)
650{
651 int payload_len;
652
653 /* Clear all events */
654 rx_events_clear();
655
656 payload_len = rx_buf.phr - FCS_LEN;
657
658 if(phr_is_valid(rx_buf.phr) == false) {
659 LOG_DBG("Incorrect length: %d\n", payload_len);
660 rx_buf_clear();
661 enter_rx();
662 return 0;
663 }
664
665 memcpy(buf, rx_buf.mpdu, payload_len);
666 last_lqi = lqi_convert_to_802154_scale(rx_buf.mpdu[payload_len]);
667 last_rssi = -(nrf_radio_rssi_sample_get());
668
669 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi);
670 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, last_lqi);
671
672 /* Latch timestamp values for this most recently received frame */
673 timestamps.phr = rx_buf.phr;
674 timestamps.framestart = nrf_timer_cc_read(NRF_TIMER0, NRF_TIMER_CC_CHANNEL3);
675 timestamps.end = nrf_timer_cc_read(NRF_TIMER0, NRF_TIMER_CC_CHANNEL2);
676 timestamps.mpdu_duration = rx_buf.phr * BYTE_DURATION_RTIMER;
677
678 /*
679 * Timestamp in rtimer ticks of the reception of the SFD. The SFD was
680 * received 1 byte before the PHR, therefore all we need to do is subtract
681 * 2 symbols (2 rtimer ticks) from the PPI FRAMESTART timestamp.
682 */
683 timestamps.sfd = timestamps.framestart - BYTE_DURATION_RTIMER;
684
685 LOG_DBG("Read frame: len=%d, RSSI=%d, LQI=0x%02x\n", payload_len, last_rssi,
686 last_lqi);
687
688 rx_buf_clear();
689 enter_rx();
690
691 return payload_len;
692}
693/*---------------------------------------------------------------------------*/
694static int
695receiving_packet(void)
696{
697 /* If we are powered off, we are not receiving */
698 if(radio_is_powered() == false) {
699 return NRF52840_RECEIVING_NO;
700 }
701
702 /* If our state is not RX, we are not receiving */
703 if(nrf_radio_state_get() != NRF_RADIO_STATE_RX) {
704 return NRF52840_RECEIVING_NO;
705 }
706
707 if(rf_config.poll_mode) {
708 /* In poll mode, if the PHR is invalid we can return early */
709 if(phr_is_valid(rx_buf.phr) == false) {
710 return NRF52840_RECEIVING_NO;
711 }
712
713 /*
714 * If the PHR is valid and we are actually on, inspect EVENTS_CRCOK and
715 * _CRCERROR. If both of them are clear then reception is ongoing
716 */
717 if((nrf_radio_event_check(NRF_RADIO_EVENT_CRCOK) == false) &&
718 (nrf_radio_event_check(NRF_RADIO_EVENT_CRCERROR) == false)) {
719 return NRF52840_RECEIVING_YES;
720 }
721
722 return NRF52840_RECEIVING_NO;
723 }
724
725 /*
726 * In non-poll mode, we are receiving if the PHR is valid but the buffer
727 * does not contain a full packet.
728 */
729 if(phr_is_valid(rx_buf.phr) == true && rx_buf.full == false) {
730 return NRF52840_RECEIVING_YES;
731 }
732 return NRF52840_RECEIVING_NO;
733}
734/*---------------------------------------------------------------------------*/
735static int
736pending_packet(void)
737{
738 /*
739 * First check if we have received a PHR. When we enter RX the value of the
740 * PHR in our RX buffer is zero so we can return early.
741 */
742 if(phr_is_valid(rx_buf.phr) == false) {
743 return NRF52840_PENDING_NO;
744 }
745
746 /*
747 * We have received a valid PHR. Either we are in the process of receiving
748 * a frame, or we have fully received one. If we have received a frame then
749 * EVENTS_CRCOK should be asserted. In poll mode that's enough. In non-poll
750 * mode the interrupt handler will clear the event (else the interrupt would
751 * fire again), but we save the state in rx_buf.full.
752 */
753 if((nrf_radio_event_check(NRF_RADIO_EVENT_CRCOK) == true) ||
754 (rx_buf.full == true)) {
755 return NRF52840_PENDING_YES;
756 }
757
758 return NRF52840_PENDING_NO;
759}
760/*---------------------------------------------------------------------------*/
761static int
762off(void)
763{
764 /* Power down radio circuitry */
765 nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
766
767 /* Wait for completion */
768 while(nrf_radio_state_get() != NRF_RADIO_STATE_DISABLED);
769
770 /* Power down radio peripheral, erasing stored register values */
771 nrf_radio_power_set(false);
772
773 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
774
775 return NRF52840_COMMAND_OK;
776}
777/*---------------------------------------------------------------------------*/
778static radio_result_t
779get_value(radio_param_t param, radio_value_t *value)
780{
781 if(!value) {
783 }
784
785 switch(param) {
787 return RADIO_RESULT_OK;
789 *value = (radio_value_t)get_channel();
790 return RADIO_RESULT_OK;
792 *value = 0;
793 if(rf_config.poll_mode) {
794 *value |= RADIO_RX_MODE_POLL_MODE;
795 }
796 return RADIO_RESULT_OK;
798 *value = 0;
799 if(rf_config.send_on_cca) {
801 }
802 return RADIO_RESULT_OK;
804 *value = (radio_value_t)rf_config.txpower;
805 return RADIO_RESULT_OK;
807 *value = (radio_value_t)rf_config.cca_corr_threshold;
808 return RADIO_RESULT_OK;
809 case RADIO_PARAM_RSSI:
810 *value = (radio_value_t)rssi_read();
811 return RADIO_RESULT_OK;
813 *value = (radio_value_t)last_rssi;
814 return RADIO_RESULT_OK;
816 *value = (radio_value_t)last_lqi;
817 return RADIO_RESULT_OK;
819 *value = 11;
820 return RADIO_RESULT_OK;
822 *value = 26;
823 return RADIO_RESULT_OK;
825 *value = (radio_value_t)RADIO_TXPOWER_TXPOWER_Neg40dBm;
826 return RADIO_RESULT_OK;
828 *value = (radio_value_t)RADIO_TXPOWER_TXPOWER_Pos8dBm;
829 return RADIO_RESULT_OK;
831 *value = (radio_value_t)RADIO_PHY_OVERHEAD;
832 return RADIO_RESULT_OK;
834 *value = (radio_value_t)RADIO_BYTE_AIR_TIME;
835 return RADIO_RESULT_OK;
837 *value = (radio_value_t)RADIO_DELAY_BEFORE_TX;
838 return RADIO_RESULT_OK;
840 *value = (radio_value_t)RADIO_DELAY_BEFORE_RX;
841 return RADIO_RESULT_OK;
843 *value = (radio_value_t)RADIO_DELAY_BEFORE_DETECT;
844 return RADIO_RESULT_OK;
845 case RADIO_CONST_MAX_PAYLOAD_LEN:
846 *value = (radio_value_t)MAX_PAYLOAD_LEN;
847 return RADIO_RESULT_OK;
850 default:
852 }
853}
854/*---------------------------------------------------------------------------*/
855static radio_result_t
856set_value(radio_param_t param, radio_value_t value)
857{
858 switch(param) {
860 if(value == RADIO_POWER_MODE_ON) {
861 on();
862 return RADIO_RESULT_OK;
863 }
864 if(value == RADIO_POWER_MODE_OFF) {
865 off();
866 return RADIO_RESULT_OK;
867 }
870 if(value < NRF52840_CHANNEL_MIN ||
871 value > NRF52840_CHANNEL_MAX) {
873 }
874 rf_config.channel = value;
875
876 /* If we are powered on, apply immediately. */
877 if(radio_is_powered()) {
878 off();
879 set_channel(value);
880 on();
881 }
882 return RADIO_RESULT_OK;
884 if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
888 }
889
890 set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
891
892 return RADIO_RESULT_OK;
894 if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
896 }
897
898 rf_config.send_on_cca = (value & RADIO_TX_MODE_SEND_ON_CCA) != 0;
899 return RADIO_RESULT_OK;
901 rf_config.txpower = value;
902 /* If we are powered on, apply immediately. */
903 if(radio_is_powered()) {
904 nrf_radio_txpower_set(value);
905 }
906 return RADIO_RESULT_OK;
908 rf_config.cca_corr_threshold = value;
909 /* If we are powered on, apply immediately. */
910 if(radio_is_powered()) {
911 cca_reconfigure();
912 }
913 return RADIO_RESULT_OK;
914
918 default:
920 }
921}
922/*---------------------------------------------------------------------------*/
923static radio_result_t
924get_object(radio_param_t param, void *dest, size_t size)
925{
927 if(size != sizeof(rtimer_clock_t) || !dest) {
929 }
930 *(rtimer_clock_t *)dest = timestamps.sfd;
931 return RADIO_RESULT_OK;
932 }
933
934#if MAC_CONF_WITH_TSCH
935 if(param == RADIO_CONST_TSCH_TIMING) {
936 if(size != sizeof(uint16_t *) || !dest) {
938 }
939 /* Assigned value: a pointer to the TSCH timing in usec */
940 *(const uint16_t **)dest = tsch_timeslot_timing_us_10000;
941 return RADIO_RESULT_OK;
942 }
943#endif /* MAC_CONF_WITH_TSCH */
944
945 /* The radio does not support h/w frame filtering based on addresses */
947}
948/*---------------------------------------------------------------------------*/
949static radio_result_t
950set_object(radio_param_t param, const void *src, size_t size)
951{
952 /* The radio does not support h/w frame filtering based on addresses */
954}
955/*---------------------------------------------------------------------------*/
956const struct radio_driver nrf52840_ieee_driver = {
957 init,
958 prepare,
959 transmit,
960 send,
961 read_frame,
965 on,
966 off,
967 get_value,
968 set_value,
971};
972/*---------------------------------------------------------------------------*/
973PROCESS_THREAD(nrf52840_ieee_rf_process, ev, data)
974{
975 int len;
977
978 while(1) {
979 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
980
981 LOG_DBG("Polled\n");
982
983 if(pending_packet()) {
986 len = read_frame(packetbuf_dataptr(), PACKETBUF_SIZE);
987 if(len > 0) {
989 NETSTACK_MAC.input();
990 LOG_DBG("last frame (%u bytes) timestamps:\n", timestamps.phr);
991 LOG_DBG(" SFD=%lu (Derived)\n", timestamps.sfd);
992 LOG_DBG(" PHY=%lu (PPI)\n", timestamps.framestart);
993 LOG_DBG(" MPDU=%lu (Duration)\n", timestamps.mpdu_duration);
994 LOG_DBG(" END=%lu (PPI)\n", timestamps.end);
995 LOG_DBG(" Expected=%lu + %u + %lu = %lu\n", timestamps.sfd,
996 BYTE_DURATION_RTIMER, timestamps.mpdu_duration,
997 timestamps.sfd + BYTE_DURATION_RTIMER + timestamps.mpdu_duration);
998 }
999 }
1000 }
1001
1002 PROCESS_END();
1003}
1004/*---------------------------------------------------------------------------*/
1005void
1006RADIO_IRQHandler(void)
1007{
1008 if(!rf_config.poll_mode) {
1009 if(nrf_radio_event_check(NRF_RADIO_EVENT_CRCOK)) {
1010 nrf_radio_event_clear(NRF_RADIO_EVENT_CRCOK);
1011 rx_buf.full = true;
1012 process_poll(&nrf52840_ieee_rf_process);
1013 } else if(nrf_radio_event_check(NRF_RADIO_EVENT_CRCERROR)) {
1014 nrf_radio_event_clear(NRF_RADIO_EVENT_CRCERROR);
1015 rx_buf_clear();
1016 enter_rx();
1017 }
1018 }
1019}
1020/*---------------------------------------------------------------------------*/
1021/**
1022 * @}
1023 * @}
1024 * @}
1025 */
Header file for the energy estimation mechanism.
static uint8_t get_channel()
Get the current operating channel.
Definition: cc2538-rf.c:166
static void set_channel(uint8_t channel)
Set the current operating channel.
Definition: cc2538-rf.c:176
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1154
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:85
static void critical_exit(int_master_status_t status)
Exit a critical section and restore the master interrupt.
Definition: critical.h:81
static int_master_status_t critical_enter()
Enter a critical section.
Definition: critical.h:65
INT_MASTER_STATUS_DATATYPE int_master_status_t
Master interrupt state representation data type.
Definition: int-master.h:62
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
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
#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
#define RADIO_RX_MODE_ADDRESS_FILTER
Enable address-based frame filtering.
Definition: radio.h:451
#define RADIO_RX_MODE_POLL_MODE
Enable/disable/get the state of radio driver poll mode operation.
Definition: radio.h:461
#define RADIO_TX_MODE_SEND_ON_CCA
Radio TX mode control / retrieval.
Definition: radio.h:474
enum radio_result_e radio_result_t
Radio return values when setting or getting radio parameters.
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio.
Definition: radio.h:88
#define RADIO_RX_MODE_AUTOACK
Enable automatic transmission of ACK frames.
Definition: radio.h:456
@ RADIO_RESULT_NOT_SUPPORTED
The parameter is not supported.
Definition: radio.h:481
@ RADIO_RESULT_INVALID_VALUE
The value argument was incorrect.
Definition: radio.h:482
@ RADIO_RESULT_OK
The parameter was set/read successfully.
Definition: radio.h:480
@ RADIO_PARAM_POWER_MODE
When getting the value of this parameter, the radio driver should indicate whether the radio is on or...
Definition: radio.h:119
@ RADIO_CONST_PHY_OVERHEAD
The physical layer header (PHR) + MAC layer footer (MFR) overhead in bytes.
Definition: radio.h:338
@ RADIO_PARAM_RSSI
Received signal strength indicator in dBm.
Definition: radio.h:218
@ RADIO_PARAM_LAST_PACKET_TIMESTAMP
Last packet timestamp, of type rtimer_clock_t.
Definition: radio.h:286
@ RADIO_PARAM_LAST_RSSI
The RSSI value of the last received packet.
Definition: radio.h:226
@ RADIO_CONST_BYTE_AIR_TIME
The air time of one byte in usec, e.g.
Definition: radio.h:343
@ RADIO_PARAM_RX_MODE
Radio receiver mode determines if the radio has address filter (RADIO_RX_MODE_ADDRESS_FILTER) and aut...
Definition: radio.h:173
@ RADIO_PARAM_CHANNEL
Channel used for radio communication.
Definition: radio.h:134
@ RADIO_PARAM_SHR_SEARCH
For enabling and disabling the SHR search.
Definition: radio.h:304
@ RADIO_PARAM_LAST_LINK_QUALITY
Link quality indicator of the last received packet.
Definition: radio.h:244
@ RADIO_CONST_DELAY_BEFORE_RX
The delay in usec between turning on the radio and it being actually listening (able to hear a preamb...
Definition: radio.h:355
@ RADIO_PARAM_TXPOWER
Transmission power in dBm.
Definition: radio.h:192
@ RADIO_CONST_DELAY_BEFORE_TX
The delay in usec between a call to the radio API's transmit function and the end of SFD transmission...
Definition: radio.h:349
@ RADIO_CONST_CHANNEL_MAX
The highest radio channel number.
Definition: radio.h:316
@ RADIO_PARAM_PAN_ID
The personal area network identifier (PAN ID), which is used by the h/w frame filtering functionality...
Definition: radio.h:150
@ RADIO_PARAM_CCA_THRESHOLD
Clear channel assessment threshold in dBm.
Definition: radio.h:205
@ RADIO_CONST_TXPOWER_MIN
The minimum transmission power in dBm.
Definition: radio.h:321
@ RADIO_CONST_CHANNEL_MIN
The lowest radio channel number.
Definition: radio.h:311
@ RADIO_CONST_TXPOWER_MAX
The maximum transmission power in dBm.
Definition: radio.h:326
@ RADIO_CONST_DELAY_BEFORE_DETECT
The delay in usec between the end of SFD reception for an incoming frame and the radio API starting t...
Definition: radio.h:361
@ RADIO_PARAM_16BIT_ADDR
The short address (16 bits) for the radio, which is used by the h/w filter.
Definition: radio.h:166
@ RADIO_PARAM_TX_MODE
Radio transmission mode determines if the radio has send on CCA (RADIO_TX_MODE_SEND_ON_CCA) enabled o...
Definition: radio.h:180
@ RADIO_POWER_MODE_OFF
Radio powered off and in the lowest possible power consumption state.
Definition: radio.h:395
@ RADIO_POWER_MODE_ON
Radio powered on and able to receive frames.
Definition: radio.h:400
@ RADIO_TX_COLLISION
TX failed due to a collision.
Definition: radio.h:511
@ RADIO_TX_ERR
An error occurred during transmission.
Definition: radio.h:506
@ RADIO_TX_OK
TX was successful and where an ACK was requested one was received.
Definition: radio.h:498
#define RTIMER_BUSYWAIT(duration)
Busy-wait for a fixed duration.
Definition: rtimer.h:218
const tsch_timeslot_timing_usec tsch_timeslot_timing_us_10000
TSCH timing attributes and description.
Header file for the logging system.
#define IEEE802154_DEFAULT_CHANNEL
The default channel for IEEE 802.15.4 networks.
Definition: mac.h:52
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
Header file for the radio API.
void(* input)(void)
Callback for getting notified of incoming packet.
Definition: mac.h:72
The structure of a Contiki-NG radio device driver.
Definition: radio.h:534
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:770
int(* prepare)(const void *payload, unsigned short payload_len)
Prepare the radio with a packet to be sent.
Definition: radio.h:580
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:756
int(* off)(void)
Turn the radio off.
Definition: radio.h:729
int(* init)(void)
Initialise the radio hardware.
Definition: radio.h:555
int(* send)(const void *payload, unsigned short payload_len)
Prepare & transmit a packet.
Definition: radio.h:631
int(* receiving_packet)(void)
Check if the radio driver is currently receiving a packet.
Definition: radio.h:684
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:787
int(* on)(void)
Turn the radio on.
Definition: radio.h:711
int(* transmit)(unsigned short transmit_len)
Send the packet that has previously been prepared.
Definition: radio.h:619
int(* pending_packet)(void)
Check if a packet has been received and is available in the radio driver's buffers.
Definition: radio.h:697
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:741
int(* channel_clear)(void)
Perform a Clear-Channel Assessment (CCA) to find out if there is a packet in the air or not.
Definition: radio.h:672
Main API declarations for TSCH.