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:
Alberto Escolar Piedras 2023-10-06 16:28:17 +02:00
parent dacbaa0fa9
commit e84fca483b
10 changed files with 341 additions and 4 deletions

View File

@ -28,7 +28,7 @@ Notation:
| **GPIO** | General purpose input/output | &#x2714; | &#x10102; | For 52: See [NRF_GPIO.c](../src/HW_models/NRF_GPIO.c) |
| **GPIOTE** | GPIO tasks and events | &#x2705; | &#x10102; | For 52: Complete with very minor differences, see [NRF_GPIOTE.c](../src/HW_models/NRF_GPIOTE.c) |
| **I2S** | Inter-IC sound interface | &#x10102; | &#x10102; | |
| **IPC** | Interprocessor communication | &#x10102; | &#x10102; | |
| **IPC** | Interprocessor communication | N/A | &#x2714; | See [NHW_IPC.c](../src/HW_models/NHW_IPC.c) |
| **KMU** | Key management unit | &#x10102; | &#x10102; | |
| **LPCOMP** | Low-power comparator | &#x10102; | &#x10102; | |
| **MUTEX** | Mutual exclusive peripheral | N/A | &#x10102; | |

View File

@ -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

View File

@ -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

View File

@ -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

175
src/HW_models/NHW_IPC.c Normal file
View File

@ -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)

31
src/HW_models/NHW_IPC.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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 ================ */
/* =========================================================================================================================== */

76
src/nrfx/hal/nrf_ipc.c Normal file
View File

@ -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)

View File

@ -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