Contiki-NG
Loading...
Searching...
No Matches
nrf-ipc-radio.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 * \addtogroup nrf-ipc
33 * @{
34 *
35 * \file
36 * IPC radio driver for the nRF5340 application core.
37 *
38 * This driver implements the Contiki-NG radio API by forwarding
39 * all radio operations over IPC to the network core, which runs
40 * the actual 802.15.4 radio hardware.
41 *
42 * \author
43 * Nicolas Tsiftes <nicolas.tsiftes@ri.se>
44 */
45/*---------------------------------------------------------------------------*/
46#include "contiki.h"
47#include "dev/radio.h"
48#include "net/netstack.h"
49#include "net/packetbuf.h"
50#include "nrf-ipc.h"
51#include "nrf.h"
52#include "nrfx.h"
53#include <inttypes.h>
54#include <string.h>
55#ifdef TRUSTZONE_SECURE
56#include "trustzone/tz-radio.h"
57#endif
58/*---------------------------------------------------------------------------*/
59/* Only compile on the nRF5340 application core. */
60#ifdef NRF5340_XXAA_APPLICATION
61/*---------------------------------------------------------------------------*/
62#include "hal/nrf_gpio.h"
63#include "hal/nrf_reset.h"
64#include "hal/nrf_spu.h"
65/*---------------------------------------------------------------------------*/
66#include "sys/log.h"
67#define LOG_MODULE "IPC Radio"
68#define LOG_LEVEL LOG_LEVEL_INFO
69/*---------------------------------------------------------------------------*/
70#define NET_CORE_INIT_TIMEOUT_MS 1000
71/*---------------------------------------------------------------------------*/
72static volatile struct nrf_ipc_shared_mem *shm = NRF_IPC_SHARED_MEM;
73/*---------------------------------------------------------------------------*/
74/* Local buffer for the last received frame. */
75static uint8_t rx_frame_buf[NRF_IPC_MAX_FRAME_LEN];
76static int rx_frame_len;
77static bool rx_frame_pending;
78/*---------------------------------------------------------------------------*/
79/* TX buffer. */
80static uint8_t tx_frame_buf[NRF_IPC_MAX_FRAME_LEN];
81/*---------------------------------------------------------------------------*/
82PROCESS(ipc_radio_process, "IPC Radio");
83/*---------------------------------------------------------------------------*/
84/**
85 * Send a command to the net core and wait for the response.
86 *
87 * The caller writes the command into shared memory, signals the
88 * net core via the IPC peripheral, and busy-waits for the response.
89 * A timeout prevents the app core from hanging if the net core
90 * becomes unresponsive.
91 *
92 * \param type The command type (one of \ref nrf_ipc_cmd_type).
93 * \param data Pointer to command payload, or NULL.
94 * \param len Length of command payload in bytes.
95 * \return The result code from the net core (rsp.data[0]),
96 * or -1 on timeout.
97 */
98static uint8_t cmd_seq_counter;
99/*---------------------------------------------------------------------------*/
100static int
101send_command(uint8_t type, const void *data, uint8_t len)
102{
103 clock_time_t start;
104 uint8_t seq;
105
106 if(len > NRF_IPC_MAX_DATA_LEN) {
107 LOG_ERR("Command payload too long: %u\n", len);
108 return -1;
109 }
110
111 /* Assign a sequence number so we can detect stale responses. */
112 seq = ++cmd_seq_counter;
113
114 /* Write the command. */
115 shm->cmd.type = type;
116 shm->cmd.len = len;
117 if(data != NULL && len > 0) {
118 memcpy((void *)shm->cmd.data, data, len);
119 }
120
121 /* Ensure data is written before setting the flag. */
122 __DMB();
123
124 shm->rsp_ready = 0;
125 shm->cmd_seq = seq;
126 shm->cmd_pending = 1;
127
128 /* Signal the net core. */
130
131 /* Busy-wait for the response with timeout. */
132 start = clock_time();
133 while(!shm->rsp_ready || shm->rsp_seq != seq) {
134 if(clock_time() - start >
135 (clock_time_t)(NRF_IPC_CMD_TIMEOUT_MS * CLOCK_SECOND / 1000)) {
136 LOG_ERR("Command %u timeout\n", type);
137 /* Clear the pending flag to prevent the net core from processing
138 * a stale command after the timeout. */
139 shm->cmd_pending = 0;
140 return -1;
141 }
142 }
143
144 __DMB();
145
146 return (int)shm->rsp.data[0];
147}
148/*---------------------------------------------------------------------------*/
149static void
150release_network_core(void)
151{
152 LOG_DBG("Releasing network core\n");
153
154 /*
155 * Do not grant the network core access to UART GPIO pins.
156 * The net core's debug output is forwarded over IPC instead,
157 * so the app core retains exclusive UART access for clean output.
158 */
159
160 /* Place the network MCU in the secure domain. */
161 nrf_spu_extdomain_set(NRF_SPU, 0, true, false);
162
163 /*
164 * Release the network MCU from force-off.
165 * NRF_RESET is a non-secure-only peripheral on nRF5340:
166 * - In TZ secure mode: must use NS alias (SPU is freshly configured)
167 * - In non-TZ mode: must use S alias (SPU may have stale state
168 * from recovery that blocks the NS alias)
169 */
170#ifdef TRUSTZONE_SECURE
171 nrf_reset_network_force_off(NRF_RESET_NS, false);
172#else
173 nrf_reset_network_force_off(NRF_RESET, false);
174#endif
175}
176/*---------------------------------------------------------------------------*/
177static bool ipc_radio_initialized;
178/*---------------------------------------------------------------------------*/
179static int
180ipc_radio_init(void)
181{
182 if(ipc_radio_initialized) {
183 return 1;
184 }
185
186 LOG_DBG("Initializing IPC radio\n");
187
188 /*
189 * Force-hold the network core before touching shared memory.
190 * FORCEOFF survives soft/pin resets, so the net core may still
191 * be running from a previous session, causing bus stalls.
192 */
193#ifdef TRUSTZONE_SECURE
194 nrf_reset_network_force_off(NRF_RESET_NS, true);
195#else
196 nrf_reset_network_force_off(NRF_RESET, true);
197#endif
198
199 /* Clear the shared memory area. */
200 memset((void *)shm, 0, sizeof(*shm));
201 shm->version = NRF_IPC_PROTOCOL_VERSION;
202
203 /* Initialize the IPC transport on the app core. */
204 nrf_ipc_init(&ipc_radio_process);
205
206 /* Start the RX handler process. */
207 process_start(&ipc_radio_process, NULL);
208
209 /* Release the network core so it can boot. */
210 release_network_core();
211
212 /* Wait for the network core to initialize and signal readiness. */
213 LOG_DBG("Waiting for network core...\n");
214#ifdef TRUSTZONE_SECURE
215 /*
216 * In TrustZone mode, this runs inside an NSC call where
217 * clock_time() may not advance (RTC interrupt preempted).
218 * Use NRFX_WAIT_FOR which provides calibrated microsecond delays.
219 */
220 {
221 bool ready;
222 NRFX_WAIT_FOR(shm->net_ready, NET_CORE_INIT_TIMEOUT_MS, 1000, ready);
223 if(!ready) {
224 LOG_ERR("Network core init timeout\n");
225 return 0;
226 }
227 }
228#else
229 {
230 clock_time_t start = clock_time();
231 while(!shm->net_ready) {
232 if(clock_time() - start >
233 (clock_time_t)(NET_CORE_INIT_TIMEOUT_MS * CLOCK_SECOND / 1000)) {
234 LOG_ERR("Network core init timeout\n");
235 return 0;
236 }
237 }
238 }
239#endif
240
241 LOG_INFO("Network core ready (IPC protocol v%u)\n",
242 (unsigned)shm->version);
243
244 /* Send the init command to the net core's radio service. */
245 if(send_command(NRF_IPC_CMD_INIT, NULL, 0) != 1) {
246 LOG_ERR("Radio init command failed\n");
247 return 0;
248 }
249
250 LOG_INFO("IPC radio operational"
251#ifdef TRUSTZONE_SECURE
252 " (TrustZone secure)"
253#endif
254 "\n");
255
256 ipc_radio_initialized = true;
257 return 1;
258}
259/*---------------------------------------------------------------------------*/
260static int
261ipc_radio_prepare(const void *payload, unsigned short payload_len)
262{
263 if(payload_len > NRF_IPC_MAX_FRAME_LEN) {
264 LOG_ERR("Frame too long: %u\n", payload_len);
265 return 1;
266 }
267
268 memcpy(tx_frame_buf, payload, payload_len);
269
270 return 0;
271}
272/*---------------------------------------------------------------------------*/
273static int
274ipc_radio_transmit(unsigned short transmit_len)
275{
276 int result;
277
278 if(transmit_len > sizeof(tx_frame_buf)) {
279 LOG_ERR("Frame too long: %u\n", transmit_len);
280 return RADIO_TX_ERR;
281 }
282
283 LOG_DBG("TX %u bytes\n", transmit_len);
284
285 result = send_command(NRF_IPC_CMD_SEND, tx_frame_buf, transmit_len);
286
287 /* send_command returns -1 on IPC timeout; map to a valid radio_tx_e. */
288 return result < 0 ? RADIO_TX_ERR : result;
289}
290/*---------------------------------------------------------------------------*/
291static int
292ipc_radio_send(const void *payload, unsigned short payload_len)
293{
294 if(ipc_radio_prepare(payload, payload_len) != 0) {
295 return RADIO_TX_ERR;
296 }
297 return ipc_radio_transmit(payload_len);
298}
299/*---------------------------------------------------------------------------*/
300static int
301ipc_radio_read(void *buf, unsigned short buf_len)
302{
303 int len;
304
305 if(!rx_frame_pending) {
306 return 0;
307 }
308
309 len = rx_frame_len;
310 if(len > buf_len) {
311 len = buf_len;
312 }
313
314 memcpy(buf, rx_frame_buf, len);
315 rx_frame_pending = false;
316
317 return len;
318}
319/*---------------------------------------------------------------------------*/
320static int
321ipc_radio_channel_clear(void)
322{
323 int result = send_command(NRF_IPC_CMD_CCA, NULL, 0);
324
325 /* Treat IPC timeout as "channel busy" so the caller backs off
326 * rather than transmitting blindly. */
327 return result < 0 ? 0 : result;
328}
329/*---------------------------------------------------------------------------*/
330static int
331ipc_radio_receiving_packet(void)
332{
333 int result = send_command(NRF_IPC_CMD_RECEIVING, NULL, 0);
334
335 return result < 0 ? 0 : result;
336}
337/*---------------------------------------------------------------------------*/
338/**
339 * Pull a received frame from shared memory into the local buffer.
340 *
341 * This is the single code path for consuming frames from the net core.
342 * It is called from both the polling context (pending_packet) and the
343 * process thread (ipc_radio_process), ensuring consistent handling.
344 *
345 * \return 1 if a frame was pulled, 0 otherwise.
346 */
347static int
348pull_rx_frame(void)
349{
350 int len;
351
352 if(!shm->rx.pending) {
353 return 0;
354 }
355
356 /* Ensure we read the data after observing pending == 1. */
357 __DMB();
358
359 len = shm->rx.len;
360 if(len > 0 && len <= NRF_IPC_MAX_FRAME_LEN) {
361 memcpy(rx_frame_buf, (const void *)shm->rx.data, len);
362 rx_frame_len = len;
363 rx_frame_pending = true;
364 }
365
366 /* Ensure the data copy completes before releasing the slot. */
367 __DMB();
368
369 shm->rx.pending = 0;
370 return rx_frame_pending ? 1 : 0;
371}
372/*---------------------------------------------------------------------------*/
373static int
374ipc_radio_pending_packet(void)
375{
376 if(rx_frame_pending) {
377 return 1;
378 }
379
380 /*
381 * Check the dedicated ACK slot first. CSMA calls pending_packet()
382 * + read() in a tight RTIMER_BUSYWAIT loop for ACK detection.
383 * The IPC MAC puts ACK frames in shm->rx_ack (separate from data
384 * frames in shm->rx) to prevent the ACK detection loop from
385 * consuming and discarding data frames.
386 */
387 if(shm->rx_ack.pending) {
388 __DMB();
389 memcpy(rx_frame_buf, (const void *)shm->rx_ack.data, 3);
390 rx_frame_len = 3;
391 rx_frame_pending = true;
392 __DMB();
393 shm->rx_ack.pending = 0;
394 return 1;
395 }
396
397 /*
398 * Data frames are delivered via the process thread only
399 * (ipc_radio_process checks shm->rx.pending). Do NOT call
400 * pull_rx_frame() here — it would consume data frames that
401 * CSMA then reads as 3-byte ACKs and discards.
402 */
403 return 0;
404}
405/*---------------------------------------------------------------------------*/
406static int
407ipc_radio_on(void)
408{
409 int result = send_command(NRF_IPC_CMD_ON, NULL, 0);
410
411 return result < 0 ? 0 : result;
412}
413/*---------------------------------------------------------------------------*/
414static int
415ipc_radio_off(void)
416{
417 int result = send_command(NRF_IPC_CMD_OFF, NULL, 0);
418
419 return result < 0 ? 0 : result;
420}
421/*---------------------------------------------------------------------------*/
422static radio_result_t
423ipc_radio_get_value(radio_param_t param, radio_value_t *value)
424{
425 uint8_t cmd_data[2];
426 int result;
427
428 cmd_data[0] = (uint8_t)(param & 0xff);
429 cmd_data[1] = (uint8_t)((param >> 8) & 0xff);
430
431 result = send_command(NRF_IPC_CMD_GET_VALUE, cmd_data, 2);
432
433 if(result < 0) {
434 return RADIO_RESULT_ERROR;
435 }
436
437 if(result == RADIO_RESULT_OK) {
438 /* Value is stored in rsp.data[1..4]. */
439 memcpy(value, (const void *)&shm->rsp.data[1], sizeof(radio_value_t));
440 }
441
442 return (radio_result_t)result;
443}
444/*---------------------------------------------------------------------------*/
445static radio_result_t
446ipc_radio_set_value(radio_param_t param, radio_value_t value)
447{
448 uint8_t cmd_data[2 + sizeof(radio_value_t)];
449 int result;
450
451 cmd_data[0] = (uint8_t)(param & 0xff);
452 cmd_data[1] = (uint8_t)((param >> 8) & 0xff);
453 memcpy(&cmd_data[2], &value, sizeof(radio_value_t));
454
455 result = send_command(NRF_IPC_CMD_SET_VALUE, cmd_data, sizeof(cmd_data));
456
457 return result < 0 ? RADIO_RESULT_ERROR : (radio_result_t)result;
458}
459/*---------------------------------------------------------------------------*/
460static radio_result_t
461ipc_radio_get_object(radio_param_t param, void *dest, size_t size)
462{
463 uint8_t cmd_data[4];
464 int result;
465
466 cmd_data[0] = (uint8_t)(param & 0xff);
467 cmd_data[1] = (uint8_t)((param >> 8) & 0xff);
468 cmd_data[2] = (uint8_t)(size & 0xff);
469 cmd_data[3] = (uint8_t)((size >> 8) & 0xff);
470
471 result = send_command(NRF_IPC_CMD_GET_OBJECT, cmd_data, 4);
472
473 if(result < 0) {
474 return RADIO_RESULT_ERROR;
475 }
476
477 if(result == RADIO_RESULT_OK) {
478 uint16_t rsp_size;
479 memcpy(&rsp_size, (const void *)&shm->rsp.data[1], 2);
480 if(rsp_size <= size) {
481 memcpy(dest, (const void *)&shm->rsp.data[3], rsp_size);
482 }
483 }
484
485 return (radio_result_t)result;
486}
487/*---------------------------------------------------------------------------*/
488static radio_result_t
489ipc_radio_set_object(radio_param_t param, const void *src, size_t size)
490{
491 uint8_t cmd_data[NRF_IPC_MAX_DATA_LEN];
492 int result;
493
494 if(size > NRF_IPC_MAX_DATA_LEN - 4) {
496 }
497
498 cmd_data[0] = (uint8_t)(param & 0xff);
499 cmd_data[1] = (uint8_t)((param >> 8) & 0xff);
500 cmd_data[2] = (uint8_t)(size & 0xff);
501 cmd_data[3] = (uint8_t)((size >> 8) & 0xff);
502 memcpy(&cmd_data[4], src, size);
503
504 result = send_command(NRF_IPC_CMD_SET_OBJECT, cmd_data, 4 + size);
505
506 return result < 0 ? RADIO_RESULT_ERROR : (radio_result_t)result;
507}
508/*---------------------------------------------------------------------------*/
509const struct radio_driver ipc_radio_driver = {
510 ipc_radio_init,
511 ipc_radio_prepare,
512 ipc_radio_transmit,
513 ipc_radio_send,
514 ipc_radio_read,
515 ipc_radio_channel_clear,
516 ipc_radio_receiving_packet,
517 ipc_radio_pending_packet,
518 ipc_radio_on,
519 ipc_radio_off,
520 ipc_radio_get_value,
521 ipc_radio_set_value,
522 ipc_radio_get_object,
523 ipc_radio_set_object
524};
525/*---------------------------------------------------------------------------*/
526/**
527 * Drain the net core's log ring buffer and print each line
528 * with a [NET] prefix for clear identification.
529 */
530static void
531drain_net_log(void)
532{
533 static char line_buf[128];
534 static uint8_t line_pos;
535 uint16_t tail;
536 uint16_t head;
537
538 tail = shm->log.tail;
539 head = shm->log.head;
540 __DMB();
541
542 /*
543 * Drain at most one line per call to avoid blocking the process
544 * thread when UART is slow (e.g., ITNS misconfigured after
545 * recovery, causing the nrfx UARTE ISR to not fire).
546 */
547 while(tail != head) {
548 char c = shm->log.data[tail];
549 tail = (tail + 1) % NRF_IPC_LOG_BUF_SIZE;
550
551 if(line_pos < sizeof(line_buf) - 1) {
552 line_buf[line_pos++] = c;
553 }
554
555 if(c == '\n' || line_pos >= sizeof(line_buf) - 1) {
556 line_buf[line_pos] = '\0';
557 printf("[NET] %s", line_buf);
558 line_pos = 0;
559 break; /* One line per call, return to process RX frames. */
560 }
561 }
562
563 shm->log.tail = tail;
564}
565/*---------------------------------------------------------------------------*/
566PROCESS_THREAD(ipc_radio_process, ev, data)
567{
568 static struct etimer rx_poll_timer;
569
571
572 /* Poll shared memory for RX frames every 50ms as a backup
573 * in case the IPC interrupt path doesn't deliver them. */
574 etimer_set(&rx_poll_timer, CLOCK_SECOND / 20);
575
576 while(1) {
578
579 drain_net_log();
580
581 if(etimer_expired(&rx_poll_timer)) {
582 etimer_restart(&rx_poll_timer);
583 }
584
585
586 /*
587 * Check for a received frame from the net core. We must read
588 * RSSI/LQI from shared memory before pull_rx_frame() releases
589 * the slot, since the net core may overwrite them immediately.
590 */
591 if(shm->rx.pending) {
592 int8_t rssi = shm->rx.rssi;
593 uint8_t lqi = shm->rx.lqi;
594
595 if(pull_rx_frame()) {
596#ifdef TRUSTZONE_SECURE
597 /*
598 * In the secure world, we do not deliver directly to the MAC
599 * (which runs in the normal world). Instead, notify the normal
600 * world so it can read the frame via NSC calls.
601 */
602 tz_radio_notify_rx(rssi, lqi);
603#else
604 /* Deliver the frame to the MAC layer. */
605 int len;
607 len = ipc_radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
608 if(len > 0) {
610 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (int)rssi);
611 packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, lqi);
612 LOG_DBG("RX %d bytes, delivering to MAC\n", len);
613 NETSTACK_MAC.input();
614 }
615#endif /* TRUSTZONE_SECURE */
616 }
617 }
618 }
619
620 PROCESS_END();
621}
622/*---------------------------------------------------------------------------*/
623#endif /* NRF5340_XXAA_APPLICATION */
624/*---------------------------------------------------------------------------*/
625/**
626 * @}
627 */
clock_time_t clock_time(void)
Get the current clock time.
Definition clock.c:118
#define CLOCK_SECOND
A second, measured in system clock time.
Definition clock.h:105
void etimer_restart(struct etimer *et)
Restart an event timer from the current point in time.
Definition etimer.c:199
static bool etimer_expired(struct etimer *et)
Check if an event timer has expired.
Definition etimer.h:201
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition etimer.c:177
#define NRF_IPC_LOG_BUF_SIZE
Size of the log ring buffer for forwarding net core output to the app core.
Definition nrf-ipc.h:102
#define NRF_IPC_MAX_FRAME_LEN
Maximum 802.15.4 frame size carried over IPC.
Definition nrf-ipc.h:75
#define NRF_IPC_MAX_DATA_LEN
Maximum data size in a command or response message.
Definition nrf-ipc.h:80
void nrf_ipc_init(struct process *callback_proc)
Initialize the IPC transport layer.
void nrf_ipc_signal(void)
Send an IPC signal to the other core.
#define NRF_IPC_PROTOCOL_VERSION
Protocol version.
Definition nrf-ipc.h:55
#define NRF_IPC_SHARED_MEM
Get a pointer to the shared memory structure.
Definition nrf-ipc.h:212
#define NRF_IPC_CMD_TIMEOUT_MS
Timeout in milliseconds for IPC command responses.
Definition nrf-ipc.h:87
@ NRF_IPC_CMD_GET_VALUE
Get a radio parameter (radio_value_t).
Definition nrf-ipc.h:119
@ NRF_IPC_CMD_GET_OBJECT
Get a radio parameter (object/blob).
Definition nrf-ipc.h:121
@ NRF_IPC_CMD_RECEIVING
Check if a frame is being received.
Definition nrf-ipc.h:117
@ NRF_IPC_CMD_SET_OBJECT
Set a radio parameter (object/blob).
Definition nrf-ipc.h:122
@ NRF_IPC_CMD_ON
Turn the radio on.
Definition nrf-ipc.h:113
@ NRF_IPC_CMD_SEND
Transmit a frame (data in cmd.data).
Definition nrf-ipc.h:115
@ NRF_IPC_CMD_SET_VALUE
Set a radio parameter (radio_value_t).
Definition nrf-ipc.h:120
@ NRF_IPC_CMD_INIT
Initialize the radio driver.
Definition nrf-ipc.h:112
@ NRF_IPC_CMD_OFF
Turn the radio off.
Definition nrf-ipc.h:114
@ NRF_IPC_CMD_CCA
Perform Clear Channel Assessment.
Definition nrf-ipc.h:116
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_WAIT_EVENT()
Wait for an event to be posted to the process.
Definition process.h:143
#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
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
@ RADIO_RESULT_ERROR
An error occurred when getting/setting the parameter, but the arguments were otherwise correct.
Definition radio.h:488
@ 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_TX_ERR
An error occurred during transmission.
Definition radio.h:506
static void start(void)
Start measurement.
Header file for the logging system.
Include file for the Contiki low-layer network stack (NETSTACK)
IPC protocol definitions for nRF5340 dual-core communication.
Header file for the Packet buffer (packetbuf) management.
Header file for the radio API.
A timer.
Definition etimer.h:79
void(* input)(void)
Callback for getting notified of incoming packet.
Definition mac.h:78
Shared memory layout between the application core and the network core.
Definition nrf-ipc.h:154
struct nrf_ipc_msg rsp
Response mailbox (net -> app).
Definition nrf-ipc.h:167
volatile uint8_t rsp_seq
Echoed from cmd_seq by net core.
Definition nrf-ipc.h:169
volatile uint8_t cmd_seq
Sequence number set by app core.
Definition nrf-ipc.h:164
struct nrf_ipc_msg cmd
Command mailbox (app -> net).
Definition nrf-ipc.h:162
The structure of a Contiki-NG radio device driver.
Definition radio.h:534