55#ifdef TRUSTZONE_SECURE
56#include "trustzone/tz-radio.h"
60#ifdef NRF5340_XXAA_APPLICATION
62#include "hal/nrf_gpio.h"
63#include "hal/nrf_reset.h"
64#include "hal/nrf_spu.h"
67#define LOG_MODULE "IPC Radio"
68#define LOG_LEVEL LOG_LEVEL_INFO
70#define NET_CORE_INIT_TIMEOUT_MS 1000
76static int rx_frame_len;
77static bool rx_frame_pending;
82PROCESS(ipc_radio_process,
"IPC Radio");
98static uint8_t cmd_seq_counter;
101send_command(uint8_t type,
const void *data, uint8_t len)
107 LOG_ERR(
"Command payload too long: %u\n", len);
112 seq = ++cmd_seq_counter;
115 shm->
cmd.type = type;
117 if(data != NULL && len > 0) {
118 memcpy((
void *)shm->
cmd.data, data, len);
126 shm->cmd_pending = 1;
133 while(!shm->rsp_ready || shm->
rsp_seq != seq) {
136 LOG_ERR(
"Command %u timeout\n", type);
139 shm->cmd_pending = 0;
146 return (
int)shm->
rsp.data[0];
150release_network_core(
void)
152 LOG_DBG(
"Releasing network core\n");
161 nrf_spu_extdomain_set(NRF_SPU, 0,
true,
false);
170#ifdef TRUSTZONE_SECURE
171 nrf_reset_network_force_off(NRF_RESET_NS,
false);
173 nrf_reset_network_force_off(NRF_RESET,
false);
177static bool ipc_radio_initialized;
182 if(ipc_radio_initialized) {
186 LOG_DBG(
"Initializing IPC radio\n");
193#ifdef TRUSTZONE_SECURE
194 nrf_reset_network_force_off(NRF_RESET_NS,
true);
196 nrf_reset_network_force_off(NRF_RESET,
true);
200 memset((
void *)shm, 0,
sizeof(*shm));
210 release_network_core();
213 LOG_DBG(
"Waiting for network core...\n");
214#ifdef TRUSTZONE_SECURE
222 NRFX_WAIT_FOR(shm->net_ready, NET_CORE_INIT_TIMEOUT_MS, 1000, ready);
224 LOG_ERR(
"Network core init timeout\n");
231 while(!shm->net_ready) {
233 (clock_time_t)(NET_CORE_INIT_TIMEOUT_MS *
CLOCK_SECOND / 1000)) {
234 LOG_ERR(
"Network core init timeout\n");
241 LOG_INFO(
"Network core ready (IPC protocol v%u)\n",
242 (
unsigned)shm->version);
246 LOG_ERR(
"Radio init command failed\n");
250 LOG_INFO(
"IPC radio operational"
251#ifdef TRUSTZONE_SECURE
252 " (TrustZone secure)"
256 ipc_radio_initialized =
true;
261ipc_radio_prepare(
const void *payload,
unsigned short payload_len)
264 LOG_ERR(
"Frame too long: %u\n", payload_len);
268 memcpy(tx_frame_buf, payload, payload_len);
274ipc_radio_transmit(
unsigned short transmit_len)
278 if(transmit_len >
sizeof(tx_frame_buf)) {
279 LOG_ERR(
"Frame too long: %u\n", transmit_len);
283 LOG_DBG(
"TX %u bytes\n", transmit_len);
292ipc_radio_send(
const void *payload,
unsigned short payload_len)
294 if(ipc_radio_prepare(payload, payload_len) != 0) {
297 return ipc_radio_transmit(payload_len);
301ipc_radio_read(
void *buf,
unsigned short buf_len)
305 if(!rx_frame_pending) {
314 memcpy(buf, rx_frame_buf, len);
315 rx_frame_pending =
false;
321ipc_radio_channel_clear(
void)
327 return result < 0 ? 0 : result;
331ipc_radio_receiving_packet(
void)
335 return result < 0 ? 0 : result;
352 if(!shm->rx.pending) {
361 memcpy(rx_frame_buf, (
const void *)shm->rx.data, len);
363 rx_frame_pending =
true;
370 return rx_frame_pending ? 1 : 0;
374ipc_radio_pending_packet(
void)
376 if(rx_frame_pending) {
387 if(shm->rx_ack.pending) {
389 memcpy(rx_frame_buf, (
const void *)shm->rx_ack.data, 3);
391 rx_frame_pending =
true;
393 shm->rx_ack.pending = 0;
411 return result < 0 ? 0 : result;
419 return result < 0 ? 0 : result;
423ipc_radio_get_value(radio_param_t param,
radio_value_t *value)
428 cmd_data[0] = (uint8_t)(param & 0xff);
429 cmd_data[1] = (uint8_t)((param >> 8) & 0xff);
439 memcpy(value, (
const void *)&shm->rsp.data[1],
sizeof(
radio_value_t));
451 cmd_data[0] = (uint8_t)(param & 0xff);
452 cmd_data[1] = (uint8_t)((param >> 8) & 0xff);
461ipc_radio_get_object(radio_param_t param,
void *dest,
size_t size)
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);
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);
489ipc_radio_set_object(radio_param_t param,
const void *src,
size_t size)
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);
515 ipc_radio_channel_clear,
516 ipc_radio_receiving_packet,
517 ipc_radio_pending_packet,
522 ipc_radio_get_object,
533 static char line_buf[128];
534 static uint8_t line_pos;
538 tail = shm->log.tail;
539 head = shm->log.head;
547 while(tail != head) {
548 char c = shm->log.data[tail];
551 if(line_pos <
sizeof(line_buf) - 1) {
552 line_buf[line_pos++] = c;
555 if(c ==
'\n' || line_pos >=
sizeof(line_buf) - 1) {
556 line_buf[line_pos] =
'\0';
557 printf(
"[NET] %s", line_buf);
563 shm->log.tail = tail;
568 static struct etimer rx_poll_timer;
591 if(shm->rx.pending) {
592 int8_t rssi = shm->rx.rssi;
593 uint8_t lqi = shm->rx.lqi;
595 if(pull_rx_frame()) {
596#ifdef TRUSTZONE_SECURE
602 tz_radio_notify_rx(rssi, lqi);
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();
clock_time_t clock_time(void)
Get the current clock time.
#define CLOCK_SECOND
A second, measured in system clock time.
void etimer_restart(struct etimer *et)
Restart an event timer from the current point in time.
static bool etimer_expired(struct etimer *et)
Check if an event timer has expired.
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
#define NRF_IPC_LOG_BUF_SIZE
Size of the log ring buffer for forwarding net core output to the app core.
#define NRF_IPC_MAX_FRAME_LEN
Maximum 802.15.4 frame size carried over IPC.
#define NRF_IPC_MAX_DATA_LEN
Maximum data size in a command or response message.
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.
#define NRF_IPC_SHARED_MEM
Get a pointer to the shared memory structure.
#define NRF_IPC_CMD_TIMEOUT_MS
Timeout in milliseconds for IPC command responses.
@ NRF_IPC_CMD_GET_VALUE
Get a radio parameter (radio_value_t).
@ NRF_IPC_CMD_GET_OBJECT
Get a radio parameter (object/blob).
@ NRF_IPC_CMD_RECEIVING
Check if a frame is being received.
@ NRF_IPC_CMD_SET_OBJECT
Set a radio parameter (object/blob).
@ NRF_IPC_CMD_ON
Turn the radio on.
@ NRF_IPC_CMD_SEND
Transmit a frame (data in cmd.data).
@ NRF_IPC_CMD_SET_VALUE
Set a radio parameter (radio_value_t).
@ NRF_IPC_CMD_INIT
Initialize the radio driver.
@ NRF_IPC_CMD_OFF
Turn the radio off.
@ NRF_IPC_CMD_CCA
Perform Clear Channel Assessment.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
void packetbuf_clear(void)
Clear and reset the packetbuf.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
#define PROCESS_BEGIN()
Define the beginning of a process.
#define PROCESS_END()
Define the end of a process.
void process_start(struct process *p, process_data_t data)
Start a process.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
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.
@ RADIO_RESULT_ERROR
An error occurred when getting/setting the parameter, but the arguments were otherwise correct.
@ RADIO_RESULT_INVALID_VALUE
The value argument was incorrect.
@ RADIO_RESULT_OK
The parameter was set/read successfully.
@ RADIO_TX_ERR
An error occurred during transmission.
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.
void(* input)(void)
Callback for getting notified of incoming packet.
Shared memory layout between the application core and the network core.
struct nrf_ipc_msg rsp
Response mailbox (net -> app).
volatile uint8_t rsp_seq
Echoed from cmd_seq by net core.
volatile uint8_t cmd_seq
Sequence number set by app core.
struct nrf_ipc_msg cmd
Command mailbox (app -> net).
The structure of a Contiki-NG radio device driver.