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