kopia lustrzana https://github.com/espressif/esp-idf
rodzic
80f993bf31
commit
497b730e8f
|
@ -511,7 +511,6 @@ menu "ESP32S2-specific"
|
|||
|
||||
config ESP32S2_ALLOW_RTC_FAST_MEM_AS_HEAP
|
||||
bool "Enable RTC fast memory for dynamic allocations"
|
||||
depends on !ESP32S2_MEMPROT_FEATURE
|
||||
default y
|
||||
help
|
||||
This config option allows to add RTC fast memory region to system heap with capability
|
||||
|
|
|
@ -18,15 +18,22 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include "esp_attr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MEMPROT_IRAM0 = 0x00000000,
|
||||
MEMPROT_DRAM0 = 0x00000001,
|
||||
MEMPROT_UNKNOWN
|
||||
MEMPROT_NONE = 0x00000000,
|
||||
MEMPROT_IRAM0_SRAM = 0x00000001, //0x40020000-0x4006FFFF, RWX
|
||||
MEMPROT_DRAM0_SRAM = 0x00000002, //0x3FFB0000-0x3FFFFFFF, RW
|
||||
MEMPROT_IRAM0_RTCFAST = 0x00000004, //0x40070000-0x40071FFF, RWX
|
||||
MEMPROT_DRAM0_RTCFAST = 0x00000008, //0x3FF9E000-0x3FF9FFFF, RW
|
||||
MEMPROT_PERI1_RTCSLOW = 0x00000010, //0x3F421000-0x3F423000, RW
|
||||
MEMPROT_PERI2_RTCSLOW_0 = 0x00000020, //0x50001000-0x50003000, RWX
|
||||
MEMPROT_PERI2_RTCSLOW_1 = 0x00000040, //0x60002000-0x60004000, RWX
|
||||
MEMPROT_ALL = 0xFFFFFFFF
|
||||
} mem_type_prot_t;
|
||||
|
||||
|
||||
|
@ -60,22 +67,6 @@ void esp_memprot_intr_init(mem_type_prot_t mem_type);
|
|||
*/
|
||||
void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Detects whether any of the memory protection interrupts is active
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool esp_memprot_is_assoc_intr_any(void);
|
||||
|
||||
/**
|
||||
* @brief Detects whether specific memory protection interrupt is active
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return true/false
|
||||
*/
|
||||
bool esp_memprot_is_assoc_intr(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Sets a request for clearing interrupt-on flag for specified memory region (register write)
|
||||
*
|
||||
|
@ -87,11 +78,17 @@ bool esp_memprot_is_assoc_intr(mem_type_prot_t mem_type);
|
|||
void esp_memprot_clear_intr(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Detects which memory protection interrupt is active, check order: IRAM0, DRAM0
|
||||
* @brief Detects which memory protection interrupt is active
|
||||
*
|
||||
* @note Check order
|
||||
* MEMPROT_IRAM0_SRAM
|
||||
* MEMPROT_IRAM0_RTCFAST
|
||||
* MEMPROT_DRAM0_SRAM
|
||||
* MEMPROT_DRAM0_RTCFAST
|
||||
*
|
||||
* @return Memory protection area type (see mem_type_prot_t enum)
|
||||
*/
|
||||
mem_type_prot_t IRAM_ATTR esp_memprot_get_intr_memtype(void);
|
||||
mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt status register contents for specified memory region
|
||||
|
@ -151,13 +148,13 @@ void esp_memprot_set_lock(mem_type_prot_t mem_type);
|
|||
bool esp_memprot_get_lock(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt permission control register contents for required memory region
|
||||
* @brief Gets permission control configuration register contents for required memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*
|
||||
* @return Permission control register contents
|
||||
*/
|
||||
uint32_t esp_memprot_get_ena_reg(mem_type_prot_t mem_type);
|
||||
uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Gets interrupt permission settings for unified management block
|
||||
|
@ -321,11 +318,12 @@ void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, b
|
|||
*
|
||||
* @param invoke_panic_handler map mem.prot interrupt to ETS_MEMACCESS_ERR_INUM and thus invokes panic handler when fired ('true' not suitable for testing)
|
||||
* @param lock_feature sets LOCK bit, see esp_memprot_set_lock() ('true' not suitable for testing)
|
||||
* @param mem_type_mask holds a set of required memory protection types (bitmask built of mem_type_prot_t). NULL means default (MEMPROT_ALL in this version)
|
||||
*/
|
||||
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature);
|
||||
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
|
||||
|
||||
/**
|
||||
* @brief Get permission settings bits for IRAM split mgmt based on current split address
|
||||
* @brief Get permission settings bits for IRAM0 split mgmt. Only IRAM0 memory types allowed
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lw Low segment Write permission flag
|
||||
|
@ -338,7 +336,7 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature);
|
|||
void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx);
|
||||
|
||||
/**
|
||||
* @brief Get permission settings bits for DRAM split mgmt based on current split address
|
||||
* @brief Get permission settings bits for DRAM0 split mgmt. Only DRAM0 memory types allowed
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lw Low segment Write permission flag
|
||||
|
@ -348,6 +346,145 @@ void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bo
|
|||
*/
|
||||
void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr);
|
||||
|
||||
/**
|
||||
* @brief Sets permissions for high and low memory segment in PERIBUS1 region
|
||||
*
|
||||
* Sets Read and Write permission for both low and high memory segments given by splitting address.
|
||||
* Applicable only to PERIBUS1 memory types
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param split_addr Address to split the memory region to lower and higher segment
|
||||
* @param lw Low segment Write permission flag
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param hw High segment Write permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
*/
|
||||
void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr);
|
||||
|
||||
/**
|
||||
* @brief Get permission settings bits for PERIBUS1 split mgmt. Only PERIBUS1 memory types allowed
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lw Low segment Write permission flag
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param hw High segment Write permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
*/
|
||||
void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr);
|
||||
|
||||
/**
|
||||
* @brief Get permission settings bits for PERIBUS2 split mgmt. Only PERIBUS2 memory types allowed
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lw Low segment Write permission flag
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param lx Low segment Execute permission flag
|
||||
* @param hw High segment Write permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
* @param hx High segment Execute permission flag
|
||||
*/
|
||||
void esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx);
|
||||
|
||||
/**
|
||||
* @brief Sets permissions for high and low memory segment in PERIBUS2 region
|
||||
*
|
||||
* Sets Read Write permission for both low and high memory segments given by splitting address.
|
||||
* Applicable only to PERIBUS2 memory types
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param split_addr Address to split the memory region to lower and higher segment
|
||||
* @param lw Low segment Write permission flag
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param lx Low segment Execute permission flag
|
||||
* @param hw High segment Write permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
* @param hx High segment Execute permission flag
|
||||
*/
|
||||
void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx);
|
||||
|
||||
/**
|
||||
* @brief Get permissions for specified memory type. Irrelevant bits are ignored
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lw Low segment Write permission flag
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param lx Low segment Execute permission flag
|
||||
* @param hw High segment Write permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
* @param hx High segment Execute permission flag
|
||||
*/
|
||||
void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx);
|
||||
|
||||
/**
|
||||
* @brief Get Read permission settings for low and high regions of given memory type
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
*/
|
||||
void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr);
|
||||
|
||||
/**
|
||||
* @brief Get Write permission settings for low and high regions of given memory type
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lr Low segment Write permission flag
|
||||
* @param hr High segment Write permission flag
|
||||
*/
|
||||
void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw);
|
||||
|
||||
/**
|
||||
* @brief Get Execute permission settings for low and high regions of given memory type
|
||||
* Applicable only to IBUS-compatible memory types
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lr Low segment Exec permission flag
|
||||
* @param hr High segment Exec permission flag
|
||||
*/
|
||||
void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx);
|
||||
|
||||
/**
|
||||
* @brief Returns the lowest address in required memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*/
|
||||
uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Returns the highest address in required memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
*/
|
||||
uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type);
|
||||
|
||||
/**
|
||||
* @brief Sets READ permission bit for required memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lr Low segment Read permission flag
|
||||
* @param hr High segment Read permission flag
|
||||
*/
|
||||
void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr);
|
||||
|
||||
/**
|
||||
* @brief Sets WRITE permission bit for required memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lr Low segment Write permission flag
|
||||
* @param hr High segment Write permission flag
|
||||
*/
|
||||
void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw);
|
||||
|
||||
/**
|
||||
* @brief Sets EXECUTE permission bit for required memory region
|
||||
*
|
||||
* @param mem_type Memory protection area type (see mem_type_prot_t enum)
|
||||
* @param lr Low segment Exec permission flag
|
||||
* @param hr High segment Exec permission flag
|
||||
*/
|
||||
void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -8,11 +8,19 @@ SECTIONS
|
|||
*/
|
||||
.rtc.text :
|
||||
{
|
||||
_rtc_text_start = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
|
||||
_rtc_code_start = .;
|
||||
|
||||
mapping[rtc_text]
|
||||
|
||||
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
|
||||
_rtc_code_end = .;
|
||||
|
||||
/* possibly align + add 16B for CPU dummy speculative instr. fetch */
|
||||
. = ((_rtc_code_end - _rtc_code_start) == 0) ? ALIGN(0) : ALIGN(4) + 16;
|
||||
|
||||
_rtc_text_end = ABSOLUTE(.);
|
||||
} > rtc_iram_seg
|
||||
|
||||
|
@ -176,7 +184,7 @@ SECTIONS
|
|||
_coredump_iram_start = 0;
|
||||
_coredump_iram_end = 0;
|
||||
|
||||
/* align + add 16B for the possibly overlapping instructions */
|
||||
/* align + add 16B for CPU dummy speculative instr. fetch */
|
||||
. = ALIGN(4) + 16;
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
_iram_end = ABSOLUTE(.);
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -186,7 +186,7 @@ void esp_panic_handler(panic_info_t *info)
|
|||
info->exception = PANIC_EXCEPTION_ABORT;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* For any supported chip, the panic handler prints the contents of panic_info_t in the following format:
|
||||
*
|
||||
*
|
||||
|
@ -343,6 +343,7 @@ void esp_panic_handler(panic_info_t *info)
|
|||
#endif /* CONFIG_ESP_SYSTEM_PANIC_GDBSTUB */
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((noreturn)) panic_abort(const char *details)
|
||||
{
|
||||
g_panic_abort = true;
|
||||
|
|
|
@ -433,9 +433,9 @@ void IRAM_ATTR call_start_cpu0(void)
|
|||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_ESP32S2_MEMPROT_FEATURE
|
||||
#if CONFIG_ESP32S2_MEMPROT_FEATURE_LOCK
|
||||
esp_memprot_set_prot(true, true);
|
||||
esp_memprot_set_prot(true, true, NULL);
|
||||
#else
|
||||
esp_memprot_set_prot(true, false);
|
||||
esp_memprot_set_prot(true, false, NULL);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -371,12 +371,12 @@ static inline void print_memprot_err_details(const void *f)
|
|||
{
|
||||
uint32_t *fault_addr;
|
||||
uint32_t op_type, op_subtype;
|
||||
mem_type_prot_t mem_type = esp_memprot_get_intr_memtype();
|
||||
mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();
|
||||
esp_memprot_get_fault_status( mem_type, &fault_addr, &op_type, &op_subtype );
|
||||
|
||||
char *operation_type = "Write";
|
||||
if ( op_type == 0 ) {
|
||||
operation_type = (mem_type == MEMPROT_IRAM0 && op_subtype == 0) ? "Instruction fetch" : "Read";
|
||||
operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read";
|
||||
}
|
||||
|
||||
panic_print_str( operation_type );
|
||||
|
@ -506,7 +506,7 @@ static void frame_to_panic_info(XtExcFrame *frame, panic_info_t *info, bool pseu
|
|||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
if (frame->exccause == PANIC_RSN_CACHEERR) {
|
||||
if ( esp_memprot_is_assoc_intr_any() ) {
|
||||
if ( esp_memprot_get_active_intr_memtype() != MEMPROT_NONE ) {
|
||||
info->details = print_memprot_err_details;
|
||||
info->reason = "Memory protection fault";
|
||||
} else {
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,453 @@
|
|||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RTCSLOW_MEMORY_SIZE 0x00002000
|
||||
|
||||
/**
|
||||
* ========================================================================================
|
||||
* === PeriBus1 common
|
||||
* ========================================================================================
|
||||
*/
|
||||
//PeriBus1 interrupt status bitmasks
|
||||
#define PERI1_INTR_ST_OP_TYPE_BIT BIT(4) //0: non-atomic, 1: atomic
|
||||
#define PERI1_INTR_ST_OP_HIGH_BITS BIT(5) //0: high bits = unchanged, 1: high bits = 0x03F40000
|
||||
#define PERI1_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg)
|
||||
#define PERI1_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address)
|
||||
|
||||
static inline void esp_memprot_peri1_clear_intr(void)
|
||||
{
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri1_get_intr_source_num(void)
|
||||
{
|
||||
return ETS_PMS_PRO_DPORT_ILG_INTR_SOURCE;
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri1_intr_ena(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_EN);
|
||||
} else {
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_EN);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri1_get_ctrl_reg(void)
|
||||
{
|
||||
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_6_REG);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri1_get_fault_reg(void)
|
||||
{
|
||||
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_7_REG);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri1_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype)
|
||||
{
|
||||
uint32_t status_bits = esp_memprot_peri1_get_fault_reg();
|
||||
//*op_type = (uint32_t)status_bits & PERI1_INTR_ST_OP_RW_BIT;
|
||||
*op_type = 0;
|
||||
//! DPORT_PMS_PRO_DPORT_7_REG is missing op_type bit
|
||||
*op_subtype = (uint32_t)status_bits & PERI1_INTR_ST_OP_TYPE_BIT;
|
||||
}
|
||||
|
||||
static inline bool esp_memprot_peri1_is_assoc_intr(void)
|
||||
{
|
||||
return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_7_REG, DPORT_PMS_PRO_DPORT_ILG_INTR) > 0;
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri1_get_intr_ena_bit(void)
|
||||
{
|
||||
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_EN);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri1_get_intr_on_bit(void)
|
||||
{
|
||||
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_INTR);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri1_get_intr_clr_bit(void)
|
||||
{
|
||||
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri1_get_lock_reg(void)
|
||||
{
|
||||
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_0_REG);
|
||||
}
|
||||
|
||||
//resets automatically on CPU restart
|
||||
static inline void esp_memprot_peri1_set_lock(void)
|
||||
{
|
||||
DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DPORT_0_REG, DPORT_PMS_PRO_DPORT_LOCK);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri1_get_lock_bit(void)
|
||||
{
|
||||
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_0_REG, DPORT_PMS_PRO_DPORT_LOCK);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ========================================================================================
|
||||
* === PeriBus1 RTC SLOW
|
||||
* ========================================================================================
|
||||
*/
|
||||
#define PERI1_RTCSLOW_ADDRESS_BASE 0x3F421000
|
||||
#define PERI1_RTCSLOW_ADDRESS_LOW PERI1_RTCSLOW_ADDRESS_BASE
|
||||
#define PERI1_RTCSLOW_ADDRESS_HIGH PERI1_RTCSLOW_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE
|
||||
#define PERI1_RTCSLOW_INTR_ST_FAULTADDR_HI_0 0x3F400000
|
||||
|
||||
|
||||
static inline uint32_t *esp_memprot_peri1_rtcslow_get_fault_address(void)
|
||||
{
|
||||
uint32_t status_bits = esp_memprot_peri1_get_fault_reg();
|
||||
uint32_t fault_address = (status_bits & PERI1_INTR_ST_FAULTADDR_M) >> PERI1_INTR_ST_FAULTADDR_S;
|
||||
uint32_t high_bits = (status_bits & PERI1_INTR_ST_OP_HIGH_BITS) ? PERI1_RTCSLOW_INTR_ST_FAULTADDR_HI_0 : 0;
|
||||
return (uint32_t *)(fault_address | high_bits);
|
||||
}
|
||||
|
||||
static inline bool esp_memprot_peri1_rtcslow_is_intr_mine(void)
|
||||
{
|
||||
if (esp_memprot_dram0_is_assoc_intr()) {
|
||||
uint32_t *faulting_address = esp_memprot_peri1_rtcslow_get_fault_address();
|
||||
return (uint32_t)faulting_address >= PERI1_RTCSLOW_ADDRESS_LOW && (uint32_t)faulting_address <= PERI1_RTCSLOW_ADDRESS_HIGH;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri1_rtcslow_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr)
|
||||
{
|
||||
uint32_t addr = (uint32_t)split_addr;
|
||||
|
||||
//check split address is WORD aligned
|
||||
uint32_t reg_split_addr = addr >> 2;
|
||||
assert(addr == (reg_split_addr << 2));
|
||||
reg_split_addr &= DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR_M;
|
||||
|
||||
//prepare high & low permission mask
|
||||
uint32_t permission_mask = 0;
|
||||
if (lw) {
|
||||
permission_mask |= DPORT_PMS_PRO_DPORT_RTCSLOW_L_W;
|
||||
}
|
||||
if (lr) {
|
||||
permission_mask |= DPORT_PMS_PRO_DPORT_RTCSLOW_L_R;
|
||||
}
|
||||
if (hw) {
|
||||
permission_mask |= DPORT_PMS_PRO_DPORT_RTCSLOW_H_W;
|
||||
}
|
||||
if (hr) {
|
||||
permission_mask |= DPORT_PMS_PRO_DPORT_RTCSLOW_H_R;
|
||||
}
|
||||
|
||||
//write PERIBUS1 RTC SLOW cfg register
|
||||
DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG, reg_split_addr | permission_mask);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri1_rtcslow_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr)
|
||||
{
|
||||
*lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_W);
|
||||
*lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_R);
|
||||
*hw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_W);
|
||||
*hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_R);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri1_rtcslow_set_read_perm(bool lr, bool hr)
|
||||
{
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_R, lr ? 1 : 0);
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_R, hr ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri1_rtcslow_set_write_perm(bool lw, bool hw)
|
||||
{
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_L_W, lw ? 1 : 0);
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DPORT_1_REG, DPORT_PMS_PRO_DPORT_RTCSLOW_H_W, hw ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri1_rtcslow_get_conf_reg(void)
|
||||
{
|
||||
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ========================================================================================
|
||||
* === PeriBus2 common
|
||||
* ========================================================================================
|
||||
*/
|
||||
//PeriBus2 interrupt status bitmasks
|
||||
#define PERI2_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1
|
||||
#define PERI2_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1
|
||||
#define PERI2_INTR_ST_FAULTADDR_M 0xFFFFFFFC //(bits 31:2 in the reg)
|
||||
|
||||
static inline void esp_memprot_peri2_clear_intr(void)
|
||||
{
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_get_intr_source_num(void)
|
||||
{
|
||||
return ETS_PMS_PRO_AHB_ILG_INTR_SOURCE;
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_intr_ena(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_EN);
|
||||
} else {
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_EN);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_get_ctrl_reg(void)
|
||||
{
|
||||
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_AHB_3_REG);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_get_fault_reg(void)
|
||||
{
|
||||
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_AHB_4_REG);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype)
|
||||
{
|
||||
uint32_t status_bits = esp_memprot_peri2_get_fault_reg();
|
||||
*op_type = (uint32_t)status_bits & PERI2_INTR_ST_OP_RW_BIT;
|
||||
*op_subtype = (uint32_t)status_bits & PERI2_INTR_ST_OP_TYPE_BIT;
|
||||
}
|
||||
|
||||
static inline bool esp_memprot_peri2_is_assoc_intr(void)
|
||||
{
|
||||
return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_INTR) > 0;
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_get_intr_ena_bit(void)
|
||||
{
|
||||
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_EN);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_get_intr_on_bit(void)
|
||||
{
|
||||
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_INTR);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_get_intr_clr_bit(void)
|
||||
{
|
||||
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_get_lock_reg(void)
|
||||
{
|
||||
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_AHB_0_REG);
|
||||
}
|
||||
|
||||
//resets automatically on CPU restart
|
||||
static inline void esp_memprot_peri2_set_lock(void)
|
||||
{
|
||||
DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_0_REG, DPORT_PMS_PRO_AHB_LOCK);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_get_lock_bit(void)
|
||||
{
|
||||
return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_0_REG, DPORT_PMS_PRO_AHB_LOCK);
|
||||
}
|
||||
|
||||
static inline uint32_t *esp_memprot_peri2_rtcslow_get_fault_address(void)
|
||||
{
|
||||
uint32_t status_bits = esp_memprot_peri2_get_fault_reg();
|
||||
return (uint32_t *)(status_bits & PERI2_INTR_ST_FAULTADDR_M);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ========================================================================================
|
||||
* === PeriBus2 RTC SLOW 0 (AHB0)
|
||||
* ========================================================================================
|
||||
*/
|
||||
#define PERI2_RTCSLOW_0_ADDRESS_BASE 0x50000000
|
||||
#define PERI2_RTCSLOW_0_ADDRESS_LOW PERI2_RTCSLOW_0_ADDRESS_BASE
|
||||
#define PERI2_RTCSLOW_0_ADDRESS_HIGH PERI2_RTCSLOW_0_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE
|
||||
|
||||
static inline bool esp_memprot_peri2_rtcslow_0_is_intr_mine(void)
|
||||
{
|
||||
if (esp_memprot_peri2_is_assoc_intr()) {
|
||||
uint32_t *faulting_address = esp_memprot_peri2_rtcslow_get_fault_address();
|
||||
return (uint32_t)faulting_address >= PERI2_RTCSLOW_0_ADDRESS_LOW && (uint32_t)faulting_address <= PERI2_RTCSLOW_0_ADDRESS_HIGH;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_0_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx)
|
||||
{
|
||||
uint32_t addr = (uint32_t)split_addr;
|
||||
|
||||
//check split address is WORD aligned
|
||||
uint32_t reg_split_addr = addr >> 2;
|
||||
assert(addr == (reg_split_addr << 2));
|
||||
reg_split_addr &= DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR_M;
|
||||
|
||||
//prepare high & low permission mask
|
||||
uint32_t permission_mask = 0;
|
||||
if (lw) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_0_L_W;
|
||||
}
|
||||
if (lr) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_0_L_R;
|
||||
}
|
||||
if (lx) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_0_L_F;
|
||||
}
|
||||
if (hw) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_0_H_W;
|
||||
}
|
||||
if (hr) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_0_H_R;
|
||||
}
|
||||
if (hx) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_0_H_F;
|
||||
}
|
||||
|
||||
//write PERIBUS1 RTC SLOW cfg register
|
||||
DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_1_REG, reg_split_addr | permission_mask);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx)
|
||||
{
|
||||
*lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_W);
|
||||
*lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_R);
|
||||
*lx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_F);
|
||||
*hw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_W);
|
||||
*hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_R);
|
||||
*hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_F);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_0_set_read_perm(bool lr, bool hr)
|
||||
{
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_R, lr ? 1 : 0);
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_R, hr ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_0_set_write_perm(bool lw, bool hw)
|
||||
{
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_W, lw ? 1 : 0);
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_W, hw ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_0_set_exec_perm(bool lx, bool hx)
|
||||
{
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_L_F, lx ? 1 : 0);
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_1_REG, DPORT_PMS_PRO_AHB_RTCSLOW_0_H_F, hx ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_rtcslow_0_get_conf_reg(void)
|
||||
{
|
||||
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG);
|
||||
}
|
||||
|
||||
/**
|
||||
* ========================================================================================
|
||||
* === PeriBus2 RTC SLOW 1 (AHB1)
|
||||
* ========================================================================================
|
||||
*/
|
||||
#define PERI2_RTCSLOW_1_ADDRESS_BASE 0x60021000
|
||||
#define PERI2_RTCSLOW_1_ADDRESS_LOW PERI2_RTCSLOW_1_ADDRESS_BASE
|
||||
#define PERI2_RTCSLOW_1_ADDRESS_HIGH PERI2_RTCSLOW_1_ADDRESS_LOW + RTCSLOW_MEMORY_SIZE
|
||||
|
||||
|
||||
static inline bool esp_memprot_peri2_rtcslow_1_is_intr_mine(void)
|
||||
{
|
||||
if (esp_memprot_peri2_is_assoc_intr()) {
|
||||
uint32_t *faulting_address = esp_memprot_peri2_rtcslow_get_fault_address();
|
||||
return (uint32_t)faulting_address >= PERI2_RTCSLOW_1_ADDRESS_LOW && (uint32_t)faulting_address <= PERI2_RTCSLOW_1_ADDRESS_HIGH;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_1_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx)
|
||||
{
|
||||
uint32_t addr = (uint32_t)split_addr;
|
||||
|
||||
//check split address is WORD aligned
|
||||
uint32_t reg_split_addr = addr >> 2;
|
||||
assert(addr == (reg_split_addr << 2));
|
||||
reg_split_addr &= DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR_M;
|
||||
|
||||
//prepare high & low permission mask
|
||||
uint32_t permission_mask = 0;
|
||||
if (lw) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_1_L_W;
|
||||
}
|
||||
if (lr) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_1_L_R;
|
||||
}
|
||||
if (lx) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_1_L_F;
|
||||
}
|
||||
if (hw) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_1_H_W;
|
||||
}
|
||||
if (hr) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_1_H_R;
|
||||
}
|
||||
if (hx) {
|
||||
permission_mask |= DPORT_PMS_PRO_AHB_RTCSLOW_1_H_F;
|
||||
}
|
||||
|
||||
//write PERIBUS1 RTC SLOW cfg register
|
||||
DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_2_REG, reg_split_addr | permission_mask);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx)
|
||||
{
|
||||
*lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_W);
|
||||
*lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_R);
|
||||
*lx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_F);
|
||||
*hw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_W);
|
||||
*hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_R);
|
||||
*hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_F);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_1_set_read_perm(bool lr, bool hr)
|
||||
{
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_R, lr ? 1 : 0);
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_R, hr ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_1_set_write_perm(bool lw, bool hw)
|
||||
{
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_W, lw ? 1 : 0);
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_W, hw ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline void esp_memprot_peri2_rtcslow_1_set_exec_perm(bool lx, bool hx)
|
||||
{
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_L_F, lx ? 1 : 0);
|
||||
DPORT_REG_SET_FIELD(DPORT_PMS_PRO_AHB_2_REG, DPORT_PMS_PRO_AHB_RTCSLOW_1_H_F, hx ? 1 : 0);
|
||||
}
|
||||
|
||||
static inline uint32_t esp_memprot_peri2_rtcslow_1_get_conf_reg(void)
|
||||
{
|
||||
return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_2_REG);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -415,6 +415,12 @@ test_app_test_003:
|
|||
- ESP32
|
||||
- Example_PPP
|
||||
|
||||
test_app_test_004:
|
||||
extends: .test_app_template
|
||||
tags:
|
||||
- ESP32S2
|
||||
- Example_GENERIC
|
||||
|
||||
component_ut_test_001:
|
||||
extends: .component_ut_template
|
||||
tags:
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32s2")
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(test_memprot)
|
||||
|
||||
target_link_libraries(${project_elf} "-Wl,--wrap=esp_panic_handler")
|
||||
|
||||
endif()
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import ttfw_idf
|
||||
from tiny_test_fw import Utility
|
||||
|
||||
|
||||
mem_test = [
|
||||
['IRAM0_SRAM', 'WRX'],
|
||||
['IRAM0_RTCFAST', 'WRX'],
|
||||
['DRAM0_SRAM', 'WR'],
|
||||
['DRAM0_RTCFAST', 'WR'],
|
||||
['PERI1_RTCSLOW', 'WR'],
|
||||
['PERI2_RTCSLOW_0', 'WRX'],
|
||||
['PERI2_RTCSLOW_1', 'WRX']
|
||||
]
|
||||
|
||||
|
||||
@ttfw_idf.idf_custom_test(env_tag="Example_GENERIC", target="esp32s2", group="test-apps")
|
||||
def test_memprot(env, extra_data):
|
||||
|
||||
dut = env.get_dut("memprot", "tools/test_apps/system/memprot")
|
||||
dut.start_app()
|
||||
|
||||
for i in mem_test:
|
||||
if 'R' in i[1]:
|
||||
dut.expect(i[0] + " read low: OK")
|
||||
dut.expect(i[0] + " read high: OK")
|
||||
if 'W' in i[1]:
|
||||
dut.expect(i[0] + " write low: OK")
|
||||
dut.expect(i[0] + " write high: OK")
|
||||
if 'X' in i[1]:
|
||||
dut.expect(i[0] + " exec low: OK")
|
||||
dut.expect(i[0] + " exec high: OK")
|
||||
|
||||
Utility.console_log("Memprot test done")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_memprot()
|
|
@ -0,0 +1,2 @@
|
|||
idf_component_register(SRCS "test_memprot_main.c" "test_panic.c"
|
||||
INCLUDE_DIRS "")
|
|
@ -0,0 +1,484 @@
|
|||
/* MEMPROT IramDram testing code */
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp32s2/memprot.h"
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
/*
|
||||
* ESP32S2 MEMORY PROTECTION MODULE TEST
|
||||
* =====================================
|
||||
*
|
||||
* In order to safely test all the mem_prot features, this test uses a proprietary setting
|
||||
* for all splitting addresses, ie it partially overrides production settings.
|
||||
* Each operation is tested at [test-splitting-addr - 16B] (low region) and
|
||||
* [test-splitting-addr + 16B] (high region). Complete testing scheme
|
||||
* is depicted below, the addresses used come from this application binary:
|
||||
*
|
||||
* ********************************************************************************************
|
||||
*
|
||||
* IRAM0 SRAM (320kB) DRAM0
|
||||
* ===========================
|
||||
* (_iram_text_end) | | (_data_start)
|
||||
* 0x4002B51C(!) <-------- real splt.addr --------> 0x3FFBB520
|
||||
* | |
|
||||
* 0x4002DA30 <---|-------------------------|--> 0x3FFBDA30
|
||||
* | test buffer (64 kB) |
|
||||
* | ... |
|
||||
* 0x40035A30 <-------- test splt.addr --------> 0x3FFC5A30
|
||||
* | ... |
|
||||
* |-------------------------|
|
||||
* | |
|
||||
* ===========================
|
||||
*
|
||||
* RTC_FAST (8kB)
|
||||
* (_rtc_text_end) =========================== (_rtc_dummy_end)
|
||||
* 0x40070000 <-------- real splt.addr --------> 0x3FF9E000
|
||||
* | |
|
||||
* | test buffer (7 kB) |
|
||||
* | ... |
|
||||
* 0x40070E00 <-------- test splt.addr --------> 0x3FF9EE00
|
||||
* | ... |
|
||||
* |-------------------------|
|
||||
* | |
|
||||
* ===========================
|
||||
*
|
||||
* ********************************************************************************************
|
||||
*
|
||||
* PERIBUS_1 RTC_SLOW (8/768kB) PERIBUS_2_0 PERIBUS_2_1
|
||||
* ===========================
|
||||
* | |
|
||||
* 0x3F421000 <-------- real splt.addr --------> 0x50000000 0x60021000
|
||||
* | |
|
||||
* | test buffer (7 kB) |
|
||||
* | ... |
|
||||
* 0x3F421E00 <-------- test splt.addr --------> 0x50000E00 0x60021E00
|
||||
* | ... |
|
||||
* |-------------------------|
|
||||
* | |
|
||||
* ===========================
|
||||
*
|
||||
* ********************************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* !!!IMPORTANT!!!
|
||||
* a0 needs to be saved/restored manually (not clobbered) to avoid return address corruption
|
||||
* caused by ASM block handling
|
||||
*/
|
||||
#define CODE_EXEC(code_buf, param, res) \
|
||||
asm volatile ( \
|
||||
"mov a3, a0\n\t" \
|
||||
"movi a2," #param "\n\t" \
|
||||
"callx0 %1\n\t" \
|
||||
"mov %0,a2\n\t" \
|
||||
"mov a0, a3\n\t" \
|
||||
: "=r"(res) \
|
||||
: "r"(code_buf) \
|
||||
: "a2", "a3" );
|
||||
|
||||
/* Binary code for the following asm:
|
||||
*
|
||||
.type _testfunc,@function
|
||||
.global _testfunc
|
||||
.align 4
|
||||
|
||||
_testfunc:
|
||||
slli a2, a2, 1
|
||||
ret.n
|
||||
*/
|
||||
static uint8_t fnc_call0_buff[] = {0xf0, 0x22, 0x11, 0x0d, 0xf0, 0x00, 0x00, 0x00};
|
||||
|
||||
#define SRAM_DUMMY_BUFFER_SIZE 64*1024
|
||||
#define RTCFAST_DUMMY_BUFFER_SIZE 7*1024
|
||||
#define RTCSLOW_DUMMY_BUFFER_SIZE 7*1024
|
||||
|
||||
volatile bool g_override_illegal_instruction = false;
|
||||
|
||||
static uint8_t sram_dummy_buffer[SRAM_DUMMY_BUFFER_SIZE] = {0};
|
||||
static uint8_t RTC_FAST_ATTR rtcfast_dummy_buffer[RTCFAST_DUMMY_BUFFER_SIZE] = {0};
|
||||
static uint8_t RTC_SLOW_ATTR rtcslow_dummy_buffer[RTCSLOW_DUMMY_BUFFER_SIZE] = {0};
|
||||
|
||||
|
||||
/* ********************************************************************************************
|
||||
* testing regions and splitting address scheme
|
||||
*
|
||||
*/
|
||||
static uint32_t *test_memprot_dram0_sram_get_min_split_addr(void)
|
||||
{
|
||||
return (uint32_t *)(sram_dummy_buffer + sizeof(sram_dummy_buffer) / 2);
|
||||
}
|
||||
|
||||
static uint32_t *test_memprot_dram0_rtcfast_get_min_split_addr(void)
|
||||
{
|
||||
return (uint32_t *)(rtcfast_dummy_buffer + sizeof(rtcfast_dummy_buffer) / 2);
|
||||
}
|
||||
|
||||
static uint32_t *test_memprot_iram0_sram_get_min_split_addr(void)
|
||||
{
|
||||
return (uint32_t *)
|
||||
((uint32_t)test_memprot_dram0_sram_get_min_split_addr() +
|
||||
+ esp_memprot_get_low_limit(MEMPROT_IRAM0_SRAM)
|
||||
- esp_memprot_get_low_limit(MEMPROT_DRAM0_SRAM));
|
||||
}
|
||||
|
||||
static uint32_t *test_memprot_iram0_rtcfast_get_min_split_addr(void)
|
||||
{
|
||||
return (uint32_t *)
|
||||
((uint32_t)test_memprot_dram0_rtcfast_get_min_split_addr()
|
||||
+ esp_memprot_get_low_limit(MEMPROT_IRAM0_RTCFAST)
|
||||
- esp_memprot_get_low_limit(MEMPROT_DRAM0_RTCFAST));
|
||||
}
|
||||
|
||||
static uint32_t *test_memprot_peri2_rtcslow_0_get_min_split_addr(void)
|
||||
{
|
||||
return (uint32_t *)(rtcslow_dummy_buffer + sizeof(rtcslow_dummy_buffer) / 2);
|
||||
}
|
||||
|
||||
static uint32_t *test_memprot_peri1_rtcslow_get_min_split_addr(void)
|
||||
{
|
||||
return (uint32_t *)
|
||||
((uint32_t)test_memprot_peri2_rtcslow_0_get_min_split_addr()
|
||||
- (esp_memprot_get_low_limit(MEMPROT_PERI2_RTCSLOW_0)
|
||||
- esp_memprot_get_low_limit(MEMPROT_PERI1_RTCSLOW)));
|
||||
}
|
||||
|
||||
static uint32_t *test_memprot_peri2_rtcslow_1_get_min_split_addr(void)
|
||||
{
|
||||
return (uint32_t *)
|
||||
((uint32_t)test_memprot_peri2_rtcslow_0_get_min_split_addr()
|
||||
+ esp_memprot_get_low_limit(MEMPROT_PERI2_RTCSLOW_1)
|
||||
- esp_memprot_get_low_limit(MEMPROT_PERI2_RTCSLOW_0));
|
||||
}
|
||||
|
||||
static uint32_t *test_memprot_get_split_addr(mem_type_prot_t mem_type)
|
||||
{
|
||||
switch (mem_type) {
|
||||
case MEMPROT_IRAM0_SRAM:
|
||||
return test_memprot_iram0_sram_get_min_split_addr();
|
||||
case MEMPROT_DRAM0_SRAM:
|
||||
return test_memprot_dram0_sram_get_min_split_addr();
|
||||
case MEMPROT_IRAM0_RTCFAST:
|
||||
return test_memprot_iram0_rtcfast_get_min_split_addr();
|
||||
case MEMPROT_DRAM0_RTCFAST:
|
||||
return test_memprot_dram0_rtcfast_get_min_split_addr();
|
||||
case MEMPROT_PERI1_RTCSLOW:
|
||||
return test_memprot_peri1_rtcslow_get_min_split_addr();
|
||||
case MEMPROT_PERI2_RTCSLOW_0:
|
||||
return test_memprot_peri2_rtcslow_0_get_min_split_addr();
|
||||
case MEMPROT_PERI2_RTCSLOW_1:
|
||||
return test_memprot_peri2_rtcslow_1_get_min_split_addr();
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* testing setup of the memory-protection module
|
||||
*/
|
||||
static void test_memprot_set_prot(uint32_t *mem_type_mask, bool use_panic_handler)
|
||||
{
|
||||
//any IRAM0/DRAM0 enable/disable call applies to all memory modules connected
|
||||
uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask;
|
||||
bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM || required_mem_prot & MEMPROT_IRAM0_RTCFAST;
|
||||
bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM || required_mem_prot & MEMPROT_DRAM0_RTCFAST;
|
||||
bool use_peri1 = required_mem_prot & MEMPROT_PERI1_RTCSLOW;
|
||||
bool use_peri2 = required_mem_prot & MEMPROT_PERI2_RTCSLOW_0 || required_mem_prot & MEMPROT_PERI2_RTCSLOW_1;
|
||||
|
||||
//disable protection
|
||||
if (use_iram0) {
|
||||
esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, false);
|
||||
}
|
||||
if (use_dram0) {
|
||||
esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, false);
|
||||
}
|
||||
if (use_peri1) {
|
||||
esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, false);
|
||||
}
|
||||
if (use_peri2) {
|
||||
esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, false);
|
||||
}
|
||||
|
||||
if ( use_panic_handler ) {
|
||||
if (use_iram0) {
|
||||
esp_memprot_intr_init(MEMPROT_IRAM0_SRAM);
|
||||
}
|
||||
if (use_dram0) {
|
||||
esp_memprot_intr_init(MEMPROT_DRAM0_SRAM);
|
||||
}
|
||||
if (use_peri1) {
|
||||
esp_memprot_intr_init(MEMPROT_PERI1_RTCSLOW);
|
||||
}
|
||||
if (use_peri2) {
|
||||
esp_memprot_intr_init(MEMPROT_PERI2_RTCSLOW_0);
|
||||
}
|
||||
}
|
||||
|
||||
//set permissions
|
||||
if (required_mem_prot & MEMPROT_IRAM0_SRAM) {
|
||||
esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, test_memprot_iram0_sram_get_min_split_addr(), true, true, true, true, true, false);
|
||||
}
|
||||
if (required_mem_prot & MEMPROT_IRAM0_RTCFAST) {
|
||||
esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, test_memprot_iram0_rtcfast_get_min_split_addr(), false, true, true, true, true, false);
|
||||
}
|
||||
if (required_mem_prot & MEMPROT_DRAM0_SRAM) {
|
||||
esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, test_memprot_dram0_sram_get_min_split_addr(), true, true, true, true);
|
||||
}
|
||||
if (required_mem_prot & MEMPROT_DRAM0_RTCFAST) {
|
||||
esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, test_memprot_dram0_rtcfast_get_min_split_addr(), false, true, true, true);
|
||||
}
|
||||
if (required_mem_prot & MEMPROT_PERI1_RTCSLOW) {
|
||||
esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, test_memprot_peri1_rtcslow_get_min_split_addr(), true, true, true, true);
|
||||
}
|
||||
if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_0) {
|
||||
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, test_memprot_peri2_rtcslow_0_get_min_split_addr(), true, true, false, true, true, false);
|
||||
}
|
||||
if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_1) {
|
||||
esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, test_memprot_peri2_rtcslow_1_get_min_split_addr(), true, true, false, true, true, false);
|
||||
}
|
||||
|
||||
//reenable protection (bus based)
|
||||
if (use_iram0) {
|
||||
esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, true);
|
||||
}
|
||||
if (use_dram0) {
|
||||
esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, true);
|
||||
}
|
||||
if (use_peri1) {
|
||||
esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, true);
|
||||
}
|
||||
if (use_peri2) {
|
||||
esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ********************************************************************************************
|
||||
* auxiliary functions
|
||||
*/
|
||||
static void __attribute__((unused)) dump_fnc_buff(uint32_t *buff)
|
||||
{
|
||||
esp_rom_printf( "0x%08X: 0x%08X-0x%08X\n", (uint32_t)buff, buff[0], buff[1] );
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) dump_bus_permissions(mem_type_prot_t mem_type)
|
||||
{
|
||||
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high;
|
||||
esp_memprot_get_permissions(mem_type, &write_perm_low, &write_perm_high, &read_perm_low, &read_perm_high, &exec_perm_low, &exec_perm_high);
|
||||
|
||||
esp_rom_printf("%s permissions: LW=%u LR=%u LX=%u HW=%u HR=%u HX=%u\n", esp_memprot_type_to_str(mem_type),
|
||||
write_perm_low, read_perm_low, exec_perm_low, write_perm_high, read_perm_high, exec_perm_high);
|
||||
}
|
||||
|
||||
static void __attribute__((unused)) dump_status_register(mem_type_prot_t mem_type)
|
||||
{
|
||||
uint32_t *faulting_address, op_type, op_subtype;
|
||||
esp_memprot_get_fault_status(mem_type, &faulting_address, &op_type, &op_subtype);
|
||||
esp_rom_printf(
|
||||
" FAULT [split addr: 0x%08X, fault addr: 0x%08X, fault status: 0x%08X]\n",
|
||||
(uint32_t)test_memprot_get_split_addr(mem_type),
|
||||
(uint32_t)faulting_address,
|
||||
esp_memprot_get_fault_reg(mem_type)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* ********************************************************************************************
|
||||
* testing functions
|
||||
*/
|
||||
static void check_test_result(mem_type_prot_t mem_type, bool expected_status)
|
||||
{
|
||||
uint32_t fault = esp_memprot_get_fault_reg(mem_type);
|
||||
|
||||
bool test_result = expected_status ? fault == 0 : fault != 0;
|
||||
if ( test_result ) {
|
||||
esp_rom_printf("OK\n");
|
||||
} else {
|
||||
dump_status_register(mem_type);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_memprot_read(mem_type_prot_t mem_type)
|
||||
{
|
||||
//get current READ & WRITE permission settings
|
||||
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high;
|
||||
esp_memprot_get_perm_read(mem_type, &write_perm_low, &write_perm_high);
|
||||
esp_memprot_get_perm_read(mem_type, &read_perm_low, &read_perm_high);
|
||||
|
||||
//get current splitting address
|
||||
volatile uint32_t *ptr = test_memprot_get_split_addr(mem_type);
|
||||
|
||||
//temporarily allow WRITE for setting the test values
|
||||
const uint32_t test_val = 100;
|
||||
esp_memprot_set_write_perm(mem_type, true, true);
|
||||
*(ptr - 4) = test_val;
|
||||
*(ptr + 4) = test_val + 1;
|
||||
esp_memprot_set_write_perm(mem_type, write_perm_low, write_perm_high);
|
||||
|
||||
//perform READ in low region
|
||||
esp_rom_printf("%s read low: ", esp_memprot_type_to_str(mem_type));
|
||||
esp_memprot_clear_intr(mem_type);
|
||||
volatile uint32_t val = *(ptr - 4);
|
||||
if ( val != 0 && val != test_val ) {
|
||||
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val );
|
||||
dump_status_register(mem_type);
|
||||
} else {
|
||||
check_test_result(mem_type, val == test_val);
|
||||
}
|
||||
|
||||
//perform read in high region
|
||||
esp_rom_printf("%s read high: ", esp_memprot_type_to_str(mem_type));
|
||||
esp_memprot_clear_intr(mem_type);
|
||||
val = *(ptr + 4);
|
||||
if ( val != 0 && val != (test_val + 1) ) {
|
||||
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
|
||||
dump_status_register(mem_type);
|
||||
} else {
|
||||
check_test_result(mem_type, val == (test_val + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_memprot_write(mem_type_prot_t mem_type)
|
||||
{
|
||||
//get current READ & WRITE permission settings
|
||||
bool write_perm_low, write_perm_high, read_perm_low, read_perm_high;
|
||||
esp_memprot_get_perm_read(mem_type, &write_perm_low, &write_perm_high);
|
||||
esp_memprot_get_perm_read(mem_type, &read_perm_low, &read_perm_high);
|
||||
|
||||
//temporarily allow READ operation
|
||||
esp_memprot_set_read_perm(mem_type, true, true);
|
||||
|
||||
//get current splitting address
|
||||
volatile uint32_t *ptr = test_memprot_get_split_addr(mem_type);
|
||||
|
||||
//perform WRITE in low region
|
||||
const uint32_t test_val = 10;
|
||||
esp_rom_printf("%s write low: ", esp_memprot_type_to_str(mem_type));
|
||||
esp_memprot_clear_intr(mem_type);
|
||||
|
||||
volatile uint32_t val = 0;
|
||||
*(ptr - 4) = test_val;
|
||||
val = *(ptr - 4);
|
||||
|
||||
if ( val != test_val && write_perm_low ) {
|
||||
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
|
||||
dump_status_register(mem_type);
|
||||
} else {
|
||||
check_test_result(mem_type, write_perm_low);
|
||||
}
|
||||
|
||||
//perform WRITE in high region
|
||||
esp_rom_printf("%s write high: ", esp_memprot_type_to_str(mem_type));
|
||||
esp_memprot_clear_intr(mem_type);
|
||||
val = 0;
|
||||
*(ptr + 4) = test_val + 1;
|
||||
val = *(ptr + 4);
|
||||
|
||||
if ( val != (test_val + 1) && write_perm_high ) {
|
||||
esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
|
||||
dump_status_register(mem_type);
|
||||
} else {
|
||||
check_test_result(mem_type, write_perm_high);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_memprot_exec(mem_type_prot_t mem_type)
|
||||
{
|
||||
//store current write permissions
|
||||
bool write_perm_low, write_perm_high;
|
||||
esp_memprot_get_perm_write(mem_type, &write_perm_low, &write_perm_high);
|
||||
|
||||
//get current EXEC permission settings
|
||||
bool exec_perm_low, exec_perm_high;
|
||||
esp_memprot_get_perm_exec(mem_type, &exec_perm_low, &exec_perm_high);
|
||||
|
||||
volatile uint32_t *fnc_ptr_low = (uint32_t *)(test_memprot_get_split_addr(mem_type) - 4);
|
||||
volatile uint32_t *fnc_ptr_high = (uint32_t *)(test_memprot_get_split_addr(mem_type) + 4);
|
||||
|
||||
//enable WRITE permission for both segments
|
||||
esp_memprot_set_write_perm(mem_type, true, true);
|
||||
|
||||
//inject the code to both low & high segments
|
||||
memcpy( (void *)fnc_ptr_low, fnc_call0_buff, sizeof(fnc_call0_buff) );
|
||||
memcpy( (void *)fnc_ptr_high, fnc_call0_buff, sizeof(fnc_call0_buff) );
|
||||
|
||||
//restore original WRITE perms
|
||||
esp_memprot_set_write_perm(mem_type, write_perm_low, write_perm_high);
|
||||
|
||||
uint32_t res = 0;
|
||||
|
||||
//LOW REGION: clear the intr flag & try to execute the code injected
|
||||
esp_memprot_clear_intr(mem_type);
|
||||
esp_rom_printf("%s exec low: ", esp_memprot_type_to_str(mem_type));
|
||||
|
||||
g_override_illegal_instruction = true;
|
||||
CODE_EXEC(fnc_ptr_low, 5, res);
|
||||
g_override_illegal_instruction = false;
|
||||
|
||||
//check results
|
||||
bool fnc_call_ok = res == 10;
|
||||
if ( fnc_call_ok ) {
|
||||
check_test_result(mem_type, exec_perm_low);
|
||||
} else {
|
||||
if ( !exec_perm_low ) {
|
||||
check_test_result(mem_type, true);
|
||||
} else {
|
||||
esp_rom_printf(" FAULT [injected code not executed]\n");
|
||||
}
|
||||
}
|
||||
|
||||
//HIGH REGION: clear the intr flag & try to execute the code injected
|
||||
esp_memprot_clear_intr(mem_type);
|
||||
esp_rom_printf("%s exec high: ", esp_memprot_type_to_str(mem_type));
|
||||
|
||||
g_override_illegal_instruction = true;
|
||||
CODE_EXEC(fnc_ptr_high, 6, res);
|
||||
g_override_illegal_instruction = false;
|
||||
|
||||
fnc_call_ok = res == 12;
|
||||
if ( fnc_call_ok ) {
|
||||
check_test_result(mem_type, exec_perm_high);
|
||||
} else {
|
||||
if ( !exec_perm_high ) {
|
||||
check_test_result(mem_type, true);
|
||||
} else {
|
||||
esp_rom_printf(" FAULT [injected code not executed]\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ********************************************************************************************
|
||||
* main test runner
|
||||
*/
|
||||
void app_main(void)
|
||||
{
|
||||
test_memprot_set_prot(NULL, false);
|
||||
|
||||
test_memprot_read(MEMPROT_IRAM0_SRAM);
|
||||
test_memprot_write(MEMPROT_IRAM0_SRAM);
|
||||
test_memprot_exec(MEMPROT_IRAM0_SRAM);
|
||||
|
||||
test_memprot_read(MEMPROT_IRAM0_RTCFAST);
|
||||
test_memprot_write(MEMPROT_IRAM0_RTCFAST);
|
||||
test_memprot_exec(MEMPROT_IRAM0_RTCFAST);
|
||||
|
||||
test_memprot_read(MEMPROT_DRAM0_SRAM);
|
||||
test_memprot_write(MEMPROT_DRAM0_SRAM);
|
||||
|
||||
test_memprot_read(MEMPROT_DRAM0_RTCFAST);
|
||||
test_memprot_write(MEMPROT_DRAM0_RTCFAST);
|
||||
|
||||
test_memprot_read(MEMPROT_PERI1_RTCSLOW);
|
||||
test_memprot_write(MEMPROT_PERI1_RTCSLOW);
|
||||
|
||||
test_memprot_read(MEMPROT_PERI2_RTCSLOW_0);
|
||||
test_memprot_write(MEMPROT_PERI2_RTCSLOW_0);
|
||||
test_memprot_exec(MEMPROT_PERI2_RTCSLOW_0);
|
||||
|
||||
test_memprot_read(MEMPROT_PERI2_RTCSLOW_1);
|
||||
test_memprot_write(MEMPROT_PERI2_RTCSLOW_1);
|
||||
test_memprot_exec(MEMPROT_PERI2_RTCSLOW_1);
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "freertos/xtensa_context.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
|
||||
extern void esp_panic_handler(panic_info_t *info);
|
||||
extern volatile bool g_override_illegal_instruction;
|
||||
|
||||
void __real_esp_panic_handler(panic_info_t *info);
|
||||
|
||||
/* Memprot test specific IllegalInstruction exception handler:
|
||||
* when testing the protection against a code execution, sample code
|
||||
* is being injected into various memory regions which produces
|
||||
* EXCCAUSE_ILLEGAL on execution attempt. Such a result is expected
|
||||
* but it causes system reboot in the standard panic handler.
|
||||
* The following variant of panic handling simply returns back to the
|
||||
* next instruction and continues normal execution.
|
||||
*
|
||||
* NOTE: if EXCCAUSE_ILLEGAL comes from a different source than the testing code
|
||||
* the behavior is undefined
|
||||
* */
|
||||
void __wrap_esp_panic_handler(panic_info_t *info)
|
||||
{
|
||||
XtExcFrame *frm = (XtExcFrame *)info->frame;
|
||||
if ( frm->exccause == EXCCAUSE_ILLEGAL && g_override_illegal_instruction == true ) {
|
||||
frm->pc = frm->a0;
|
||||
return;
|
||||
} else {
|
||||
__real_esp_panic_handler(info);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# Esp32S2 only
|
||||
CONFIG_IDF_TARGET="esp32s2"
|
||||
|
||||
# Disable automatic memory protection
|
||||
CONFIG_ESP32S2_MEMPROT_FEATURE=n
|
Ładowanie…
Reference in New Issue