ci(hal): Extend support for ESP32-P4 for the PMS HAL test-app

This commit is contained in:
Laukik Hase
2026-02-25 17:54:36 +05:30
parent 3acb4a3e0c
commit 4c39f0d006
18 changed files with 1344 additions and 107 deletions

View File

@@ -5,11 +5,13 @@ set(srcs "src/common/test_intr_utils.c"
"src/common/test_panic_handler.c")
if(CONFIG_SOC_SUPPORT_TEE_SYS_APM_TEST)
list(APPEND srcs "src/common/test_apm_utils.c"
"src/common/test_setup_utils.c"
"src/pms/test_tee_vectors.S")
if(CONFIG_SOC_APM_CTRL_FILTER_SUPPORTED)
list(APPEND srcs "src/common/test_apm_utils.c"
"src/common/test_setup_utils.c"
"src/pms/test_tee_sys_apm.c"
"src/pms/test_tee_vectors.S")
list(APPEND srcs "src/pms/test_tee_sys_apm.c")
else()
list(APPEND srcs "src/pms/test_tee_pms.c")
endif()
endif()
@@ -27,7 +29,7 @@ idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include" "priv_include"
PRIV_INCLUDE_DIRS "priv_include/${target}"
REQUIRES ulp unity esp_hal_security
PRIV_REQUIRES esp_hal_timg
PRIV_REQUIRES esp_hal_timg esp_mm
LDFRAGMENTS linker.lf)
if(CONFIG_ULP_COPROC_ENABLED)

View File

@@ -1,10 +1,13 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc_caps.h"
/* Test-cases */
#if SOC_APM_CTRL_FILTER_SUPPORTED
void test_sys_apm_master_hp_cpu_slave_hp_peri(void);
void test_sys_apm_master_hp_cpu_slave_cpu_peri(void);
@@ -34,3 +37,20 @@ void test_peri_apm_master_lp_cpu_slave_hp_peri(void);
void test_peri_apm_master_lp_cpu_slave_lp_peri(void);
void test_tee_mode_default_access(void);
#else
void test_sys_pms_master_hp_cpu_slave_hp_peri(void);
void test_sys_pms_master_hp_cpu_slave_lp_peri(void);
void test_sys_pms_master_hp_cpu_peri_regn_access(void);
void test_sys_pms_master_lp_cpu_slave_hp_peri(void);
void test_sys_pms_master_lp_cpu_slave_lp_peri(void);
void test_sys_pms_master_lp_cpu_peri_regn_access(void);
void test_sys_pms_master_gdma_slave_hp_mem(void);
void test_sys_pms_master_gdma_slave_ext_mem(void);
#endif

View File

@@ -23,7 +23,7 @@
#define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 0
/********* GDMA APM master ID *********/
#define TEST_GDMA_APM_MASTER_ID 26 /* GDMA_DUMMY10 */
#define TEST_GDMA_APM_MASTER_ID 27 /* GDMA_DUMMY11 */
/********* APM controller and path definitions *********/
#define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM
@@ -202,8 +202,6 @@
/********* For PERI_APM *********/
#include "soc/reg_base.h"
/********* For PERI_APM *********/
#include "soc/uart_reg.h"
#include "soc/i2c_reg.h"
#include "soc/i2s_reg.h"

View File

@@ -21,7 +21,7 @@
#define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 1
/********* GDMA APM master ID *********/
#define TEST_GDMA_APM_MASTER_ID APM_MASTER_GDMA_GPSPI
#define TEST_GDMA_APM_MASTER_ID 27 /* GDMA_DUMMY11 */
/********* APM controller and path definitions *********/
#define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM

View File

@@ -23,7 +23,7 @@
#define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 0
/********* GDMA APM master ID *********/
#define TEST_GDMA_APM_MASTER_ID 26 /* GDMA_DUMMY10 */
#define TEST_GDMA_APM_MASTER_ID 27 /* GDMA_DUMMY11 */
/********* APM controller and path definitions *********/
#define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM

View File

@@ -21,7 +21,7 @@
#define SOC_APM_CTRL_TEE_MODE_ACCESS_BUG 1
/********* GDMA APM master ID *********/
#define TEST_GDMA_APM_MASTER_ID APM_MASTER_GDMA_GPSPI
#define TEST_GDMA_APM_MASTER_ID 27 /* GDMA_DUMMY11 */
/********* APM controller and path definitions *********/
#define HP_CPU_CPUPERI_APM_CTRL APM_CTRL_HP_APM

View File

@@ -0,0 +1,63 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "hal/apm_types.h"
#include "soc/apm_defs.h"
#define ALIGN_TO_NEXT_4KB(addr) (((addr) + 0x1000) & ~0xFFF)
/********* For DMA_PMS *********/
#define GDMA_HPMEM_TEST_REGN_NUM APM_DMA_PMS_REGION_NUM
#define GDMA_HPMEM_TEST_REGN_SIZE APM_DMA_PMS_REGION_ADDR_ALIGN
/* Reserved regions for HPMEM test: [0] pre-buf, [1] post-buf */
#define GDMA_HPMEM_TEST_REGN_RESV_NUM 2
#define GDMA_EXTMEM_TEST_REGN_NUM APM_DMA_PMS_REGION_NUM
#define GDMA_EXTMEM_TEST_REGN_SIZE APM_DMA_PMS_REGION_ADDR_ALIGN
/* Reserved regions for EXTMEM test: [0] pre-buf, [1] post-buf, [2] full HP-mem
* TODO: Investigate why [2] is required for EXT_MEM case
*/
#define GDMA_EXTMEM_TEST_REGN_RESV_NUM 3
/********* For HP_PERI_PMS *********/
#include "soc/timer_group_reg.h"
#include "soc/i2c_reg.h"
#include "soc/i2s_reg.h"
#include "soc/pcnt_reg.h"
#include "soc/uart_reg.h"
#include "soc/spi_reg.h"
#include "soc/ledc_reg.h"
#include "soc/adc_reg.h"
#include "soc/parl_io_reg.h"
#include "soc/rmt_reg.h"
#include "soc/gpio_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/cache_reg.h"
#include "soc/hp_system_reg.h"
#include "soc/bitscrambler_reg.h"
#include "soc/trace_reg.h"
#include "soc/sha_reg.h"
#include "soc/assist_debug_reg.h"
#include "soc/parl_io_reg.h"
#include "soc/io_mux_reg.h"
/********* For HP2LP_PERI_PMS *********/
#include "soc/lp_timer_reg.h"
#include "soc/lp_analog_peri_reg.h"
#include "soc/pmu_reg.h"
#include "soc/lp_wdt_reg.h"
#include "soc/lp_uart_reg.h"
#include "soc/lp_i2c_reg.h"
#include "soc/lp_i2c_ana_mst_reg.h"
#include "soc/huk_reg.h"
#include "soc/efuse_reg.h"
#include "soc/lp_iomux_reg.h"
#include "soc/trng_reg.h"

View File

@@ -18,6 +18,7 @@
#include "soc/lp_system_reg.h"
#define LP_STORE_REG_PREFIX(reg) LP_SYSTEM_REG_LP_STORE##reg##_REG
#endif
#include "hal/apm_types.h"
/********* Panic Handler *********/
@@ -35,8 +36,8 @@
#define SEND_ADDR(addr) REG_WRITE(LP_STORE_REG_PREFIX(7), addr)
#define RECV_ADDR() REG_READ(LP_STORE_REG_PREFIX(7))
#define SEND_SIZE(size) REG_WRITE(LP_STORE_REG_PREFIX(8), size)
#define RECV_SIZE() REG_READ(LP_STORE_REG_PREFIX(8))
#define SEND_DATA(data) REG_WRITE(LP_STORE_REG_PREFIX(8), data)
#define RECV_DATA() REG_READ(LP_STORE_REG_PREFIX(8))
#define SEND_EXCP(val) REG_WRITE(LP_STORE_REG_PREFIX(9), val)
#define RECV_EXCP() REG_READ(LP_STORE_REG_PREFIX(9))
@@ -57,35 +58,12 @@
#endif
#if SOC_APM_CTRL_FILTER_SUPPORTED
typedef struct {
apm_master_id_t master_id;
apm_ctrl_module_t ctrl_mod;
const uint32_t *test_addr;
uint32_t test_addr_num;
uint32_t test_addr_resv_mask;
} test_sys_apm_periph_cfg_t;
typedef struct {
apm_master_id_t master_id;
apm_ctrl_module_t ctrl_mod;
apm_ctrl_access_path_t path;
uint32_t mem_start_addr;
uint32_t mem_end_addr;
uint32_t regn_count;
uint32_t regn_sz;
} test_sys_apm_mem_cfg_t;
typedef struct {
apm_master_id_t master_id;
apm_tee_ctrl_module_t ctrl_mod;
const uint32_t *test_reg;
uint32_t test_reg_num;
uint64_t test_reg_resv_mask;
} test_peri_apm_periph_cfg_t;
void apm_hal_enable_region_filter_all(apm_ctrl_module_t ctrl_mod, bool enable);
void test_apm_ctrl_reset_all(void);
void test_apm_ctrl_enable_intr(apm_ctrl_module_t ctrl_mod, apm_ctrl_access_path_t path);
#else
void test_pms_ctrl_reset_all(void);
void test_pms_enable_intr(apm_ctrl_module_t ctrl_mod);
#endif
/* Utility functions */
@@ -97,7 +75,9 @@ void test_u2m_switch(void);
void test_boot_lp_cpu(void);
void test_stop_lp_cpu(void);
void test_reset_lp_cpu(void);
#if SOC_LP_AON_SUPPORTED
void test_switch_lp_mem_speed(bool high_speed);
#endif
void test_gdma_init(void);
void test_gdma_deinit(void);

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -11,6 +11,11 @@
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "soc/interrupts.h"
#if SOC_CPU_CORES_NUM > 1
#include "soc/interrupt_core0_reg.h"
#else
#include "soc/interrupt_matrix_reg.h"
#endif
#include "soc/apm_defs.h"
#include "hal/apm_hal.h"
@@ -22,6 +27,7 @@
#include "unity.h"
#if SOC_APM_CTRL_FILTER_SUPPORTED
/***************************** Utility - APM interrupts *****************************/
#define MAX_APM_CTRL_NUM (4)
@@ -213,7 +219,7 @@ static const char *const excp_mid_strs[] = {
#if SOC_PARLIO_SUPPORTED
[APM_MASTER_GDMA_PARLIO] = "GDMA_PARLIO",
#endif /* SOC_PARLIO_SUPPORTED */
[26] = "GDMA_DUMMYX",
[27] = "GDMA_DUMMYX",
};
static const char *apm_excp_mid_to_str(uint8_t mid)
@@ -368,3 +374,232 @@ static void test_apm_ctrl_free_all_intr(void)
}
}
}
#elif SOC_APM_SUPPORTED
/***************************** Utility - PMS interrupts *****************************/
#include "soc/icm_sys_reg.h"
#include "hal/lp_sys_ll.h"
#include "test_pms_params.h"
static intr_handle_t s_pms_hp_intr_hdl = NULL;
static intr_handle_t s_pms_lp_intr_hdl = NULL;
volatile bool pms_lp_excp_flag = false;
volatile uint32_t pms_lp_excp_addr = 0;
volatile bool pms_dma_excp_flag = false;
/***************************** PMS exception check *****************************/
static const char *apm_excp_type_to_str(bool is_secure)
{
char *excp_type = "Unknown";
if (is_secure) {
excp_type = "Space exception";
} else {
excp_type = "Authority exception";
}
return excp_type;
}
static const char *apm_excp_src_to_str(apm_ctrl_exception_type type)
{
char *excp_src = "Unknown";
switch (type) {
case APM_EXCP_HP_AXI:
excp_src = "HP_AXI";
break;
case APM_EXCP_HP_AHB:
excp_src = "HP_AHB";
break;
case APM_EXCP_LP_AHB:
excp_src = "LP_AHB";
break;
case APM_EXCP_LP_IDBUS:
excp_src = "LP_IDBUS";
break;
default:
break;
}
return excp_src;
}
IRAM_ATTR static void pms_log_violation(apm_ctrl_exception_type type, apm_ctrl_exception_info_t *info)
{
apm_hal_get_exception_info(type, info);
esp_rom_printf("PMS violation: %s\n\r", apm_excp_type_to_str(info->is_secure));
esp_rom_printf("Access addr: 0x%08x | Type: %s\n\r", info->addr, info->is_wr ? "Write" : "Read");
esp_rom_printf("Master: %d | Source: %s\n\r", info->id, apm_excp_src_to_str(type));
}
IRAM_ATTR static void pms_hp_intr_cb(void *arg)
{
apm_ctrl_exception_info_t info;
uint32_t status = apm_hal_get_intr_status();
if (status & APM_EXCP_HP_AXI) {
pms_log_violation(APM_EXCP_HP_AXI, &info);
}
if (status & APM_EXCP_HP_AHB) {
pms_log_violation(APM_EXCP_HP_AHB, &info);
pms_dma_excp_flag = true;
}
apm_hal_clear_intr(APM_CTRL_DMA_PMS);
apm_hal_clear_intr(APM_CTRL_HP_PERI_PMS);
apm_hal_clear_intr(APM_CTRL_LP2HP_PERI_PMS);
}
IRAM_ATTR static void pms_lp_intr_cb(void *arg)
{
apm_ctrl_exception_info_t info;
uint32_t status = apm_hal_get_intr_status();
if (status & APM_EXCP_LP_AHB) {
pms_log_violation(APM_EXCP_LP_AHB, &info);
pms_lp_excp_addr = info.addr;
pms_lp_excp_flag = true;
}
if (status & APM_EXCP_LP_IDBUS) {
pms_log_violation(APM_EXCP_LP_IDBUS, &info);
pms_lp_excp_addr = info.addr;
pms_lp_excp_flag = true;
}
apm_hal_clear_intr(APM_CTRL_HP2LP_PERI_PMS);
apm_hal_clear_intr(APM_CTRL_LP_PERI_PMS);
}
void test_pms_enable_intr(apm_ctrl_module_t ctrl_mod)
{
/* TODO: Investigate why this is required */
REG_CLR_BIT(ICM_INT_ENA_REG, ICM_REG_DLOCK_INT_ENA);
int intr_src = apm_hal_get_intr_src_num(ctrl_mod);
TEST_ASSERT(intr_src >= 0);
uint32_t flags = ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL3;
switch (ctrl_mod) {
case APM_CTRL_DMA_PMS:
case APM_CTRL_HP_PERI_PMS:
case APM_CTRL_LP2HP_PERI_PMS:
if (!s_pms_hp_intr_hdl) {
TEST_ESP_OK(esp_intr_alloc(intr_src, flags, &pms_hp_intr_cb, NULL, &s_pms_hp_intr_hdl));
}
break;
case APM_CTRL_LP_PERI_PMS:
case APM_CTRL_HP2LP_PERI_PMS:
if (!s_pms_lp_intr_hdl) {
TEST_ESP_OK(esp_intr_alloc(intr_src, flags, &pms_lp_intr_cb, NULL, &s_pms_lp_intr_hdl));
}
break;
default:
TEST_ASSERT_MESSAGE(false, "Invalid PMS module");
return;
}
apm_hal_enable_intr(ctrl_mod, true);
}
static void test_pms_free_all_intr(void)
{
if (s_pms_hp_intr_hdl) {
esp_intr_free(s_pms_hp_intr_hdl);
s_pms_hp_intr_hdl = NULL;
}
if (s_pms_lp_intr_hdl) {
esp_intr_free(s_pms_lp_intr_hdl);
s_pms_lp_intr_hdl = NULL;
}
}
/********************************** PMS Reset *************************************/
static void test_dma_pms_reset(void)
{
for (uint32_t regn = 0; regn < APM_DMA_PMS_REGION_NUM; regn++) {
apm_hal_dma_pms_set_region_bounds(regn, 0x00U, UINT32_MAX);
}
for (uint32_t mid = 0; mid < APM_MASTER_DMA_MAX; mid++) {
apm_hal_dma_pms_set_master_region_attr((apm_master_dma_id_t)mid, UINT32_MAX, UINT32_MAX);
}
apm_hal_enable_intr(APM_CTRL_DMA_PMS, false);
apm_hal_clear_intr(APM_CTRL_DMA_PMS);
}
static void test_hp_peri_pms_reset(void)
{
const apm_hal_pms_hp_peri_cfg_t cfg = {
.cpu_peri = UINT32_MAX,
.hp_peri0 = UINT32_MAX,
.hp_peri1 = UINT64_MAX,
};
for (int core = 0; core < SOC_CPU_CORES_NUM; core++) {
apm_hal_hp_peri_pms_set_hpcpu_access(core, APM_SEC_MODE_TEE, &cfg);
apm_hal_hp_peri_pms_set_hpcpu_access(core, APM_SEC_MODE_REE, &cfg);
}
apm_hal_enable_intr(APM_CTRL_HP_PERI_PMS, false);
apm_hal_clear_intr(APM_CTRL_HP_PERI_PMS);
}
static void test_hp2lp_peri_pms_reset(void)
{
uint32_t cfg_mask = UINT32_MAX;
for (int core = 0; core < SOC_CPU_CORES_NUM; core++) {
apm_hal_hp2lp_peri_pms_set_hpcpu_access(core, APM_SEC_MODE_TEE, cfg_mask);
apm_hal_hp2lp_peri_pms_set_hpcpu_access(core, APM_SEC_MODE_REE, cfg_mask);
}
apm_hal_enable_intr(APM_CTRL_HP2LP_PERI_PMS, false);
apm_hal_clear_intr(APM_CTRL_HP2LP_PERI_PMS);
}
static void test_lp_peri_pms_reset(void)
{
uint32_t cfg_mask = UINT32_MAX;
apm_hal_lp_peri_pms_set_lpcpu_access(cfg_mask);
for (uint32_t regn = 0; regn < APM_LP_PERI_PMS_REGION_NUM; regn++) {
apm_hal_lp_peri_pms_set_region_bounds(regn, 0x00U, UINT32_MAX);
}
for (uint32_t mid = 0; mid < APM_MASTER_DMA; mid++) {
apm_hal_lp_peri_pms_set_master_region_attr(mid, APM_SEC_MODE_TEE, UINT32_MAX);
apm_hal_lp_peri_pms_set_master_region_attr(mid, APM_SEC_MODE_REE, UINT32_MAX);
}
apm_hal_enable_intr(APM_CTRL_LP_PERI_PMS, false);
apm_hal_clear_intr(APM_CTRL_LP_PERI_PMS);
}
static void test_lp2hp_peri_pms_reset(void)
{
const apm_hal_pms_hp_peri_cfg_t cfg = {
.cpu_peri = UINT32_MAX,
.hp_peri0 = UINT32_MAX,
.hp_peri1 = UINT64_MAX,
};
apm_hal_lp2hp_peri_pms_set_lpcpu_access(&cfg);
apm_hal_enable_intr(APM_CTRL_LP2HP_PERI_PMS, false);
apm_hal_clear_intr(APM_CTRL_LP2HP_PERI_PMS);
lp_sys_ll_enable_lp_core_err_resp(true);
}
void test_pms_ctrl_reset_all(void)
{
test_dma_pms_reset();
test_hp_peri_pms_reset();
test_hp2lp_peri_pms_reset();
test_lp_peri_pms_reset();
test_lp2hp_peri_pms_reset();
test_pms_free_all_intr();
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -61,11 +61,18 @@ void test_panicHandler(RvExcFrame *frame, int exccause)
}
return;
}
/* PERI_APM access fault */
#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL
#if SOC_APM_SUPPORT_TEE_PERI_ACCESS_CTRL || !SOC_APM_CTRL_FILTER_SUPPORTED
#if CONFIG_IDF_TARGET_ESP32P4
if ((regs->mtval >= CPU_PERIPH_LOW && regs->mtval < CPU_PERIPH_HIGH) ||
(regs->mtval >= SOC_PERIPHERAL_LOW && regs->mtval < SOC_PERIPHERAL_HIGH) ||
(regs->mtval >= SOC_LP_PERIPH_LOW && regs->mtval < SOC_LP_PERIPH_HIGH)) {
#else
if (regs->mtval >= SOC_PERIPHERAL_LOW && regs->mtval < SOC_PERIPHERAL_HIGH) {
#endif
if (mcause == MCAUSE_LOAD_ACCESS_FAULT || mcause == MCAUSE_STORE_ACCESS_FAULT) {
panic_print("[PERI_APM] %s at 0x%08x\n\r", rsn, regs->mtval);
panic_print("[PERI_ACC] %s at 0x%08x (%s)\n\r", rsn, regs->mtval, (regs->mstatus & MSTATUS_MPP) ? "M-mode" : "U-mode");
frame->mepc += 0x04U;
RV_WRITE_CSR(uscratch, regs->mtval);
return;

View File

@@ -13,18 +13,27 @@
#include "hal/gdma_ll.h"
#include "hal/gdma_types.h"
#if SOC_AHB_GDMA_VERSION == 2
#include "hal/ahb_dma_ll.h"
#include "soc/ahb_dma_struct.h"
#elif SOC_AHB_GDMA_VERSION == 1
#include "soc/gdma_struct.h"
#endif
#include "esp_private/periph_ctrl.h"
#if CONFIG_ULP_COPROC_ENABLED
#include "soc/lp_aon_reg.h"
#include "soc/lpperi_reg.h"
#if SOC_LP_AON_SUPPORTED
#include "soc/lp_aon_reg.h"
#define LP_CPU_RST_EN (LPPERI_LP_CPU_RESET_EN)
#else
#include "soc/lp_system_reg.h"
#define LP_CPU_RST_EN (LPPERI_RST_EN_LP_CORE)
#endif
#include "ulp_lp_core.h"
#endif
#include "esp_attr.h"
#include "esp_cache.h"
#include "esp_rom_lldesc.h"
#include "esp_rom_sys.h"
@@ -61,9 +70,11 @@ void test_stop_lp_cpu(void)
void test_reset_lp_cpu(void)
{
REG_SET_BIT(LPPERI_RESET_EN_REG, LPPERI_LP_CPU_RESET_EN);
REG_SET_BIT(LPPERI_RESET_EN_REG, LP_CPU_RST_EN);
REG_CLR_BIT(LPPERI_RESET_EN_REG, LP_CPU_RST_EN);
}
#if SOC_LP_AON_SUPPORTED
void test_switch_lp_mem_speed(bool high_speed)
{
if (high_speed) {
@@ -74,6 +85,7 @@ void test_switch_lp_mem_speed(bool high_speed)
REG_SET_BIT(LP_AON_LPBUS_REG, LP_AON_FAST_MEM_MUX_SEL_UPDATE);
}
#endif
#endif
/***************************** Utility - GDMA *****************************/
@@ -87,15 +99,21 @@ void test_switch_lp_mem_speed(bool high_speed)
#define DMA_MEM_TRANS_EN_FIELD mem_trans_en
#endif
#if SOC_RCC_IS_INDEPENDENT
#define GDMA_RCC_ATOMIC()
#else /* !SOC_RCC_IS_INDEPENDENT */
#define GDMA_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
#endif /* SOC_RCC_IS_INDEPENDENT */
#define dma_ll_force_enable_reg_clock DMA_LL_FUNC(force_enable_reg_clock)
#define dma_ll_tx_enable_data_burst DMA_LL_FUNC(tx_enable_data_burst)
#define dma_ll_tx_enable_descriptor_burst DMA_LL_FUNC(tx_enable_descriptor_burst)
#define dma_ll_rx_enable_data_burst DMA_LL_FUNC(rx_enable_data_burst)
#define dma_ll_rx_enable_descriptor_burst DMA_LL_FUNC(rx_enable_descriptor_burst)
#define dma_ll_tx_reset_channel DMA_LL_FUNC(tx_reset_channel)
#define dma_ll_tx_connect_to_periph DMA_LL_FUNC(tx_connect_to_periph)
#define dma_ll_tx_connect_to_mem DMA_LL_FUNC(tx_connect_to_mem)
#define dma_ll_rx_reset_channel DMA_LL_FUNC(rx_reset_channel)
#define dma_ll_rx_connect_to_periph DMA_LL_FUNC(rx_connect_to_periph)
#define dma_ll_rx_connect_to_mem DMA_LL_FUNC(rx_connect_to_mem)
#define dma_ll_tx_disconnect_all DMA_LL_FUNC(tx_disconnect_all)
#define dma_ll_rx_disconnect_all DMA_LL_FUNC(rx_disconnect_all)
#define dma_ll_tx_set_desc_addr DMA_LL_FUNC(tx_set_desc_addr)
@@ -113,10 +131,13 @@ void test_switch_lp_mem_speed(bool high_speed)
#define dma_ll_tx_get_interrupt_status DMA_LL_FUNC(tx_get_interrupt_status)
#define dma_ll_rx_get_interrupt_status DMA_LL_FUNC(rx_get_interrupt_status)
#define TEST_DMA_CHN_NUM 0
#define TEST_DMA_GRP_NUM 0
#define TEST_DMA_CHN_NUM 1
#define TEST_DMA_BLK_LEN 1024
#define TEST_DMA_MAX_BLK_NUM 32
#define SOC_GDMA_TRIG_PERIPH_DUMMY (11)
DRAM_ATTR static lldesc_t tx_link[TEST_DMA_MAX_BLK_NUM];
DRAM_ATTR static lldesc_t rx_link[TEST_DMA_MAX_BLK_NUM];
@@ -146,6 +167,11 @@ static void setup_gdma_link(lldesc_t *link, uint8_t *buf, size_t size, bool is_t
link[x - 1].empty = 0;
}
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
size_t num_desc = (size + TEST_DMA_BLK_LEN - 1) / TEST_DMA_BLK_LEN;
esp_cache_msync(&link[0], num_desc * sizeof(lldesc_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
#endif
if (is_tx) {
dma_ll_tx_set_desc_addr(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, (uint32_t)&link[0]);
} else {
@@ -155,8 +181,10 @@ static void setup_gdma_link(lldesc_t *link, uint8_t *buf, size_t size, bool is_t
void test_gdma_init(void)
{
gdma_ll_enable_bus_clock(TEST_DMA_CHN_NUM, true);
gdma_ll_reset_register(TEST_DMA_CHN_NUM);
GDMA_RCC_ATOMIC() {
gdma_ll_enable_bus_clock(TEST_DMA_GRP_NUM, true);
gdma_ll_reset_register(TEST_DMA_GRP_NUM);
}
dma_ll_force_enable_reg_clock(&TEST_DMA_DEV, true);
#if SOC_AHB_GDMA_VERSION == 2
@@ -181,9 +209,8 @@ void test_gdma_init(void)
dma_ll_tx_set_priority(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, 1);
dma_ll_rx_set_priority(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, 1);
dma_ll_tx_connect_to_periph(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, SOC_GDMA_TRIG_PERIPH_SPI2);
dma_ll_rx_connect_to_periph(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, SOC_GDMA_TRIG_PERIPH_SPI2);
TEST_DMA_DEV.channel[TEST_DMA_CHN_NUM].in.in_conf0.DMA_MEM_TRANS_EN_FIELD = 1;
dma_ll_tx_connect_to_mem(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, SOC_GDMA_TRIG_PERIPH_DUMMY);
dma_ll_rx_connect_to_mem(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, SOC_GDMA_TRIG_PERIPH_DUMMY);
dma_ll_tx_enable_interrupt(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, GDMA_LL_EVENT_TX_EOF, true);
dma_ll_rx_enable_interrupt(&TEST_DMA_DEV, TEST_DMA_CHN_NUM, GDMA_LL_EVENT_RX_SUC_EOF, true);
@@ -200,8 +227,10 @@ void test_gdma_deinit(void)
dma_ll_tx_reset_channel(&TEST_DMA_DEV, TEST_DMA_CHN_NUM);
dma_ll_rx_reset_channel(&TEST_DMA_DEV, TEST_DMA_CHN_NUM);
gdma_ll_reset_register(TEST_DMA_CHN_NUM);
gdma_ll_enable_bus_clock(TEST_DMA_CHN_NUM, false);
GDMA_RCC_ATOMIC() {
gdma_ll_reset_register(TEST_DMA_GRP_NUM);
gdma_ll_enable_bus_clock(TEST_DMA_GRP_NUM, false);
}
}
void test_gdma_m2m_transfer(uint8_t *src, uint8_t *dest, size_t size)

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -27,6 +27,14 @@
/***************************** PERI_APM *****************************/
typedef struct {
apm_master_id_t master_id;
apm_tee_ctrl_module_t ctrl_mod;
const uint32_t *test_reg;
uint32_t test_reg_num;
uint64_t test_reg_resv_mask;
} test_peri_apm_periph_cfg_t;
static const uint32_t test_peri_apm_hp_peri_reg[] = {
[APM_TEE_HP_PERIPH_UART1] = UART_DATE_REG(1),
[APM_TEE_HP_PERIPH_I2C_EXT0] = I2C_DATE_REG(0),
@@ -130,30 +138,35 @@ IRAM_ATTR static void hp_cpu_peri_addr_rw(uint32_t peri_addr, uint32_t attr)
IRAM_ATTR static void lp_cpu_peri_addr_rw(uint32_t peri_addr, uint32_t attr)
{
test_reset_lp_cpu();
SEND_MSG(MSG_SLAVE_CLEAR);
test_delay_ms(5);
SEND_EXCP(0);
SEND_MSG(MSG_SLAVE_WRITE);
SEND_ADDR(peri_addr);
SEND_DATA(TEST_VAL);
SEND_MSG(MSG_SLAVE_WRITE);
test_delay_ms(10);
bool can_write = (attr & APM_PERM_W);
if (!can_write) {
TEST_ASSERT(RECV_EXCP() == MCAUSE_STORE_ACCESS_FAULT);
TEST_ASSERT_EQUAL_HEX32(peri_addr, RECV_ADDR());
esp_rom_printf("[PERI_APM] Store access fault at 0x%08x\n", peri_addr);
esp_rom_printf("[PERI_ACC] Store access fault at 0x%08x\n", peri_addr);
}
SEND_MSG(MSG_SLAVE_CLEAR);
test_delay_ms(5);
SEND_EXCP(0);
SEND_MSG(MSG_SLAVE_READ);
SEND_ADDR(peri_addr);
SEND_MSG(MSG_SLAVE_READ);
test_delay_ms(10);
bool can_read = (attr & APM_PERM_R);
if (!can_read) {
TEST_ASSERT(RECV_EXCP() == MCAUSE_LOAD_ACCESS_FAULT);
TEST_ASSERT_EQUAL_HEX32(peri_addr, RECV_ADDR());
esp_rom_printf("[PERI_APM] Load access fault at 0x%08x\n", peri_addr);
esp_rom_printf("[PERI_ACC] Load access fault at 0x%08x\n", peri_addr);
}
SEND_EXCP(0);

View File

@@ -0,0 +1,740 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <string.h>
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "soc/apm_defs.h"
#include "hal/apm_hal.h"
#include "hal/apm_ll.h"
#include "hal/apm_types.h"
#include "esp_attr.h"
#include "esp_cpu.h"
#include "esp_rom_sys.h"
#include "riscv/csr.h"
#include "riscv/rv_utils.h"
#include "test_pms_priv.h"
#include "test_pms_params.h"
#include "esp_cache.h"
#include "esp_heap_caps.h"
#include "esp_memory_utils.h"
#include "unity.h"
#define TEST_VAL 0x0FACADE0
extern volatile bool pms_lp_excp_flag;
extern volatile uint32_t pms_lp_excp_addr;
extern volatile bool pms_dma_excp_flag;
/***************************** HP/HP2LP PERI_PMS & LP/LP2HP PERI_PMS *****************************/
typedef enum {
HP_PERI0,
HP_PERI1,
CPU_PERI,
LP_PERI
} test_pms_peri_grp_t;
typedef struct {
apm_master_id_t master_id;
apm_ctrl_module_t ctrl_mod;
const uint32_t *test_reg;
uint32_t test_reg_num;
test_pms_peri_grp_t test_peri_grp;
} test_pms_periph_cfg_t;
static const uint32_t test_cpu_peri_reg[] = {
[APM_SLAVE_TRACE0] = TRACE_DATE_REG(0),
[APM_SLAVE_TRACE1] = TRACE_DATE_REG(1),
[APM_SLAVE_CACHE] = CACHE_DATE_REG,
};
static const uint32_t test_hp_peri0_reg[] = {
[APM_SLAVE_HP_CRYPTO] = SHA_DATE_REG,
[APM_SLAVE_HP_RMT] = RMT_DATE_REG,
[APM_SLAVE_HP_BITSCRAMBLER] = BITSCRAMBLER_VERSION_REG,
};
static const uint32_t test_hp_peri1_reg[] = {
[APM_SLAVE_HP_TG0] = TIMG_NTIMERS_DATE_REG(0),
[APM_SLAVE_HP_I2C0] = I2C_DATE_REG(0),
[APM_SLAVE_HP_I2S0] = I2S_DATE_REG(0),
[APM_SLAVE_HP_PCNT] = PCNT_DATE_REG,
[APM_SLAVE_HP_UART2] = UART_DATE_REG(2),
[APM_SLAVE_HP_PARLIO] = PARL_IO_VERSION_REG,
[APM_SLAVE_HP_GPSPI2] = SPI_DATE_REG(2),
[APM_SLAVE_HP_LEDC] = LEDC_DATE_REG,
[APM_SLAVE_HP_ADC] = ADC_CTRL_DATE_REG,
[APM_SLAVE_HP_GPIO] = GPIO_DATE_REG,
[APM_SLAVE_HP_IOMUX] = IO_MUX_DATE_REG,
[APM_SLAVE_HP_SYS_REG] = HP_SYSTEM_VER_DATE_REG,
};
static const uint32_t test_lp_peri_reg[] = {
[APM_SLAVE_LP_TIMER] = LP_TIMER_DATE_REG,
[APM_SLAVE_LP_ANAPERI] = LP_ANALOG_PERI_DATE_REG,
[APM_SLAVE_LP_WDT] = LP_WDT_DATE_REG,
[APM_SLAVE_LP_UART] = LP_UART_ID_REG,
[APM_SLAVE_LP_I2C] = LP_I2C_DATE_REG,
[APM_SLAVE_LP_I2CMST] = LP_I2C_ANA_MST_DATE_REG,
[APM_SLAVE_LP_IOMUX] = LP_IOMUX_VER_DATE_REG,
[APM_SLAVE_LP_HUK] = HUK_DATE_REG,
[APM_SLAVE_LP_TRNG] = RNG_DATE_REG,
};
FORCE_INLINE_ATTR uint32_t reg_read(uint32_t addr)
{
uint32_t value;
__asm__ volatile(
"lw %0, 0(%1)\n"
"fence\n"
"nop\nnop\nnop\nnop\n"
: "=r"(value)
: "r"(addr)
: "memory"
);
return value;
}
FORCE_INLINE_ATTR void reg_write(uint32_t addr, uint32_t value)
{
__asm__ volatile(
"sw %1, 0(%0)\n"
"fence\n"
"nop\nnop\nnop\nnop\n"
:
: "r"(addr), "r"(value)
: "memory"
);
}
IRAM_ATTR static void hp_cpu_peri_addr_rw(uint32_t peri_addr, bool should_panic)
{
RV_WRITE_CSR(uscratch, 0x00);
reg_write(peri_addr, TEST_VAL);
test_delay_ms(10);
if (should_panic) {
TEST_ASSERT_EQUAL_HEX32(peri_addr, RV_READ_CSR(uscratch));
} else {
TEST_ASSERT_EQUAL_HEX32(0x00, RV_READ_CSR(uscratch));
}
RV_WRITE_CSR(uscratch, 0x00);
volatile uint32_t val = reg_read(peri_addr);
(void)val;
test_delay_ms(10);
if (should_panic) {
TEST_ASSERT_EQUAL_HEX32(peri_addr, RV_READ_CSR(uscratch));
} else {
TEST_ASSERT_EQUAL_HEX32(0x00, RV_READ_CSR(uscratch));
}
RV_WRITE_CSR(uscratch, 0x00);
}
#if CONFIG_ULP_COPROC_ENABLED
IRAM_ATTR static void lp_cpu_peri_addr_rw(uint32_t peri_addr, bool should_panic)
{
bool is_lp_peri = (peri_addr >= SOC_LP_PERIPH_LOW && peri_addr < SOC_LP_PERIPH_HIGH);
SEND_MSG(MSG_SLAVE_CLEAR);
test_delay_ms(5);
if (is_lp_peri) {
pms_lp_excp_flag = false;
pms_lp_excp_addr = UINT32_MAX;
} else {
SEND_EXCP(0);
}
SEND_ADDR(peri_addr);
SEND_DATA(TEST_VAL);
SEND_MSG(MSG_SLAVE_WRITE);
test_delay_ms(10);
if (should_panic) {
if (is_lp_peri) {
TEST_ASSERT_TRUE(pms_lp_excp_flag);
TEST_ASSERT_EQUAL_HEX32(peri_addr, pms_lp_excp_addr);
} else {
TEST_ASSERT(RECV_EXCP() == MCAUSE_STORE_ACCESS_FAULT);
TEST_ASSERT_EQUAL_HEX32(peri_addr, RECV_ADDR());
esp_rom_printf("[PERI_ACC] Store access fault at 0x%08x\n", peri_addr);
}
} else {
if (is_lp_peri) {
TEST_ASSERT_FALSE(pms_lp_excp_flag);
} else {
TEST_ASSERT(RECV_EXCP() == 0);
}
}
SEND_MSG(MSG_SLAVE_CLEAR);
test_delay_ms(5);
if (is_lp_peri) {
pms_lp_excp_flag = false;
pms_lp_excp_addr = UINT32_MAX;
} else {
SEND_EXCP(0);
}
SEND_ADDR(peri_addr);
SEND_MSG(MSG_SLAVE_READ);
test_delay_ms(10);
if (should_panic) {
if (is_lp_peri) {
TEST_ASSERT_TRUE(pms_lp_excp_flag);
TEST_ASSERT_EQUAL_HEX32(peri_addr, pms_lp_excp_addr);
} else {
TEST_ASSERT(RECV_EXCP() == MCAUSE_LOAD_ACCESS_FAULT);
TEST_ASSERT_EQUAL_HEX32(peri_addr, RECV_ADDR());
esp_rom_printf("[PERI_ACC] Load access fault at 0x%08x\n", peri_addr);
}
} else {
if (is_lp_peri) {
TEST_ASSERT_FALSE(pms_lp_excp_flag);
} else {
TEST_ASSERT(RECV_EXCP() == 0);
}
}
}
#endif
IRAM_ATTR static void switch_priv_mode(void)
{
int mode = esp_cpu_get_curr_privilege_level();
if (mode == PRV_M) {
rv_utils_intr_global_disable();
test_m2u_switch();
} else {
test_u2m_switch();
rv_utils_intr_global_enable();
}
}
static const apm_hal_pms_regn_cfg_t test_hp_peri_regn_cfg[] = {
/* cpu_peri */
APM_HAL_PMS_REGION_ENTRY(0, REG_TRACE_BASE(0), REG_TRACE_BASE(1)),
APM_HAL_PMS_REGION_ENTRY(1, DR_REG_CACHE_BASE, ALIGN_TO_NEXT_4KB(DR_REG_CACHE_BASE)),
/* hp_peri */
APM_HAL_PMS_REGION_ENTRY(2, DR_REG_SHA_BASE, DR_REG_RSA_BASE),
APM_HAL_PMS_REGION_ENTRY(3, DR_REG_RMT_BASE, DR_REG_BITSCRAMBLER_BASE),
APM_HAL_PMS_REGION_ENTRY(4, DR_REG_PCNT_BASE, DR_REG_UART0_BASE),
APM_HAL_PMS_REGION_ENTRY(5, DR_REG_PARIO_BASE, DR_REG_SPI2_BASE),
APM_HAL_PMS_REGION_ENTRY(6, DR_REG_GPIO_BASE, DR_REG_IO_MUX_BASE),
APM_HAL_PMS_REGION_ENTRY(7, DR_REG_IO_MUX_BASE, DR_REG_SYSTIMER_BASE),
};
static const uint32_t test_hp_peri_regn_addr[] = {
TRACE_DATE_REG(0), CACHE_DATE_REG, SHA_DATE_REG, RMT_DATE_REG,
PCNT_DATE_REG, PARL_IO_VERSION_REG, GPIO_DATE_REG, IO_MUX_DATE_REG,
};
static const apm_hal_pms_regn_cfg_t test_lp_peri_regn_cfg[] = {
/* lp_peri */
APM_HAL_PMS_REGION_ENTRY(0, DR_REG_LP_TIMER_BASE, DR_REG_LP_ANALOG_PERI_BASE),
APM_HAL_PMS_REGION_ENTRY(1, DR_REG_LP_ANALOG_PERI_BASE, DR_REG_LP_HUK_BASE),
APM_HAL_PMS_REGION_ENTRY(2, DR_REG_LP_HUK_BASE, DR_REG_PMU_BASE),
APM_HAL_PMS_REGION_ENTRY(3, DR_REG_LP_WDT_BASE, DR_REG_LP_MB_BASE),
APM_HAL_PMS_REGION_ENTRY(4, DR_REG_LP_UART_BASE, DR_REG_LP_I2C_BASE),
APM_HAL_PMS_REGION_ENTRY(5, DR_REG_LP_I2C_BASE, DR_REG_LP_SPI_BASE),
APM_HAL_PMS_REGION_ENTRY(6, DR_REG_LP_I2C_ANA_MST_BASE, DR_REG_LP_I2S_BASE),
APM_HAL_PMS_REGION_ENTRY(7, DR_REG_LP_TRNG_BASE, DR_REG_LP_ADC_BASE),
};
static const uint32_t test_lp_peri_regn_addr[] = {
LP_TIMER_DATE_REG, LP_ANALOG_PERI_DATE_REG, HUK_DATE_REG, LP_WDT_DATE_REG,
LP_UART_ID_REG, LP_I2C_DATE_REG, LP_I2C_ANA_MST_DATE_REG, RNG_DATE_REG,
};
static void test_hp_cpu_to_peri_access(const test_pms_periph_cfg_t *cfg)
{
apm_hal_pms_hp_peri_cfg_t hp_peri_cfg = {
.cpu_peri = UINT32_MAX,
.hp_peri0 = UINT32_MAX,
.hp_peri1 = UINT64_MAX,
};
const uint32_t lp_peri_cfg = UINT32_MAX;
for (uint32_t mode = APM_SEC_MODE_TEE; mode <= APM_SEC_MODE_REE; mode++) {
apm_hal_hp_peri_pms_set_hpcpu_access(0, (apm_security_mode_t)mode, &hp_peri_cfg);
apm_hal_hp2lp_peri_pms_set_hpcpu_access(0, (apm_security_mode_t)mode, lp_peri_cfg);
for (uint32_t sid = 0; sid < cfg->test_reg_num; sid++) {
uint32_t peri_addr = cfg->test_reg[sid];
if (peri_addr == 0) {
continue;
}
bool is_switch_req = (mode == APM_SEC_MODE_REE);
if (is_switch_req) {
switch_priv_mode();
}
hp_cpu_peri_addr_rw(peri_addr, false);
if (is_switch_req) {
switch_priv_mode();
}
switch (cfg->ctrl_mod) {
case APM_CTRL_HP_PERI_PMS:
switch (cfg->test_peri_grp) {
case HP_PERI0:
hp_peri_cfg.hp_peri0 &= ~BIT(sid);
break;
case HP_PERI1:
hp_peri_cfg.hp_peri1 &= ~BIT64(sid);
break;
case CPU_PERI:
hp_peri_cfg.cpu_peri &= ~BIT(sid);
break;
default:
TEST_ASSERT_MESSAGE(false, "Invalid group");
return;
}
apm_hal_hp_peri_pms_set_hpcpu_access(0, (apm_security_mode_t)mode, &hp_peri_cfg);
break;
case APM_CTRL_HP2LP_PERI_PMS:
apm_hal_hp2lp_peri_pms_set_hpcpu_access(0, (apm_security_mode_t)mode, lp_peri_cfg & ~BIT(sid));
break;
default:
break;
}
memset(&hp_peri_cfg, 0xFF, sizeof(hp_peri_cfg));
if (is_switch_req) {
switch_priv_mode();
}
hp_cpu_peri_addr_rw(peri_addr, true);
if (is_switch_req) {
switch_priv_mode();
}
}
}
}
static void test_hp_cpu_to_peri_access_regn(const test_pms_periph_cfg_t *cfg)
{
const apm_hal_pms_regn_cfg_t *regn_cfg;
if (cfg->test_peri_grp == LP_PERI) {
regn_cfg = test_lp_peri_regn_cfg;
} else {
regn_cfg = test_hp_peri_regn_cfg;
}
apm_hal_lp_peri_pms_set_region_cfg(cfg->test_reg_num, regn_cfg);
for (uint32_t mode = APM_SEC_MODE_TEE; mode <= APM_SEC_MODE_REE; mode++) {
bool is_switch_req = (mode == APM_SEC_MODE_REE);
for (uint32_t rid = 0; rid < cfg->test_reg_num; rid++) {
uint32_t peri_addr = cfg->test_reg[rid];
apm_hal_lp_peri_pms_set_master_region_attr(cfg->master_id, (apm_security_mode_t)mode, UINT32_MAX);
if (is_switch_req) {
switch_priv_mode();
}
hp_cpu_peri_addr_rw(peri_addr, false);
if (is_switch_req) {
switch_priv_mode();
}
apm_hal_lp_peri_pms_set_master_region_attr(cfg->master_id, (apm_security_mode_t)mode, UINT32_MAX & ~BIT(rid));
if (is_switch_req) {
switch_priv_mode();
}
hp_cpu_peri_addr_rw(peri_addr, true);
if (is_switch_req) {
switch_priv_mode();
}
}
}
}
#if CONFIG_ULP_COPROC_ENABLED
static void test_lp_cpu_to_peri_access(const test_pms_periph_cfg_t *cfg)
{
apm_hal_pms_hp_peri_cfg_t hp_peri_cfg = {
.cpu_peri = UINT32_MAX,
.hp_peri0 = UINT32_MAX,
.hp_peri1 = UINT64_MAX,
};
const uint32_t lp_peri_cfg = UINT32_MAX;
for (uint32_t sid = 0; sid < cfg->test_reg_num; sid++) {
uint32_t peri_addr = cfg->test_reg[sid];
if (peri_addr == 0) {
continue;
}
apm_hal_lp_peri_pms_set_lpcpu_access(lp_peri_cfg);
apm_hal_lp2hp_peri_pms_set_lpcpu_access(&hp_peri_cfg);
lp_cpu_peri_addr_rw(peri_addr, false);
switch (cfg->ctrl_mod) {
case APM_CTRL_LP_PERI_PMS:
apm_hal_lp_peri_pms_set_lpcpu_access(lp_peri_cfg & ~BIT(sid));
break;
case APM_CTRL_LP2HP_PERI_PMS:
switch (cfg->test_peri_grp) {
case HP_PERI0:
hp_peri_cfg.hp_peri0 &= ~BIT(sid);
break;
case HP_PERI1:
hp_peri_cfg.hp_peri1 &= ~BIT64(sid);
break;
case CPU_PERI:
hp_peri_cfg.cpu_peri &= ~BIT(sid);
break;
default:
TEST_ASSERT_MESSAGE(false, "Invalid group");
return;
}
apm_hal_lp2hp_peri_pms_set_lpcpu_access(&hp_peri_cfg);
break;
default:
break;
}
memset(&hp_peri_cfg, 0xFF, sizeof(hp_peri_cfg));
lp_cpu_peri_addr_rw(peri_addr, true);
}
}
static void test_lp_cpu_to_peri_access_regn(const test_pms_periph_cfg_t *cfg)
{
const apm_hal_pms_regn_cfg_t *regn_cfg;
if (cfg->test_peri_grp == LP_PERI) {
regn_cfg = test_lp_peri_regn_cfg;
} else {
regn_cfg = test_hp_peri_regn_cfg;
}
apm_hal_lp_peri_pms_set_region_cfg(cfg->test_reg_num, regn_cfg);
for (uint32_t rid = 0; rid < cfg->test_reg_num; rid++) {
uint32_t peri_addr = cfg->test_reg[rid];
apm_hal_lp_peri_pms_set_master_region_attr(cfg->master_id, APM_SEC_MODE_TEE, UINT32_MAX);
lp_cpu_peri_addr_rw(peri_addr, false);
apm_hal_lp_peri_pms_set_master_region_attr(cfg->master_id, APM_SEC_MODE_TEE, UINT32_MAX & ~BIT(rid));
lp_cpu_peri_addr_rw(peri_addr, true);
}
}
#endif
void test_sys_pms_master_hp_cpu_slave_hp_peri(void)
{
const test_pms_periph_cfg_t cfgs[] = {
{
.master_id = APM_MASTER_HPCPU0,
.ctrl_mod = APM_CTRL_HP_PERI_PMS,
.test_reg = test_hp_peri0_reg,
.test_reg_num = sizeof(test_hp_peri0_reg) / sizeof(test_hp_peri0_reg[0]),
.test_peri_grp = HP_PERI0,
},
{
.master_id = APM_MASTER_HPCPU0,
.ctrl_mod = APM_CTRL_HP_PERI_PMS,
.test_reg = test_hp_peri1_reg,
.test_reg_num = sizeof(test_hp_peri1_reg) / sizeof(test_hp_peri1_reg[0]),
.test_peri_grp = HP_PERI1,
},
{
.master_id = APM_MASTER_HPCPU0,
.ctrl_mod = APM_CTRL_HP_PERI_PMS,
.test_reg = test_cpu_peri_reg,
.test_reg_num = sizeof(test_cpu_peri_reg) / sizeof(test_cpu_peri_reg[0]),
.test_peri_grp = CPU_PERI,
},
};
test_pms_ctrl_reset_all();
set_test_vector_table();
for (int i = 0; i < sizeof(cfgs) / sizeof(cfgs[0]); i++) {
test_hp_cpu_to_peri_access(&cfgs[i]);
}
restore_default_vector_table();
}
void test_sys_pms_master_hp_cpu_slave_lp_peri(void)
{
const test_pms_periph_cfg_t cfg = {
.master_id = APM_MASTER_HPCPU0,
.ctrl_mod = APM_CTRL_HP2LP_PERI_PMS,
.test_reg = test_lp_peri_reg,
.test_reg_num = sizeof(test_lp_peri_reg) / sizeof(test_lp_peri_reg[0]),
};
test_pms_ctrl_reset_all();
set_test_vector_table();
test_hp_cpu_to_peri_access(&cfg);
restore_default_vector_table();
}
void test_sys_pms_master_hp_cpu_peri_regn_access(void)
{
const test_pms_periph_cfg_t hp_peri_regn_cfg = {
.master_id = APM_MASTER_HPCPU0,
.test_reg = test_hp_peri_regn_addr,
.test_reg_num = sizeof(test_hp_peri_regn_addr) / sizeof(test_hp_peri_regn_addr[0]),
};
const test_pms_periph_cfg_t lp_peri_regn_cfg = {
.master_id = APM_MASTER_HPCPU0,
.test_reg = test_lp_peri_regn_addr,
.test_reg_num = sizeof(test_lp_peri_regn_addr) / sizeof(test_lp_peri_regn_addr[0]),
.test_peri_grp = LP_PERI,
};
test_pms_ctrl_reset_all();
set_test_vector_table();
test_hp_cpu_to_peri_access_regn(&hp_peri_regn_cfg);
test_hp_cpu_to_peri_access_regn(&lp_peri_regn_cfg);
restore_default_vector_table();
}
#if CONFIG_ULP_COPROC_ENABLED
void test_sys_pms_master_lp_cpu_slave_hp_peri(void)
{
const test_pms_periph_cfg_t cfgs[] = {
{
.master_id = APM_MASTER_LPCPU,
.ctrl_mod = APM_CTRL_LP2HP_PERI_PMS,
.test_reg = test_hp_peri0_reg,
.test_reg_num = sizeof(test_hp_peri0_reg) / sizeof(test_hp_peri0_reg[0]),
.test_peri_grp = HP_PERI0,
},
{
.master_id = APM_MASTER_LPCPU,
.ctrl_mod = APM_CTRL_LP2HP_PERI_PMS,
.test_reg = test_hp_peri1_reg,
.test_reg_num = sizeof(test_hp_peri1_reg) / sizeof(test_hp_peri1_reg[0]),
.test_peri_grp = HP_PERI1,
},
{
.master_id = APM_MASTER_LPCPU,
.ctrl_mod = APM_CTRL_LP2HP_PERI_PMS,
.test_reg = test_cpu_peri_reg,
.test_reg_num = sizeof(test_cpu_peri_reg) / sizeof(test_cpu_peri_reg[0]),
.test_peri_grp = CPU_PERI,
},
};
test_pms_ctrl_reset_all();
test_boot_lp_cpu();
set_test_vector_table();
for (int i = 0; i < sizeof(cfgs) / sizeof(cfgs[0]); i++) {
test_lp_cpu_to_peri_access(&cfgs[i]);
}
restore_default_vector_table();
test_stop_lp_cpu();
}
void test_sys_pms_master_lp_cpu_slave_lp_peri(void)
{
const test_pms_periph_cfg_t cfg = {
.master_id = APM_MASTER_LPCPU,
.ctrl_mod = APM_CTRL_LP_PERI_PMS,
.test_reg = test_lp_peri_reg,
.test_reg_num = sizeof(test_lp_peri_reg) / sizeof(test_lp_peri_reg[0]),
};
test_pms_ctrl_reset_all();
test_pms_enable_intr(APM_CTRL_LP_PERI_PMS);
test_boot_lp_cpu();
set_test_vector_table();
test_lp_cpu_to_peri_access(&cfg);
restore_default_vector_table();
test_stop_lp_cpu();
}
void test_sys_pms_master_lp_cpu_peri_regn_access(void)
{
const test_pms_periph_cfg_t hp_peri_regn_cfg = {
.master_id = APM_MASTER_LPCPU,
.test_reg = test_hp_peri_regn_addr,
.test_reg_num = sizeof(test_hp_peri_regn_addr) / sizeof(test_hp_peri_regn_addr[0]),
};
const test_pms_periph_cfg_t lp_peri_regn_cfg = {
.master_id = APM_MASTER_LPCPU,
.test_reg = test_lp_peri_regn_addr,
.test_reg_num = sizeof(test_lp_peri_regn_addr) / sizeof(test_lp_peri_regn_addr[0]),
.test_peri_grp = LP_PERI,
};
test_pms_ctrl_reset_all();
test_pms_enable_intr(APM_CTRL_LP_PERI_PMS);
test_boot_lp_cpu();
set_test_vector_table();
test_lp_cpu_to_peri_access_regn(&hp_peri_regn_cfg);
test_lp_cpu_to_peri_access_regn(&lp_peri_regn_cfg);
restore_default_vector_table();
test_stop_lp_cpu();
}
#endif
/***************************** DMA_PMS *****************************/
typedef struct {
apm_master_dma_id_t master_id;
uint32_t mem_start_addr;
uint32_t mem_end_addr;
uint32_t regn_count;
uint32_t regn_sz;
bool is_ext_mem;
} test_dma_pms_mem_cfg_t;
#define GDMA_TEST_REGN_RESV_NUM(is_ext_mem) \
((is_ext_mem) ? GDMA_EXTMEM_TEST_REGN_RESV_NUM : GDMA_HPMEM_TEST_REGN_RESV_NUM)
static void test_dma_pms_mem_setup(const test_dma_pms_mem_cfg_t *cfg, uint32_t test_start, uint32_t test_end)
{
apm_hal_pms_regn_cfg_t regn_cfgs[GDMA_HPMEM_TEST_REGN_NUM] = {0};
regn_cfgs[0] = (apm_hal_pms_regn_cfg_t)APM_HAL_PMS_REGION_ENTRY(0, cfg->mem_start_addr, test_start);
regn_cfgs[1] = (apm_hal_pms_regn_cfg_t)APM_HAL_PMS_REGION_ENTRY(1, test_end, cfg->mem_end_addr);
const uint32_t test_regn_start = GDMA_TEST_REGN_RESV_NUM(cfg->is_ext_mem);
if (cfg->is_ext_mem) {
regn_cfgs[2] = (apm_hal_pms_regn_cfg_t)APM_HAL_PMS_REGION_ENTRY(2, SOC_IRAM_LOW, SOC_DRAM_HIGH);
}
for (uint32_t idx = test_regn_start; idx < cfg->regn_count; idx++) {
uint32_t regn_start = test_start + (idx - test_regn_start) * cfg->regn_sz;
regn_cfgs[idx] = (apm_hal_pms_regn_cfg_t)APM_HAL_PMS_REGION_ENTRY(idx, regn_start, regn_start + cfg->regn_sz);
}
apm_hal_dma_pms_set_region_cfg(GDMA_HPMEM_TEST_REGN_NUM, regn_cfgs);
}
static void gdma_hpmem_addr_rw(uint8_t *src, uint8_t *dest, size_t size, bool should_panic)
{
pms_dma_excp_flag = false;
memset(src, 0xA5, size);
esp_cache_msync(src, size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
test_gdma_init();
test_gdma_m2m_transfer(src, dest, size);
test_delay_ms(10);
if (should_panic) {
TEST_ASSERT(pms_dma_excp_flag);
} else {
test_gdma_wait_done();
esp_cache_msync(dest, size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
TEST_ASSERT_FALSE(pms_dma_excp_flag);
TEST_ASSERT_EQUAL_HEX8_ARRAY(src, dest, size);
}
test_gdma_deinit();
pms_dma_excp_flag = false;
}
static void test_gdma_to_xmem_access(const test_dma_pms_mem_cfg_t *cfg, uint32_t test_start_addr)
{
uint8_t *test_dma_buf = heap_caps_aligned_alloc(cfg->regn_sz, cfg->regn_sz, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(test_dma_buf);
memset(test_dma_buf, 0x5A, cfg->regn_sz);
const uint32_t test_regn_start = GDMA_TEST_REGN_RESV_NUM(cfg->is_ext_mem);
const uint32_t resv_regn = BIT(test_regn_start) - 1;
for (uint32_t regn_idx = test_regn_start; regn_idx < cfg->regn_count; regn_idx++) {
uint8_t *regn_start = (uint8_t *)(test_start_addr + (regn_idx - test_regn_start) * cfg->regn_sz);
apm_hal_dma_pms_set_master_region_attr(cfg->master_id, resv_regn, resv_regn | BIT(regn_idx));
gdma_hpmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, true);
gdma_hpmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, false);
apm_hal_dma_pms_set_master_region_attr(cfg->master_id, resv_regn | BIT(regn_idx), resv_regn);
gdma_hpmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, false);
gdma_hpmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, true);
apm_hal_dma_pms_set_master_region_attr(cfg->master_id, UINT32_MAX, UINT32_MAX);
}
free(test_dma_buf);
}
void test_sys_pms_master_gdma_slave_hp_mem(void)
{
test_pms_ctrl_reset_all();
test_pms_enable_intr(APM_CTRL_DMA_PMS);
const uint32_t total_sz = (GDMA_HPMEM_TEST_REGN_NUM - GDMA_HPMEM_TEST_REGN_RESV_NUM) * GDMA_HPMEM_TEST_REGN_SIZE;
test_dma_pms_mem_cfg_t cfg = {
.master_id = APM_MASTER_DMA_AHB_PDMA_DUMMY,
.mem_start_addr = SOC_IRAM_LOW,
.mem_end_addr = SOC_DRAM_HIGH,
.regn_count = GDMA_HPMEM_TEST_REGN_NUM,
.regn_sz = GDMA_HPMEM_TEST_REGN_SIZE,
};
uint8_t *test_hpmem_buf = heap_caps_aligned_alloc(cfg.regn_sz, total_sz, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(test_hpmem_buf);
uint32_t test_start_addr = (uint32_t)test_hpmem_buf;
uint32_t test_end_addr = test_start_addr + total_sz;
test_dma_pms_mem_setup(&cfg, test_start_addr, test_end_addr);
test_gdma_to_xmem_access(&cfg, test_start_addr);
free(test_hpmem_buf);
}
#if CONFIG_SPIRAM
void test_sys_pms_master_gdma_slave_ext_mem(void)
{
test_pms_ctrl_reset_all();
test_pms_enable_intr(APM_CTRL_DMA_PMS);
const uint32_t total_sz = (GDMA_HPMEM_TEST_REGN_NUM - GDMA_EXTMEM_TEST_REGN_RESV_NUM) * GDMA_HPMEM_TEST_REGN_SIZE;
test_dma_pms_mem_cfg_t cfg = {
.master_id = APM_MASTER_DMA_AHB_PDMA_DUMMY,
.mem_start_addr = SOC_EXTRAM_LOW,
.mem_end_addr = SOC_EXTRAM_HIGH,
.regn_count = GDMA_HPMEM_TEST_REGN_NUM,
.regn_sz = GDMA_HPMEM_TEST_REGN_SIZE,
.is_ext_mem = true,
};
uint8_t *test_extmem_buf = heap_caps_aligned_alloc(cfg.regn_sz, total_sz, MALLOC_CAP_SPIRAM);
TEST_ASSERT_NOT_NULL(test_extmem_buf);
uint32_t test_start_addr = (uint32_t)test_extmem_buf;
uint32_t test_end_addr = test_start_addr + total_sz;
test_dma_pms_mem_setup(&cfg, test_start_addr, test_end_addr);
test_gdma_to_xmem_access(&cfg, test_start_addr);
free(test_extmem_buf);
}
#endif

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,9 +14,8 @@
#include "hal/apm_hal.h"
#include "hal/apm_types.h"
#include "rom/cache.h"
#include "esp_cache.h"
#include "esp_rom_sys.h"
#include "esp_memory_utils.h"
#include "esp_heap_caps.h"
#include "test_pms_priv.h"
@@ -34,7 +33,25 @@
APM_HAL_REGION_ENTRY(path, id, start, end, perm)
#endif
extern bool apm_master_excp_flag[APM_MASTER_MAX];
typedef struct {
apm_master_id_t master_id;
apm_ctrl_module_t ctrl_mod;
apm_ctrl_access_path_t path;
uint32_t mem_start_addr;
uint32_t mem_end_addr;
uint32_t regn_count;
uint32_t regn_sz;
} test_sys_apm_mem_cfg_t;
typedef struct {
apm_master_id_t master_id;
apm_ctrl_module_t ctrl_mod;
const uint32_t *test_addr;
uint32_t test_addr_num;
uint32_t test_addr_resv_mask;
} test_sys_apm_periph_cfg_t;
extern volatile bool apm_master_excp_flag[APM_MASTER_MAX];
/***************************** APM setup for memory *****************************/
@@ -65,31 +82,21 @@ static void test_mem_apm_setup(test_sys_apm_mem_cfg_t *cfg, uint32_t test_start_
/***************************** GDMA: Utility *****************************/
static void gdma_xmem_addr_rw(uint8_t *src, uint8_t *dest, size_t size, uint32_t test_attr)
static void gdma_xmem_addr_rw(uint8_t *src, uint8_t *dest, size_t size, bool should_panic)
{
apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID] = false;
memset(src, TEST_VAL, size);
memset(src, 0xA5, size);
esp_cache_msync(src, size, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
test_gdma_init();
#if CONFIG_SPIRAM
if (esp_ptr_external_ram(src)) {
Cache_WriteBack_Addr((uint32_t)src, size);
}
#endif
test_gdma_m2m_transfer(src, dest, size);
#if CONFIG_SPIRAM
if (esp_ptr_external_ram(dest)) {
Cache_Invalidate_Addr((uint32_t)dest, size);
}
#endif
if (!test_attr) {
test_delay_ms(10);
test_delay_ms(10);
if (should_panic) {
TEST_ASSERT(apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID]);
test_gdma_wait_done();
} else {
test_gdma_wait_done();
test_delay_ms(10);
esp_cache_msync(dest, size, ESP_CACHE_MSYNC_FLAG_DIR_M2C);
TEST_ASSERT_FALSE(apm_master_excp_flag[TEST_GDMA_APM_MASTER_ID]);
TEST_ASSERT_EQUAL_HEX8_ARRAY(src, dest, size);
}
@@ -109,26 +116,22 @@ static void test_gdma_to_xmem_access(const test_sys_apm_mem_cfg_t *cfg, uint32_t
for (uint32_t regn_idx = 2; regn_idx < cfg->regn_count; regn_idx++) {
uint8_t *regn_start = (uint8_t *)(test_start_addr + (regn_idx - 2) * cfg->regn_sz);
uint32_t pms_attr = APM_PERM_NONE;
if (mode == APM_SEC_MODE_TEE) {
pms_attr = APM_PERM_R | APM_PERM_W;
gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, pms_attr & APM_PERM_R);
gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, pms_attr & APM_PERM_W);
gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, false);
gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, false);
continue;
}
pms_attr = APM_PERM_W;
apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_NONE);
apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, pms_attr);
gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, pms_attr & APM_PERM_R);
gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, pms_attr & APM_PERM_W);
apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_W);
gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, true);
gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, false);
pms_attr = APM_PERM_R;
apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_NONE);
apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, pms_attr);
gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, pms_attr & APM_PERM_R);
gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, pms_attr & APM_PERM_W);
apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_R);
gdma_xmem_addr_rw(regn_start, test_dma_buf, cfg->regn_sz, false);
gdma_xmem_addr_rw(test_dma_buf, regn_start, cfg->regn_sz, true);
apm_hal_set_sec_mode_region_attr(cfg->ctrl_mod, regn_idx, mode, APM_PERM_ALL);
}
@@ -545,7 +548,7 @@ static void lp_cpu_xmem_addr_rw(uint32_t mem_addr, size_t size, uint32_t attr)
SEND_MSG(MSG_SLAVE_WRITE);
SEND_ADDR(mem_addr);
SEND_SIZE(sizeof(uint32_t));
SEND_DATA(sizeof(uint32_t));
test_delay_ms(10);
bool can_write = (attr & APM_PERM_W);
@@ -868,13 +871,13 @@ void test_tee_mode_default_access(void)
test_tee_mode_apm_setup(&cfg, (uint32_t)test_hpmem_buf, (uint32_t)test_hpmem_buf + total_sz);
apm_ll_hp_tee_set_master_sec_mode(TEST_GDMA_APM_MASTER_ID, APM_SEC_MODE_TEE);
uint32_t pms_attr = APM_PERM_R | APM_PERM_W;
bool should_panic = false;
#if SOC_APM_CTRL_TEE_MODE_ACCESS_BUG
pms_attr = APM_PERM_NONE;
should_panic = true;
#endif
gdma_xmem_addr_rw(test_hpmem_buf, test_dma_buf, total_sz, pms_attr & APM_PERM_R);
gdma_xmem_addr_rw(test_dma_buf, test_hpmem_buf, total_sz, pms_attr & APM_PERM_W);
gdma_xmem_addr_rw(test_hpmem_buf, test_dma_buf, total_sz, should_panic);
gdma_xmem_addr_rw(test_dma_buf, test_hpmem_buf, total_sz, should_panic);
free(test_dma_buf);
free(test_hpmem_buf);

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "soc/soc.h"
#include "esp_attr.h"
#include "riscv/csr.h"
#include "riscv/rv_utils.h"
@@ -53,6 +54,32 @@ void test_panicHandler(void *frame, int exccause)
return;
}
NOINLINE_ATTR static uint32_t reg_read(uint32_t addr)
{
uint32_t value;
__asm__ volatile(
"lw %0, 0(%1)\n"
"fence\n"
"nop\nnop\nnop\nnop\n"
: "=r"(value)
: "r"(addr)
: "memory"
);
return value;
}
NOINLINE_ATTR static void reg_write(uint32_t addr, uint32_t value)
{
__asm__ volatile(
"sw %1, 0(%0)\n"
"fence\n"
"nop\nnop\nnop\nnop\n"
:
: "r"(addr), "r"(value)
: "memory"
);
}
/**
* @brief Test LP CPU access to memory/peripherals
*
@@ -84,14 +111,14 @@ int main(void)
}
uint32_t test_addr = RECV_ADDR();
uint32_t test_size = RECV_SIZE();
uint32_t test_data = RECV_DATA();
switch (test_msg) {
case MSG_SLAVE_READ:
(void)REG_READ(test_addr);
(void)reg_read(test_addr);
break;
case MSG_SLAVE_WRITE:
REG_WRITE(test_addr, test_size);
reg_write(test_addr, test_data);
break;
case MSG_SLAVE_EXEC: {
void (*func_ptr)(void) = (void (*)(void))(test_addr);

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -245,4 +245,116 @@ TEST_CASE("Test LP_CPU -> LP_PERI access", "[PERI_APM]")
}
#endif /* CONFIG_ULP_COPROC_ENABLED */
#endif
#else
/**
* Test HP-CPU access to HP_PERI
*
* PMS uses per-peripheral based access control with per-master read/write permissions.
* For each peripheral, tests HP-CPU read/write access with varying permissions:
* all access (both read and write pass) and no access (both read and write fail).
* Verifies enforcement of PMS access control by asserting expected load/store access faults.
*/
TEST_CASE("Test HP_CPU -> HP_PERI access", "[SYS_APM]")
{
test_sys_pms_master_hp_cpu_slave_hp_peri();
}
/**
* Test HP-CPU access to LP_PERI
*
* PMS uses per-peripheral based access control with per-master read/write permissions.
* For each peripheral, tests HP-CPU read/write access with varying permissions:
* all access (both read and write pass) and no access (both read and write fail).
* Verifies enforcement of PMS access control by asserting expected load/store access faults.
*/
TEST_CASE("Test HP_CPU -> LP_PERI access", "[SYS_APM]")
{
test_sys_pms_master_hp_cpu_slave_lp_peri();
}
/**
* Test HP-CPU access to HP_PERI and LP_PERI (configurable regions)
*
* PMS also provides region-based access control with start/end address boundaries and per-master
* read/write permissions. Configures PMS regions covering HP_PERI and LP_PERI address
* ranges. For each region, tests HP-CPU read/write access with varying permissions in
* both TEE and REE modes: all access (both read and write pass) and no access (both read
* and write fail). Verifies enforcement of PMS access control by asserting expected PMS violations.
*/
TEST_CASE("Test HP_CPU -> PERI access (configurable regions)", "[SYS_APM]")
{
test_sys_pms_master_hp_cpu_peri_regn_access();
}
#if CONFIG_ULP_COPROC_ENABLED
/**
* Test LP-CPU access to HP_PERI
*
* PMS uses per-peripheral based access control with per-master read/write permissions.
* For each peripheral, tests LP-CPU read/write access with varying permissions:
* all access (both read and write pass) and no access (both read and write fail).
* Verifies enforcement of PMS access control by asserting expected load/store access faults.
*/
TEST_CASE("Test LP_CPU -> HP_PERI access", "[SYS_APM]")
{
test_sys_pms_master_lp_cpu_slave_hp_peri();
}
/**
* Test LP-CPU access to LP_PERI
*
* PMS uses per-peripheral based access control with per-master read/write permissions.
* For each peripheral, tests LP-CPU read/write access with varying permissions:
* all access (both read and write pass) and no access (both read and write fail).
* Verifies enforcement of PMS access control by asserting expected PMS violations.
*/
TEST_CASE("Test LP_CPU -> LP_PERI access", "[SYS_APM]")
{
test_sys_pms_master_lp_cpu_slave_lp_peri();
}
/**
* Test LP-CPU access to HP_PERI and LP_PERI (configurable regions)
*
* PMS uses region-based access control with start/end address boundaries and per-master
* read/write permissions. Configures PMS regions covering HP_PERI and LP_PERI address
* ranges. For each region, tests LP-CPU read/write access with varying permissions:
* all access (both read and write pass) and no access (both read and write fail).
* Verifies enforcement of PMS access control by asserting expected PMS violations.
*/
TEST_CASE("Test LP_CPU -> PERI access (configurable regions)", "[SYS_APM]")
{
test_sys_pms_master_lp_cpu_peri_regn_access();
}
#endif /* CONFIG_ULP_COPROC_ENABLED */
/**
* Test GDMA access to HP_MEM
*
* PMS uses region-based access control with start/end address boundaries and per-master
* read/write permissions. Divides a contiguous HP_MEM block into multiple PMS regions and
* configures their boundaries. For each region, tests GDMA read/write access with varying
* permissions: R-only (read passes, write fails) and W-only (write passes, read fails).
* Verifies enforcement of PMS access control by asserting expected PMS violations.
*/
TEST_CASE("Test GDMA -> HP_MEM access", "[SYS_APM]")
{
test_sys_pms_master_gdma_slave_hp_mem();
}
#if CONFIG_SPIRAM
/**
* Test GDMA access to EXT_MEM (SPIRAM)
*
* PMS uses region-based access control with start/end address boundaries and per-master
* read/write permissions. Divides a contiguous EXT_MEM block into multiple PMS regions and
* configures their boundaries. For each region, tests GDMA read/write access with varying
* permissions: R-only (read passes, write fails) and W-only (write passes, read fails).
* Verifies enforcement of PMS access control by asserting expected PMS violations.
*/
TEST_CASE("Test GDMA -> EXT_MEM access", "[SYS_APM]")
{
test_sys_pms_master_gdma_slave_ext_mem();
}
#endif /* CONFIG_SPIRAM */
#endif /* SOC_APM_CTRL_FILTER_SUPPORTED */

View File

@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import pytest
from pytest_embedded_idf import IdfDut
@@ -6,7 +6,7 @@ from pytest_embedded_idf.utils import idf_parametrize
# ---------------- Pytest build parameters ----------------
SOC_SUPPORT_SYS_APM_TEST = ['esp32c6', 'esp32h2', 'esp32c5', 'esp32c61']
SOC_SUPPORT_SYS_APM_TEST = ['esp32c6', 'esp32h2', 'esp32c5', 'esp32c61', 'esp32p4']
SOC_SUPPORT_PERI_APM_TEST = ['esp32c5']
SOC_SUPPORT_INTR_TEST = ['esp32c5', 'esp32c61', 'esp32p4']

View File

@@ -2,3 +2,11 @@
# U-mode for multicore SoCs. Thus, TEE interrupt tests will
# run only in unicore mode till then.
CONFIG_FREERTOS_UNICORE=y
# Enable LP core
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_RESERVE_MEM=8192
CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=n
# Enable SPIRAM
CONFIG_SPIRAM=y