IPC: Add nrf5340 IPC peripheral model
Including HAL replacements Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
This commit is contained in:
parent
dacbaa0fa9
commit
e84fca483b
|
@ -28,7 +28,7 @@ Notation:
|
|||
| **GPIO** | General purpose input/output | ✔ | 𐄂 | For 52: See [NRF_GPIO.c](../src/HW_models/NRF_GPIO.c) |
|
||||
| **GPIOTE** | GPIO tasks and events | ✅ | 𐄂 | For 52: Complete with very minor differences, see [NRF_GPIOTE.c](../src/HW_models/NRF_GPIOTE.c) |
|
||||
| **I2S** | Inter-IC sound interface | 𐄂 | 𐄂 | |
|
||||
| **IPC** | Interprocessor communication | 𐄂 | 𐄂 | |
|
||||
| **IPC** | Interprocessor communication | N/A | ✔ | See [NHW_IPC.c](../src/HW_models/NHW_IPC.c) |
|
||||
| **KMU** | Key management unit | 𐄂 | 𐄂 | |
|
||||
| **LPCOMP** | Low-power comparator | 𐄂 | 𐄂 | |
|
||||
| **MUTEX** | Mutual exclusive peripheral | N/A | 𐄂 | |
|
||||
|
|
|
@ -2,6 +2,7 @@ src/nrfx/drivers/nrfx_common.c
|
|||
src/nrfx/hal/nrf_clock.c
|
||||
src/nrfx/hal/nrf_dppi.c
|
||||
src/nrfx/hal/nrf_egu.c
|
||||
src/nrfx/hal/nrf_ipc.c
|
||||
src/nrfx/hal/nrf_nvmc.c
|
||||
src/nrfx/hal/nrf_rtc.c
|
||||
src/nrfx/hal/nrf_timer.c
|
||||
|
|
|
@ -13,6 +13,7 @@ src/HW_models/NHW_AES_ECB.c
|
|||
src/HW_models/NHW_DPPI.c
|
||||
src/HW_models/NHW_CLOCK.c
|
||||
src/HW_models/NHW_EGU.c
|
||||
src/HW_models/NHW_IPC.c
|
||||
src/HW_models/NHW_misc.c
|
||||
src/HW_models/NHW_NVMC.c
|
||||
src/HW_models/NHW_NVM_backend.c
|
||||
|
|
|
@ -6,6 +6,7 @@ src/nrfx/hal/nrf_dppi.c
|
|||
src/nrfx/hal/nrf_ecb.c
|
||||
src/nrfx/hal/nrf_egu.c
|
||||
src/nrfx/hal/nrf_hack.c
|
||||
src/nrfx/hal/nrf_ipc.c
|
||||
src/nrfx/hal/nrf_nvmc.c
|
||||
src/nrfx/hal/nrf_radio.c
|
||||
src/nrfx/hal/nrf_rng.c
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* IPC - Interprocessor communication
|
||||
* https://infocenter.nordicsemi.com/topic/ps_nrf5340/ipc.html?cp=4_0_0_6_15
|
||||
*
|
||||
* This file provides the implementation of the nRF5340 IPC peripherals,
|
||||
* and instantiates N of them (and initializes them at startup and frees them on exit),
|
||||
* as described in the configuration (NHW_config.h)
|
||||
*
|
||||
* Each IPC instance has a configurable number of channels/tasks/events (up to 32)
|
||||
*
|
||||
* Notes:
|
||||
* * Close enough events in the IPC channels are not merged.
|
||||
* Note the spec does not specify t_IPC.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "nsi_tasks.h"
|
||||
#include "bs_tracing.h"
|
||||
#include "bs_oswrap.h"
|
||||
#include "NHW_common_types.h"
|
||||
#include "NHW_config.h"
|
||||
#include "NHW_peri_types.h"
|
||||
#include "NHW_templates.h"
|
||||
#include "irq_ctrl.h"
|
||||
#include "NHW_DPPI.h"
|
||||
|
||||
struct ipc_status {
|
||||
NRF_IPC_Type *NRF_IPC_regs;
|
||||
uint n_ch; /* Number of events configured in this IPC instance */
|
||||
|
||||
uint dppi_map; //To which DPPI instance are this IPC subscribe&publish ports connected to
|
||||
//Which of the subscription ports are currently connected, and to which channel:
|
||||
struct nhw_subsc_mem* subscribed; //[n_ch]
|
||||
};
|
||||
|
||||
static uint nhw_IPC_dppi_map[NHW_IPC_TOTAL_INST] = NHW_IPC_DPPI_MAP;
|
||||
static struct ipc_status nhw_ipc_st[NHW_IPC_TOTAL_INST];
|
||||
NRF_IPC_Type NRF_IPC_regs[NHW_IPC_TOTAL_INST];
|
||||
|
||||
/**
|
||||
* Initialize the IPC model
|
||||
*/
|
||||
static void nhw_ipc_init(void) {
|
||||
/* Mapping of peripheral instance to DPPI instance */
|
||||
uint nhw_ipc_n_ch[NHW_IPC_TOTAL_INST] = NHW_IPC_N_CH;
|
||||
|
||||
memset(NRF_IPC_regs, 0, sizeof(NRF_IPC_Type) * NHW_IPC_TOTAL_INST);
|
||||
|
||||
for (int i = 0; i< NHW_IPC_TOTAL_INST; i++) {
|
||||
nhw_ipc_st[i].NRF_IPC_regs = &NRF_IPC_regs[i];
|
||||
nhw_ipc_st[i].n_ch = nhw_ipc_n_ch[i];
|
||||
|
||||
nhw_ipc_st[i].dppi_map = nhw_IPC_dppi_map[i];
|
||||
nhw_ipc_st[i].subscribed = (struct nhw_subsc_mem*)bs_calloc(nhw_ipc_n_ch[i], sizeof(struct nhw_subsc_mem));
|
||||
}
|
||||
}
|
||||
|
||||
NSI_TASK(nhw_ipc_init, HW_INIT, 100);
|
||||
|
||||
/*
|
||||
* Free all IPC instances resources before program exit
|
||||
*/
|
||||
static void nhw_ipc_free(void)
|
||||
{
|
||||
for (int i = 0; i < NHW_IPC_TOTAL_INST; i++) {
|
||||
free(nhw_ipc_st[i].subscribed);
|
||||
nhw_ipc_st[i].subscribed = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
NSI_TASK(nhw_ipc_free, ON_EXIT_PRE, 100);
|
||||
|
||||
static void nhw_IPC_eval_interrupt(uint inst) {
|
||||
static bool ipc_int_line[NHW_IPC_TOTAL_INST]; /* Is this IPC currently driving its interrupt line high */
|
||||
/* Mapping of peripheral instance to {int controller instance, int number} */
|
||||
static struct nhw_irq_mapping nhw_ipc_irq_map[NHW_IPC_TOTAL_INST] = NHW_IPC_INT_MAP;
|
||||
bool new_int_line = false;
|
||||
|
||||
struct ipc_status *this = &nhw_ipc_st[inst];
|
||||
NRF_IPC_Type *IPC_regs = &NRF_IPC_regs[inst];
|
||||
|
||||
uint32_t event_m = 0;
|
||||
|
||||
for (int i = 0; i < this->n_ch; i++) {
|
||||
if (IPC_regs->EVENTS_RECEIVE[i]) {
|
||||
event_m |= 1<<i;
|
||||
}
|
||||
}
|
||||
|
||||
IPC_regs->INTPEND = IPC_regs->INTEN & event_m;
|
||||
|
||||
new_int_line = (IPC_regs->INTPEND != 0);
|
||||
|
||||
hw_irq_ctrl_toggle_level_irq_line_if(&ipc_int_line[inst],
|
||||
new_int_line,
|
||||
&nhw_ipc_irq_map[inst]);
|
||||
}
|
||||
|
||||
#define CHECK_VALID_CHANNEL(inst, ch, what) \
|
||||
if (nhw_ipc_st[inst].n_ch <= ch) { \
|
||||
bs_trace_error_time_line("Attempting to access IPC%i %s for channel %u>=%u\n", \
|
||||
inst, what, ch, nhw_ipc_st[inst].n_ch); \
|
||||
}
|
||||
|
||||
static void nhw_IPC_signal_EVENT(uint inst, uint ch) {
|
||||
NRF_IPC_regs[inst].EVENTS_RECEIVE[ch] = 1;
|
||||
nhw_IPC_eval_interrupt(inst);
|
||||
nhw_dppi_event_signal_if(nhw_IPC_dppi_map[inst], NRF_IPC_regs[inst].PUBLISH_RECEIVE[ch]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal an event in channel <ch> in the IPC backbone
|
||||
* i.e. Check for all IPC peripherals, if they are receiving
|
||||
* in that channel, and if so have them signal the corresponding
|
||||
* EVENT RECEIVE
|
||||
*/
|
||||
static void nhw_IPC_notify_ipc_ch(uint ch) {
|
||||
for (uint inst = 0; inst <= NHW_IPC_TOTAL_INST; inst++) {
|
||||
uint ch_mask = 1 << ch;
|
||||
for (int i = 0; i < nhw_ipc_st[inst].n_ch; i++) {
|
||||
if (NRF_IPC_regs[inst].RECEIVE_CNF[i] & ch_mask) {
|
||||
nhw_IPC_signal_EVENT(inst, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nhw_IPC_TASKS_SEND(uint inst, uint ch) {
|
||||
CHECK_VALID_CHANNEL(inst, ch, "TASK_SEND");
|
||||
|
||||
uint32_t send_cnf = NRF_IPC_regs[inst].SEND_CNF[ch];
|
||||
|
||||
for (int i = __builtin_ffs(send_cnf) - 1; i >= 0; i = __builtin_ffs(send_cnf) - 1) {
|
||||
nhw_IPC_notify_ipc_ch(i);
|
||||
send_cnf &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
void nhw_IPC_regw_sideeffects_TASKS_SEND(uint inst, uint ch) {
|
||||
if (NRF_IPC_regs[inst].TASKS_SEND[ch]) {
|
||||
NRF_IPC_regs[inst].TASKS_SEND[ch] = 0;
|
||||
nhw_IPC_TASKS_SEND(inst, ch);
|
||||
}
|
||||
}
|
||||
|
||||
static void nhw_IPC_tasks_send_wrap(void* param) {
|
||||
unsigned int inst = (uintptr_t)param >> 16;
|
||||
uint n = (uintptr_t)param & 0xFFFF;
|
||||
nhw_IPC_TASKS_SEND(inst, n);
|
||||
}
|
||||
|
||||
void nhw_IPC_regw_sideeffects_SUBSCRIBE_SEND(uint inst, uint ch) {
|
||||
struct ipc_status *this = &nhw_ipc_st[inst];
|
||||
|
||||
CHECK_VALID_CHANNEL(inst, ch, "SUBSCRIBE");
|
||||
|
||||
nhw_dppi_common_subscribe_sideeffect(this->dppi_map,
|
||||
this->NRF_IPC_regs->SUBSCRIBE_SEND[ch],
|
||||
&this->subscribed[ch],
|
||||
nhw_IPC_tasks_send_wrap,
|
||||
(void*)((inst << 16) + ch));
|
||||
}
|
||||
|
||||
NHW_SIDEEFFECTS_INTEN(IPC, NRF_IPC_regs[inst]., NRF_IPC_regs[inst].INTEN)
|
||||
NHW_SIDEEFFECTS_INTSET(IPC, NRF_IPC_regs[inst]., NRF_IPC_regs[inst].INTEN)
|
||||
NHW_SIDEEFFECTS_INTCLR(IPC, NRF_IPC_regs[inst]., NRF_IPC_regs[inst].INTEN)
|
||||
|
||||
NHW_SIDEEFFECTS_EVENTS(IPC)
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _NRF_HW_MODEL_IPC_H
|
||||
#define _NRF_HW_MODEL_IPC_H
|
||||
|
||||
#include "bs_types.h"
|
||||
#include "NHW_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
extern NRF_IPC_Type NRF_IPC_regs[NHW_IPC_TOTAL_INST];
|
||||
|
||||
void nhw_IPC_regw_sideeffects_TASKS_SEND(uint inst, uint ch);
|
||||
void nhw_IPC_regw_sideeffects_EVENTS_all(uint inst);
|
||||
void nhw_IPC_regw_sideeffects_INTEN(uint inst);
|
||||
void nhw_IPC_regw_sideeffects_INTENSET(uint inst);
|
||||
void nhw_IPC_regw_sideeffects_INTENCLR(uint inst);
|
||||
void nhw_IPC_regw_sideeffects_SUBSCRIBE_SEND(uint inst, uint ch);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -263,6 +263,17 @@
|
|||
#define NHW_DPPI_N_CH {32, 32} /* Number of channels in each DPPI */
|
||||
#define NHW_DPPI_N_CHG {6, 6} /* Number of channel groups in each DPPI */
|
||||
|
||||
#define NHW_IPC_TOTAL_INST 2
|
||||
#define NHW_IPC_APP0 0
|
||||
#define NHW_IPC_NET0 1
|
||||
#define NHW_IPC_INT_MAP {{0 , 42}, \
|
||||
{1 , 18}}
|
||||
/* {App, IPC}
|
||||
* {Network, IPC}
|
||||
* */
|
||||
#define NHW_IPC_DPPI_MAP {0, 1} /*App, network */
|
||||
#define NHW_IPC_N_CH {16, 16}
|
||||
|
||||
#define NHW_FICR_APP 0
|
||||
#define NHW_FICR_NET 1
|
||||
|
||||
|
|
|
@ -1975,6 +1975,45 @@ typedef struct { /*!< (@ 0x01FF0000) FICR_NS Stru
|
|||
} NRF_FICR_NET_Type; /*!< Size = 1024 (0x400) */
|
||||
|
||||
|
||||
|
||||
/* =========================================================================================================================== */
|
||||
/* ================ IPC_NS ================ */
|
||||
/* =========================================================================================================================== */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Interprocessor communication (IPC_NS)
|
||||
*/
|
||||
|
||||
typedef struct { /*!< (@ 0x41012000) IPC_NS Structure */
|
||||
__OM uint32_t TASKS_SEND[16]; /*!< (@ 0x00000000) Description collection: Trigger events on IPC
|
||||
channel enabled in SEND_CNF[n] */
|
||||
__IM uint32_t RESERVED[16];
|
||||
__IOM uint32_t SUBSCRIBE_SEND[16]; /*!< (@ 0x00000080) Description collection: Subscribe configuration
|
||||
for task SEND[n] */
|
||||
__IM uint32_t RESERVED1[16];
|
||||
__IOM uint32_t EVENTS_RECEIVE[16]; /*!< (@ 0x00000100) Description collection: Event received on one
|
||||
or more of the enabled IPC channels in RECEIVE_CNF[n] */
|
||||
__IM uint32_t RESERVED2[16];
|
||||
__IOM uint32_t PUBLISH_RECEIVE[16]; /*!< (@ 0x00000180) Description collection: Publish configuration
|
||||
for event RECEIVE[n] */
|
||||
__IM uint32_t RESERVED3[80];
|
||||
__IOM uint32_t INTEN; /*!< (@ 0x00000300) Enable or disable interrupt */
|
||||
__IOM uint32_t INTENSET; /*!< (@ 0x00000304) Enable interrupt */
|
||||
__IOM uint32_t INTENCLR; /*!< (@ 0x00000308) Disable interrupt */
|
||||
__IM uint32_t INTPEND; /*!< (@ 0x0000030C) Pending interrupts */
|
||||
__IM uint32_t RESERVED4[128];
|
||||
__IOM uint32_t SEND_CNF[16]; /*!< (@ 0x00000510) Description collection: Send event configuration
|
||||
for TASKS_SEND[n] */
|
||||
__IM uint32_t RESERVED5[16];
|
||||
__IOM uint32_t RECEIVE_CNF[16]; /*!< (@ 0x00000590) Description collection: Receive event configuration
|
||||
for EVENTS_RECEIVE[n] */
|
||||
__IM uint32_t RESERVED6[16];
|
||||
__IOM uint32_t GPMEM[2]; /*!< (@ 0x00000610) Description collection: General purpose memory */
|
||||
} NRF_IPC_Type; /*!< Size = 1560 (0x618) */
|
||||
|
||||
|
||||
|
||||
/* =========================================================================================================================== */
|
||||
/* ================ NVMC ================ */
|
||||
/* =========================================================================================================================== */
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Note that the function prototypes are taken from the NRFx HAL
|
||||
*/
|
||||
#include "hal/nrf_ipc.h"
|
||||
#include "bs_tracing.h"
|
||||
#include "NHW_IPC.h"
|
||||
|
||||
static int ipc_number_from_ptr(NRF_IPC_Type const * p_reg){
|
||||
int i = ( (int)p_reg - (int)&NRF_IPC_regs[0] ) / sizeof(NRF_IPC_Type);
|
||||
return i;
|
||||
}
|
||||
|
||||
void nrf_ipc_task_trigger(NRF_IPC_Type * p_reg, nrf_ipc_task_t ipc_task)
|
||||
{
|
||||
*((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)ipc_task)) = 0x1UL;
|
||||
|
||||
int i = ipc_number_from_ptr(p_reg);
|
||||
int task_nbr = (ipc_task - NRF_IPC_TASK_SEND_0)/sizeof(uint32_t);
|
||||
nhw_IPC_regw_sideeffects_TASKS_SEND(i, task_nbr);
|
||||
}
|
||||
|
||||
void nrf_ipc_event_clear(NRF_IPC_Type * p_reg, nrf_ipc_event_t ipc_event)
|
||||
{
|
||||
*((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)ipc_event)) = 0x0UL;
|
||||
|
||||
int i = ipc_number_from_ptr(p_reg);
|
||||
nhw_IPC_regw_sideeffects_EVENTS_all(i);
|
||||
}
|
||||
|
||||
void nrf_ipc_int_enable(NRF_IPC_Type * p_reg, uint32_t mask)
|
||||
{
|
||||
p_reg->INTENSET = mask;
|
||||
|
||||
int i = ipc_number_from_ptr(p_reg);
|
||||
nhw_IPC_regw_sideeffects_INTENSET(i);
|
||||
}
|
||||
|
||||
void nrf_ipc_int_disable(NRF_IPC_Type * p_reg, uint32_t mask)
|
||||
{
|
||||
p_reg->INTENCLR = mask;
|
||||
|
||||
int i = ipc_number_from_ptr(p_reg);
|
||||
nhw_IPC_regw_sideeffects_INTENCLR(i);
|
||||
}
|
||||
|
||||
#if defined(DPPI_PRESENT)
|
||||
void nrf_ipc_subscribe_set(NRF_IPC_Type * p_reg,
|
||||
nrf_ipc_task_t task,
|
||||
uint8_t channel)
|
||||
{
|
||||
NRFX_ASSERT(p_reg);
|
||||
*((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) =
|
||||
((uint32_t)channel | NRF_SUBSCRIBE_PUBLISH_ENABLE);
|
||||
|
||||
int i = ipc_number_from_ptr(p_reg);
|
||||
int task_nbr = (task - NRF_IPC_TASK_SEND_0)/sizeof(uint32_t);
|
||||
|
||||
nhw_IPC_regw_sideeffects_SUBSCRIBE_SEND(i, task_nbr);
|
||||
}
|
||||
|
||||
void nrf_ipc_subscribe_clear(NRF_IPC_Type * p_reg,
|
||||
nrf_ipc_task_t task)
|
||||
{
|
||||
NRFX_ASSERT(p_reg);
|
||||
*((volatile uint32_t *) ((uint8_t *) p_reg + (uint32_t) task + 0x80uL)) = 0;
|
||||
|
||||
int i = ipc_number_from_ptr(p_reg);
|
||||
int task_nbr = (task - NRF_IPC_TASK_SEND_0)/sizeof(uint32_t);
|
||||
|
||||
nhw_IPC_regw_sideeffects_SUBSCRIBE_SEND(i, task_nbr);
|
||||
}
|
||||
#endif // defined(DPPI_PRESENT)
|
|
@ -155,8 +155,9 @@ extern NRF_RTC_Type NRF_RTC_regs[];
|
|||
#define NRF_RTC0_NS_BASE (&NRF_RTC_regs[NHW_RTC_NET0])
|
||||
#undef NRF_RTC1_NS_BASE
|
||||
#define NRF_RTC1_NS_BASE (&NRF_RTC_regs[NHW_RTC_NET1])
|
||||
extern NRF_IPC_Type NRF_IPC_regs[NHW_IPC_TOTAL_INST];
|
||||
#undef NRF_IPC_NS_BASE
|
||||
#define NRF_IPC_NS_BASE NULL
|
||||
#define NRF_IPC_NS_BASE (&NRF_IPC_regs[NHW_IPC_NET0])
|
||||
#undef NRF_SPIM0_NS_BASE
|
||||
#define NRF_SPIM0_NS_BASE NULL
|
||||
#undef NRF_SPIS0_NS_BASE
|
||||
|
@ -442,10 +443,11 @@ extern NRF_EGU_Type NRF_EGU_regs[];
|
|||
#define NRF_I2S0_NS_BASE NULL
|
||||
#undef NRF_I2S0_S_BASE
|
||||
#define NRF_I2S0_S_BASE NULL
|
||||
extern NRF_IPC_Type NRF_IPC_regs[NHW_IPC_TOTAL_INST];
|
||||
#undef NRF_IPC_NS_BASE
|
||||
#define NRF_IPC_NS_BASE NULL
|
||||
#define NRF_IPC_NS_BASE (&NRF_IPC_regs[NHW_IPC_APP0])
|
||||
#undef NRF_IPC_S_BASE
|
||||
#define NRF_IPC_S_BASE NULL
|
||||
#define NRF_IPC_S_BASE (&NRF_IPC_regs[NHW_IPC_APP0])
|
||||
#undef NRF_QSPI_NS_BASE
|
||||
#define NRF_QSPI_NS_BASE NULL
|
||||
#undef NRF_QSPI_S_BASE
|
||||
|
|
Loading…
Reference in New Issue