Contiki-NG
Loading...
Searching...
No Matches
nrf-ieee-driver-nrf53.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2026, RISE Research Institutes of Sweden AB.
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 * \file
33 * IEEE 802.15.4 radio driver for the nRF5340 network core using
34 * Nordic's nrf_802154 library. Wraps the asynchronous nrf_802154 API
35 * into Contiki-NG's synchronous radio_driver interface and exposes it
36 * as nrf_ieee_driver (replacing the raw nrf-ieee-driver-arch.c on this
37 * core). Adapted from the nRF54L15 port.
38 *
39 * \author
40 * Nicolas Tsiftes <nicolas.tsiftes@ri.se>
41 */
42/*---------------------------------------------------------------------------*/
43#include "contiki.h"
44#include "dev/radio.h"
45#include "net/netstack.h"
46#include "net/packetbuf.h"
47#include "net/linkaddr.h"
49#include "sys/energest.h"
50#include "nrf_802154.h"
51#include "nrf_802154_config.h"
52#include "nrf.h"
53
54#include <string.h>
55#include <stdbool.h>
56/*---------------------------------------------------------------------------*/
57#include "sys/log.h"
58#ifndef LOG_CONF_LEVEL_RADIO
59#define LOG_CONF_LEVEL_RADIO LOG_LEVEL_INFO
60#endif
61#define LOG_MODULE "nrf53-radio"
62#define LOG_LEVEL LOG_CONF_LEVEL_RADIO
63/*---------------------------------------------------------------------------*/
64#define MAX_PAYLOAD_LEN 125 /* 127 - FCS(2) */
65#define FRAME_ACK_REQUEST_BIT 0x20
66
67/*
68 * Seed the radio's channel from the Contiki build configuration
69 * (IEEE802154_CONF_DEFAULT_CHANNEL, default 26), mirroring how the PAN ID is
70 * taken from IEEE802154_PANID below. The app core does not push the channel
71 * over IPC, so the net core must default to the configured channel; otherwise
72 * a non-default IEEE802154_CONF_DEFAULT_CHANNEL silently channel-mismatches
73 * the net-core radio against the app core and its peers.
74 */
75#define DEFAULT_CHANNEL IEEE802154_DEFAULT_CHANNEL
76#define DEFAULT_TX_POWER 0 /* dBm */
77
78/* Timeouts are expressed against nrf_802154_time_get() (microseconds), which
79 * is driven by the SL lptimer platform backend (RTC1 on this core). */
80#define TX_DONE_TIMEOUT_US 250000ULL
81#define TX_ABORT_TIMEOUT_US 10000ULL
82#define CCA_DONE_TIMEOUT_US 50000ULL
83/*---------------------------------------------------------------------------*/
84/* TX buffer in nrf_802154 raw format: [PHR (length incl. FCS)] [PSDU ...]. */
85static uint8_t tx_buf[1 + MAX_PAYLOAD_LEN + 2];
86
87/*
88 * Software RX ring. The head/tail indices are free-running uint8_t values,
89 * so the ring size must be a power of two for the index mapping to stay
90 * consistent across their 256-wrap. It must also be at least as large as
91 * the library's RX buffer pool: the library can never have more frames
92 * outstanding than it has buffers, so enqueue can then never overwrite an
93 * unread slot.
94 */
95#define RX_BUF_COUNT 32
96#define RX_BUF_MASK (RX_BUF_COUNT - 1)
97#if (RX_BUF_COUNT & RX_BUF_MASK) != 0
98#error RX_BUF_COUNT must be a power of two
99#endif
100#if RX_BUF_COUNT < NRF_802154_RX_BUFFERS
101#error RX_BUF_COUNT must be >= NRF_802154_RX_BUFFERS
102#endif
103static uint8_t *rx_bufs[RX_BUF_COUNT];
104static int8_t rx_rssi[RX_BUF_COUNT];
105static uint8_t rx_lqi[RX_BUF_COUNT];
106static volatile uint8_t rx_head;
107static volatile uint8_t rx_tail;
108
109static volatile bool tx_done;
110static volatile bool tx_success;
111static volatile nrf_802154_tx_error_t tx_error;
112
113static volatile bool cca_done;
114static volatile bool cca_free;
115
116static volatile uint32_t rx_fail_count;
117static volatile uint32_t rx_drop_count;
118static volatile uint32_t tx_fail_count;
119
120static uint8_t current_channel = DEFAULT_CHANNEL;
121static int8_t current_tx_power = DEFAULT_TX_POWER;
122static bool radio_is_on;
123
124/* Reflects the hardware configuration applied in init(): frame filtering
125 * enabled, auto-ACK enabled. Poll mode is not supported (RX is
126 * interrupt-driven), so it is never present in rx_mode. */
127static radio_value_t rx_mode =
129static radio_value_t tx_mode;
130/*---------------------------------------------------------------------------*/
131PROCESS(nrf53_radio_process, "nRF53 radio driver");
132/*---------------------------------------------------------------------------*/
133static const char *
134tx_error_name(nrf_802154_tx_error_t error)
135{
136 switch(error) {
137 case NRF_802154_TX_ERROR_NONE:
138 return "none";
139 case NRF_802154_TX_ERROR_BUSY_CHANNEL:
140 return "busy_channel";
141 case NRF_802154_TX_ERROR_INVALID_ACK:
142 return "invalid_ack";
143 case NRF_802154_TX_ERROR_NO_MEM:
144 return "no_mem";
145 case NRF_802154_TX_ERROR_TIMESLOT_ENDED:
146 return "timeslot_ended";
147 case NRF_802154_TX_ERROR_NO_ACK:
148 return "no_ack";
149 case NRF_802154_TX_ERROR_ABORTED:
150 return "aborted";
151 case NRF_802154_TX_ERROR_TIMESLOT_DENIED:
152 return "timeslot_denied";
153 default:
154 return "unknown";
155 }
156}
157/*---------------------------------------------------------------------------*/
158static bool
159wait_for_flag(volatile bool *flag, uint64_t timeout_us)
160{
161 uint64_t deadline = nrf_802154_time_get() + timeout_us;
162
163 while(!*flag && nrf_802154_time_get() < deadline) {
164 __WFE();
165 }
166
167 return *flag;
168}
169/*---------------------------------------------------------------------------*/
170static void
171recover_to_receive_state(void)
172{
173 if(!radio_is_on) {
174 return;
175 }
176
177 /*
178 * Request sleep to abort any operation still in progress. An aborted
179 * transmission reports through nrf_802154_transmit_failed(), which sets
180 * tx_done; waiting for it here keeps a late TX completion callback from
181 * leaking into the next transmit()'s freshly cleared flags. When no TX is
182 * pending (e.g. the CCA timeout path), tx_done is still set from the last
183 * completed transmission and the wait returns immediately.
184 */
185 nrf_802154_sleep();
186 (void)wait_for_flag(&tx_done, TX_ABORT_TIMEOUT_US);
187
188 if(!nrf_802154_receive()) {
189 LOG_WARN("Failed to restore receive state\n");
190 }
191}
192/*---------------------------------------------------------------------------*/
193static int
194init(void)
195{
196 uint8_t pan_id[2];
197 uint8_t short_addr[2];
198 uint8_t ext_addr[8];
199 int i;
200
201 LOG_INFO("Initializing nrf_802154 radio driver\n");
202
203 nrf_802154_init();
204
205 nrf_802154_channel_set(current_channel);
206 nrf_802154_tx_power_set(current_tx_power);
207
208 nrf_802154_auto_ack_set(true);
209 nrf_802154_rx_on_when_idle_set(true);
210
211 /*
212 * Seed the PAN ID and addresses from this (net) core's configuration and
213 * FICR-derived link-layer address as a fallback. The application core's
214 * link-layer address differs (each core derives it from its own FICR
215 * DEVICEID), so the app core pushes its authoritative addresses over IPC
216 * right after radio init (see ipc_radio_init() in nrf-ipc-radio.c); those
217 * arrive through set_object() below and override this seeding. Hardware
218 * frame filtering and auto-ACK operate on whatever is programmed last.
219 */
220 pan_id[0] = (uint8_t)(IEEE802154_PANID & 0xFF);
221 pan_id[1] = (uint8_t)(IEEE802154_PANID >> 8);
222 nrf_802154_pan_id_set(pan_id);
223
224 short_addr[0] = linkaddr_node_addr.u8[LINKADDR_SIZE - 2];
225 short_addr[1] = linkaddr_node_addr.u8[LINKADDR_SIZE - 1];
226 nrf_802154_short_address_set(short_addr);
227
228 /* Extended address is the link-layer address in little-endian order. */
229 for(i = 0; i < 8; i++) {
230 ext_addr[i] = (i < LINKADDR_SIZE) ?
231 linkaddr_node_addr.u8[LINKADDR_SIZE - 1 - i] : 0;
232 }
233 nrf_802154_extended_address_set(ext_addr);
234
235 rx_head = 0;
236 rx_tail = 0;
237 radio_is_on = false;
238 /* No transmission is in flight, so the TX completion state is settled;
239 * recover_to_receive_state() relies on this. */
240 tx_done = true;
241
242 process_start(&nrf53_radio_process, NULL);
243
244 LOG_INFO("Radio initialized, channel %u, PAN 0x%04x\n",
245 current_channel, IEEE802154_PANID);
246
247 /*
248 * On the net core this driver is consumed only via the IPC radio service,
249 * which (like the raw nrf-ieee-driver-arch.c) treats RADIO_TX_OK (0) as a
250 * successful init. Match that convention.
251 */
252 return RADIO_TX_OK;
253}
254/*---------------------------------------------------------------------------*/
255static int
256on(void)
257{
258 if(!radio_is_on) {
259 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
260 if(!nrf_802154_receive()) {
261 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
262 LOG_WARN("Failed to enter receive state\n");
263 return 0;
264 }
265 radio_is_on = true;
266 }
267 return 1;
268}
269/*---------------------------------------------------------------------------*/
270static int
271off(void)
272{
273 if(radio_is_on) {
274 nrf_802154_sleep();
275 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
276 radio_is_on = false;
277 }
278 return 1;
279}
280/*---------------------------------------------------------------------------*/
281static int
282prepare(const void *payload, unsigned short payload_len)
283{
284 if(payload_len > MAX_PAYLOAD_LEN) {
285 LOG_WARN("TX payload too long: %u\n", payload_len);
286 return 1;
287 }
288
289 tx_buf[0] = payload_len + 2; /* PHR = PSDU + FCS(2). */
290 memcpy(&tx_buf[1], payload, payload_len);
291
292 return 0;
293}
294/*---------------------------------------------------------------------------*/
295static int
296transmit(unsigned short transmit_len)
297{
298 nrf_802154_transmit_metadata_t metadata = {
299 .frame_props = NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT,
300 .cca = (tx_mode & RADIO_TX_MODE_SEND_ON_CCA) != 0,
301 .tx_power = { .use_metadata_value = false },
302 .tx_channel = { .use_metadata_value = false },
303 };
304 nrf_802154_tx_error_t tx_err;
305
306 /* The frame to send was stored in tx_buf by prepare(); its length is the
307 * PHR (tx_buf[0] = PSDU + FCS). Validate the caller's length against the
308 * prepared PHR rather than trusting it: transmit() is a separate radio API
309 * entry point, and callers such as CSMA invoke it without checking that the
310 * preceding prepare() succeeded. Without this check, a skipped or failed
311 * prepare() would make transmit() send the stale contents of tx_buf. */
312 if(transmit_len > MAX_PAYLOAD_LEN || transmit_len + 2 != tx_buf[0]) {
313 LOG_WARN("TX length mismatch: %u vs PHR %u\n", transmit_len, tx_buf[0]);
314 return RADIO_TX_ERR;
315 }
316
317 if(!radio_is_on) {
318 on();
319 }
320
321 tx_done = false;
322 tx_success = false;
323 tx_error = NRF_802154_TX_ERROR_NONE;
324
325 ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
326
327 tx_err = nrf_802154_transmit_raw(tx_buf, &metadata);
328
329 if(tx_err != NRF_802154_TX_ERROR_NONE) {
330 LOG_WARN("TX request rejected: %s (%u)\n", tx_error_name(tx_err), tx_err);
331 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
332
333 if(tx_err == NRF_802154_TX_ERROR_BUSY_CHANNEL) {
334 recover_to_receive_state();
335 return RADIO_TX_COLLISION;
336 }
337 if(tx_err == NRF_802154_TX_ERROR_INVALID_ACK ||
338 tx_err == NRF_802154_TX_ERROR_NO_ACK) {
339 return RADIO_TX_NOACK;
340 }
341 return RADIO_TX_ERR;
342 }
343
344 if(!wait_for_flag(&tx_done, TX_DONE_TIMEOUT_US)) {
345 LOG_WARN("TX timeout\n");
346 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
347 /* Abort the stuck transmission and let the completion flags settle
348 * before returning, so a late TX callback cannot corrupt the result of
349 * the next transmit(). */
350 recover_to_receive_state();
351 return RADIO_TX_ERR;
352 }
353
354 ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN);
355
356 if(tx_success) {
357 return RADIO_TX_OK;
358 }
359 if(tx_error == NRF_802154_TX_ERROR_NO_ACK ||
360 tx_error == NRF_802154_TX_ERROR_INVALID_ACK) {
361 return RADIO_TX_NOACK;
362 }
363 if(tx_error == NRF_802154_TX_ERROR_BUSY_CHANNEL) {
364 return RADIO_TX_COLLISION;
365 }
366
367 LOG_WARN("TX failed: %s (%u)\n", tx_error_name(tx_error), tx_error);
368 return RADIO_TX_ERR;
369}
370/*---------------------------------------------------------------------------*/
371static int
372send(const void *payload, unsigned short payload_len)
373{
374 if(prepare(payload, payload_len) != 0) {
375 /* Transmitting anyway would send the stale contents of tx_buf. */
376 return RADIO_TX_ERR;
377 }
378 return transmit(payload_len);
379}
380/*---------------------------------------------------------------------------*/
381static int
382radio_read(void *buf, unsigned short buf_len)
383{
384 uint8_t idx;
385 uint8_t *p_data;
386 uint8_t payload_len;
387
388 if(rx_tail == rx_head) {
389 return 0;
390 }
391
392 idx = rx_tail & RX_BUF_MASK;
393 p_data = rx_bufs[idx];
394
395 if(p_data == NULL) {
396 rx_tail++;
397 return 0;
398 }
399
400 if(p_data[0] < 2) {
401 /* Malformed PHR; cannot happen for CRC-checked frames, but guard the
402 * unsigned underflow below. */
403 nrf_802154_buffer_free_raw(p_data);
404 rx_bufs[idx] = NULL;
405 rx_tail++;
406 return 0;
407 }
408
409 /* p_data[0] = PHR (length incl. FCS); payload = PHR - FCS(2). */
410 payload_len = p_data[0] - 2;
411 if(payload_len > buf_len) {
412 payload_len = buf_len;
413 }
414
415 memcpy(buf, &p_data[1], payload_len);
416
417 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rx_rssi[idx]);
418 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, rx_lqi[idx]);
419
420 nrf_802154_buffer_free_raw(p_data);
421 rx_bufs[idx] = NULL;
422 rx_tail++;
423
424 return payload_len;
425}
426/*---------------------------------------------------------------------------*/
427static int
428channel_clear(void)
429{
430 if(!radio_is_on) {
431 on();
432 }
433
434 cca_done = false;
435 cca_free = false;
436
437 if(!nrf_802154_cca()) {
438 LOG_WARN("CCA could not start\n");
439 return 0;
440 }
441
442 if(!wait_for_flag(&cca_done, CCA_DONE_TIMEOUT_US)) {
443 LOG_WARN("CCA timeout\n");
444 recover_to_receive_state();
445 return 0;
446 }
447
448 return cca_free ? 1 : 0;
449}
450/*---------------------------------------------------------------------------*/
451static int
452receiving_packet(void)
453{
454 return 0;
455}
456/*---------------------------------------------------------------------------*/
457static int
458pending_packet(void)
459{
460 return (rx_head != rx_tail) ? 1 : 0;
461}
462/*---------------------------------------------------------------------------*/
463static radio_result_t
464get_value(radio_param_t param, radio_value_t *value)
465{
466 switch(param) {
469 return RADIO_RESULT_OK;
471 *value = (radio_value_t)nrf_802154_channel_get();
472 return RADIO_RESULT_OK;
474 *value = rx_mode;
475 return RADIO_RESULT_OK;
477 *value = tx_mode;
478 return RADIO_RESULT_OK;
480 *value = (radio_value_t)nrf_802154_tx_power_get();
481 return RADIO_RESULT_OK;
482 case RADIO_PARAM_RSSI:
483 *value = (radio_value_t)nrf_802154_rssi_last_get();
484 return RADIO_RESULT_OK;
486 *value = 11;
487 return RADIO_RESULT_OK;
489 *value = 26;
490 return RADIO_RESULT_OK;
492 /* nRF5340 radio output power range is -40..+3 dBm. */
493 *value = -40;
494 return RADIO_RESULT_OK;
496 *value = 3;
497 return RADIO_RESULT_OK;
498 case RADIO_CONST_MAX_PAYLOAD_LEN:
499 *value = MAX_PAYLOAD_LEN;
500 return RADIO_RESULT_OK;
501 default:
503 }
504}
505/*---------------------------------------------------------------------------*/
506static radio_result_t
507set_value(radio_param_t param, radio_value_t value)
508{
509 switch(param) {
512 on();
513 } else {
514 off();
515 }
516 return RADIO_RESULT_OK;
518 if(value < 11 || value > 26) {
520 }
521 current_channel = (uint8_t)value;
522 nrf_802154_channel_set(current_channel);
523 return RADIO_RESULT_OK;
527 }
528 current_tx_power = (int8_t)value;
529 nrf_802154_tx_power_set(current_tx_power);
530 return RADIO_RESULT_OK;
533 RADIO_RX_MODE_AUTOACK)) != 0) {
534 /* Poll mode is not supported: reception is interrupt-driven and
535 * frames are forwarded to the app core by the IPC MAC. */
537 }
538 nrf_802154_promiscuous_set((value & RADIO_RX_MODE_ADDRESS_FILTER) == 0);
539 nrf_802154_auto_ack_set((value & RADIO_RX_MODE_AUTOACK) != 0);
540 rx_mode = value;
541 return RADIO_RESULT_OK;
545 }
546 tx_mode = value;
547 return RADIO_RESULT_OK;
548 default:
550 }
551}
552/*---------------------------------------------------------------------------*/
553static radio_result_t
554get_object(radio_param_t param, void *dest, size_t size)
555{
556 (void)param;
557 (void)dest;
558 (void)size;
560}
561/*---------------------------------------------------------------------------*/
562static radio_result_t
563set_object(radio_param_t param, const void *src, size_t size)
564{
565 uint8_t ext_addr[8];
566 const uint8_t *addr;
567 int i;
568
569 switch(param) {
571 if(size != 8) {
573 }
574 /* nrf_802154 wants the extended address in little-endian order. */
575 addr = (const uint8_t *)src;
576 for(i = 0; i < 8; i++) {
577 ext_addr[i] = addr[7 - i];
578 }
579 nrf_802154_extended_address_set(ext_addr);
580 return RADIO_RESULT_OK;
582 if(size != 2) {
584 }
585 nrf_802154_pan_id_set((const uint8_t *)src);
586 return RADIO_RESULT_OK;
588 if(size != 2) {
590 }
591 nrf_802154_short_address_set((const uint8_t *)src);
592 return RADIO_RESULT_OK;
593 default:
595 }
596}
597/*---------------------------------------------------------------------------*/
598/* nrf_802154 callbacks (invoked from ISR context). */
599void
600nrf_802154_received_timestamp_raw(uint8_t *p_data, int8_t power,
601 uint8_t lqi, uint64_t time)
602{
603 uint8_t idx;
604
605 (void)time;
606
607 if(((uint8_t)(rx_head - rx_tail)) >= RX_BUF_COUNT) {
608 /*
609 * Ring full -- drop the incoming frame. Only the consumer
610 * (radio_read(), process context) may advance rx_tail or free queued
611 * buffers; freeing the oldest entry from this ISR would race a read in
612 * progress. Unreachable as long as RX_BUF_COUNT >=
613 * NRF_802154_RX_BUFFERS, since the library cannot have more frames
614 * outstanding than its buffer pool.
615 */
616 nrf_802154_buffer_free_raw(p_data);
617 rx_drop_count++;
618 process_poll(&nrf53_radio_process);
619 return;
620 }
621
622 idx = rx_head & RX_BUF_MASK;
623 rx_bufs[idx] = p_data;
624 rx_rssi[idx] = power;
625 rx_lqi[idx] = lqi;
626 rx_head++;
627
628 process_poll(&nrf53_radio_process);
629}
630/*---------------------------------------------------------------------------*/
631void
632nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id)
633{
634 (void)error;
635 (void)id;
636 rx_fail_count++;
637 process_poll(&nrf53_radio_process);
638}
639/*---------------------------------------------------------------------------*/
640void
641nrf_802154_transmitted_raw(uint8_t *p_frame,
642 const nrf_802154_transmit_done_metadata_t *p_metadata)
643{
644 bool ack_requested = false;
645
646 if(p_frame != NULL) {
647 ack_requested = (p_frame[1] & FRAME_ACK_REQUEST_BIT) != 0;
648 }
649
650 if(p_metadata->data.transmitted.p_ack != NULL) {
651 nrf_802154_buffer_free_raw(p_metadata->data.transmitted.p_ack);
652 tx_success = true;
653 } else if(ack_requested) {
654 tx_error = NRF_802154_TX_ERROR_NO_ACK;
655 tx_success = false;
656 } else {
657 tx_success = true;
658 }
659
660 tx_done = true;
661 __SEV();
662}
663/*---------------------------------------------------------------------------*/
664void
665nrf_802154_transmit_failed(uint8_t *p_frame,
666 nrf_802154_tx_error_t error,
667 const nrf_802154_transmit_done_metadata_t *p_metadata)
668{
669 (void)p_frame;
670 (void)p_metadata;
671 /*
672 * NO_ACK and BUSY_CHANNEL are expected link conditions, not driver faults:
673 * transmit() returns them as RADIO_TX_NOACK / RADIO_TX_COLLISION and the
674 * MAC layer handles retransmission. Only count the genuinely abnormal
675 * errors here so the aggregate "TX failed" warning stays meaningful.
676 */
677 if(error != NRF_802154_TX_ERROR_NO_ACK &&
678 error != NRF_802154_TX_ERROR_BUSY_CHANNEL) {
679 tx_fail_count++;
680 }
681 tx_error = error;
682 tx_success = false;
683 tx_done = true;
684 __SEV();
685}
686/*---------------------------------------------------------------------------*/
687void
688nrf_802154_cca_done(bool channel_free)
689{
690 cca_free = channel_free;
691 cca_done = true;
692 __SEV();
693}
694/*---------------------------------------------------------------------------*/
695void
696nrf_802154_cca_failed(nrf_802154_cca_error_t error)
697{
698 (void)error;
699 cca_free = false;
700 cca_done = true;
701 __SEV();
702}
703/*---------------------------------------------------------------------------*/
704void
705nrf_802154_energy_detected(const nrf_802154_energy_detected_t *p_result)
706{
707 (void)p_result;
708}
709/*---------------------------------------------------------------------------*/
710void
711nrf_802154_energy_detection_failed(nrf_802154_ed_error_t error)
712{
713 (void)error;
714}
715/*---------------------------------------------------------------------------*/
716PROCESS_THREAD(nrf53_radio_process, ev, data)
717{
719
720 while(1) {
721 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
722
723 if(rx_fail_count > 0) {
724 if(rx_fail_count > 16) {
725 LOG_WARN("RX failed %" PRIu32 " times\n", rx_fail_count);
726 }
727 rx_fail_count = 0;
728 }
729 if(rx_drop_count > 0) {
730 LOG_WARN("RX ring full, dropped %" PRIu32 " frames\n", rx_drop_count);
731 rx_drop_count = 0;
732 }
733 if(tx_fail_count > 0) {
734 LOG_WARN("TX failed %" PRIu32 " times\n", tx_fail_count);
735 tx_fail_count = 0;
736 }
737
738 while(pending_packet()) {
739 int len;
741 len = radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
742 if(len > 0) {
744 NETSTACK_MAC.input();
745 }
746 }
747 }
748
749 PROCESS_END();
750}
751/*---------------------------------------------------------------------------*/
752const struct radio_driver nrf_ieee_driver = {
753 init,
754 prepare,
755 transmit,
756 send,
757 radio_read,
758 channel_clear,
759 receiving_packet,
760 pending_packet,
761 on,
762 off,
763 get_value,
764 set_value,
767};
768/*---------------------------------------------------------------------------*/
Header file for the energy estimation mechanism.
802.15.4 frame creation and parsing functions
static int transmit(unsigned short transmit_len)
Definition cc2538-rf.c:708
static int off(void)
Definition cc2538-rf.c:533
static radio_result_t get_object(radio_param_t param, void *dest, size_t size)
Definition cc2538-rf.c:1069
static int prepare(const void *payload, unsigned short payload_len)
Definition cc2538-rf.c:648
static radio_result_t set_object(radio_param_t param, const void *src, size_t size)
Definition cc2538-rf.c:1110
static int on(void)
Definition cc2538-rf.c:517
static int init(void)
Definition cc2538-rf.c:556
static int value(int type)
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Definition linkaddr.c:48
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:309
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition process.h:122
#define PROCESS_END()
Define the end of a process.
Definition process.h:133
void process_start(struct process *p, process_data_t data)
Start a process.
Definition process.c:121
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition process.h:275
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition process.h:180
void process_poll(struct process *p)
Request a process to be polled.
Definition process.c:366
#define RADIO_RX_MODE_ADDRESS_FILTER
Enable address-based frame filtering.
Definition radio.h:451
#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_PARAM_RSSI
Received signal strength indicator in dBm.
Definition radio.h:218
@ 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_TXPOWER
Transmission power in dBm.
Definition radio.h:192
@ RADIO_PARAM_64BIT_ADDR
Long (64 bits) address for the radio, which is used by the address filter.
Definition radio.h:263
@ 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_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_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_NOACK
A unicast frame was sent OK but an ACK was not received.
Definition radio.h:516
@ 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
Header file for the link-layer address representation.
Header file for the logging system.
Include file for the Contiki low-layer network stack (NETSTACK).
Header file for the Packet buffer (packetbuf) management.
Header file for the radio API.
The structure of a Contiki-NG radio device driver.
Definition radio.h:534
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition uip-nd6.c:107