57#ifdef TRUSTZONE_SECURE
58#include "trustzone/tz-radio.h"
62#ifdef NRF5340_XXAA_APPLICATION
64#include "hal/nrf_gpio.h"
65#include "hal/nrf_reset.h"
66#include "hal/nrf_spu.h"
69#define LOG_MODULE "IPC Radio"
70#define LOG_LEVEL LOG_LEVEL_INFO
72#define NET_CORE_INIT_TIMEOUT_MS 1000
78static int rx_frame_len;
79static bool rx_frame_pending;
84PROCESS(ipc_radio_process,
"IPC Radio");
87 const void *src,
size_t size);
103static uint8_t cmd_seq_counter;
106send_command(uint8_t type,
const void *data, uint8_t len)
112 LOG_ERR(
"Command payload too long: %u\n", len);
117 seq = ++cmd_seq_counter;
120 shm->cmd.type = type;
122 if(data != NULL && len > 0) {
123 memcpy((
void *)shm->cmd.data, data, len);
131 shm->cmd_pending = 1;
138 while(!shm->rsp_ready || shm->rsp_seq != seq) {
141 LOG_ERR(
"Command %u timeout\n", type);
144 shm->cmd_pending = 0;
151 return (
int)shm->rsp.data[0];
155release_network_core(
void)
157 LOG_DBG(
"Releasing network core\n");
166 nrf_spu_extdomain_set(NRF_SPU, 0,
true,
false);
175#ifdef TRUSTZONE_SECURE
176 nrf_reset_network_force_off(NRF_RESET_NS,
false);
178 nrf_reset_network_force_off(NRF_RESET,
false);
182static bool ipc_radio_initialized;
187 if(ipc_radio_initialized) {
191 LOG_DBG(
"Initializing IPC radio\n");
198#ifdef TRUSTZONE_SECURE
199 nrf_reset_network_force_off(NRF_RESET_NS,
true);
201 nrf_reset_network_force_off(NRF_RESET,
true);
205 memset((
void *)shm, 0,
sizeof(*shm));
215 release_network_core();
218 LOG_DBG(
"Waiting for network core...\n");
219#ifdef TRUSTZONE_SECURE
227 NRFX_WAIT_FOR(shm->net_ready, NET_CORE_INIT_TIMEOUT_MS, 1000, ready);
229 LOG_ERR(
"Network core init timeout\n");
236 while(!shm->net_ready) {
238 (clock_time_t)(NET_CORE_INIT_TIMEOUT_MS *
CLOCK_SECOND / 1000)) {
239 LOG_ERR(
"Network core init timeout\n");
246 LOG_INFO(
"Network core ready (IPC protocol v%u)\n",
247 (
unsigned)shm->version);
251 LOG_ERR(
"Radio init command failed\n");
267 uint8_t short_addr[2];
269 pan_id[0] = (uint8_t)(IEEE802154_PANID & 0xFF);
270 pan_id[1] = (uint8_t)(IEEE802154_PANID >> 8);
273 LOG_INFO(
"Net core radio does not take addresses (legacy service)\n");
279#if LINKADDR_SIZE == 8
283 LOG_INFO(
"Pushed link-layer address to net core\n");
287 LOG_INFO(
"IPC radio operational"
288#ifdef TRUSTZONE_SECURE
289 " (TrustZone secure)"
293 ipc_radio_initialized =
true;
298ipc_radio_prepare(
const void *payload,
unsigned short payload_len)
301 LOG_ERR(
"Frame too long: %u\n", payload_len);
305 memcpy(tx_frame_buf, payload, payload_len);
311ipc_radio_transmit(
unsigned short transmit_len)
315 if(transmit_len >
sizeof(tx_frame_buf)) {
316 LOG_ERR(
"Frame too long: %u\n", transmit_len);
320 LOG_DBG(
"TX %u bytes\n", transmit_len);
329ipc_radio_send(
const void *payload,
unsigned short payload_len)
331 if(ipc_radio_prepare(payload, payload_len) != 0) {
334 return ipc_radio_transmit(payload_len);
338ipc_radio_read(
void *buf,
unsigned short buf_len)
342 if(!rx_frame_pending) {
351 memcpy(buf, rx_frame_buf, len);
352 rx_frame_pending =
false;
358ipc_radio_channel_clear(
void)
364 return result < 0 ? 0 : result;
368ipc_radio_receiving_packet(
void)
372 return result < 0 ? 0 : result;
389 if(!shm->rx.pending) {
398 memcpy(rx_frame_buf, (
const void *)shm->rx.data, len);
400 rx_frame_pending =
true;
407 return rx_frame_pending ? 1 : 0;
411ipc_radio_pending_packet(
void)
413 if(rx_frame_pending) {
424 if(shm->rx_ack.pending) {
426 memcpy(rx_frame_buf, (
const void *)shm->rx_ack.data, 3);
428 rx_frame_pending =
true;
430 shm->rx_ack.pending = 0;
448 return result < 0 ? 0 : result;
456 return result < 0 ? 0 : result;
465 cmd_data[0] = (uint8_t)(param & 0xff);
466 cmd_data[1] = (uint8_t)((param >> 8) & 0xff);
488 cmd_data[0] = (uint8_t)(param & 0xff);
489 cmd_data[1] = (uint8_t)((param >> 8) & 0xff);
498ipc_radio_get_object(radio_param_t param,
void *dest,
size_t size)
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);
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);
526ipc_radio_set_object(radio_param_t param,
const void *src,
size_t size)
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);
552 ipc_radio_channel_clear,
553 ipc_radio_receiving_packet,
554 ipc_radio_pending_packet,
559 ipc_radio_get_object,
570 static char line_buf[128];
571 static uint8_t line_pos;
575 tail = shm->log.tail;
576 head = shm->log.head;
584 while(tail != head) {
585 char c = shm->log.data[tail];
588 if(line_pos <
sizeof(line_buf) - 1) {
589 line_buf[line_pos++] = c;
592 if(c ==
'\n' || line_pos >=
sizeof(line_buf) - 1) {
593 line_buf[line_pos] =
'\0';
594 printf(
"[NET] %s", line_buf);
600 shm->log.tail = tail;
605 static struct etimer rx_poll_timer;
628 if(shm->rx.pending) {
629 int8_t rssi = shm->rx.rssi;
630 uint8_t lqi = shm->rx.lqi;
632 if(pull_rx_frame()) {
633#ifdef TRUSTZONE_SECURE
639 tz_radio_notify_rx(rssi, lqi);
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();
802.15.4 frame creation and parsing functions
clock_time_t clock_time(void)
Get the current clock time.
static int value(int type)
#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.
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
#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_PARAM_64BIT_ADDR
Long (64 bits) address for the radio, which is used by the address filter.
@ RADIO_PARAM_PAN_ID
The personal area network identifier (PAN ID), which is used by the h/w frame filtering functionality...
@ RADIO_PARAM_16BIT_ADDR
The short address (16 bits) for the radio, which is used by the h/w filter.
@ RADIO_TX_ERR
An error occurred during transmission.
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.
Shared memory layout between the application core and the network core.
The structure of a Contiki-NG radio device driver.