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