esp32c3: memprot API upgrade and test application

Closes IDF-2641
This commit is contained in:
Martin Vychodil
2021-01-27 22:03:07 +01:00
committed by Angus Gratton
parent 2ed3e8b344
commit 6dfff2fdbd
23 changed files with 1464 additions and 311 deletions

View File

@@ -46,9 +46,9 @@ else()
# Process the template file through the linker script generation mechanism, and use the output for linking the
# final binary
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/ld/esp32c3.project.ld.in"
PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp32c3.project.ld")
PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp32c3.project.ld")
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32c3.peripherals.ld")
target_link_libraries(${COMPONENT_LIB} PUBLIC gcc)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u call_user_start_cpu0")

View File

@@ -26,6 +26,22 @@
extern "C" {
#endif
#ifndef IRAM_SRAM_START
#define IRAM_SRAM_START 0x4037C000
#endif
#ifndef DRAM_SRAM_START
#define DRAM_SRAM_START 0x3FC7C000
#endif
#ifndef MAP_DRAM_TO_IRAM
#define MAP_DRAM_TO_IRAM(addr) (addr - DRAM_SRAM_START + IRAM_SRAM_START)
#endif
#ifndef MAP_IRAM_TO_DRAM
#define MAP_IRAM_TO_DRAM(addr) (addr - IRAM_SRAM_START + DRAM_SRAM_START)
#endif
typedef enum {
MEMPROT_NONE = 0x00000000,
MEMPROT_IRAM0_SRAM = 0x00000001,
@@ -34,6 +50,7 @@ typedef enum {
} mem_type_prot_t;
typedef enum {
MEMPROT_SPLITLINE_NONE = 0,
MEMPROT_IRAM0_DRAM0_SPLITLINE,
MEMPROT_IRAM0_LINE_0_SPLITLINE,
MEMPROT_IRAM0_LINE_1_SPLITLINE,
@@ -42,6 +59,7 @@ typedef enum {
} split_line_t;
typedef enum {
MEMPROT_PMS_AREA_NONE = 0,
MEMPROT_IRAM0_PMS_AREA_0,
MEMPROT_IRAM0_PMS_AREA_1,
MEMPROT_IRAM0_PMS_AREA_2,
@@ -52,43 +70,386 @@ typedef enum {
MEMPROT_DRAM0_PMS_AREA_3
} pms_area_t;
typedef enum
{
MEMPROT_PMS_WORLD_0 = 0,
MEMPROT_PMS_WORLD_1,
MEMPROT_PMS_WORLD_2,
MEMPROT_PMS_WORLD_INVALID = 0xFFFFFFFF
} pms_world_t;
const char *mem_type_to_str(mem_type_prot_t mem_type);
const char *split_line_to_str(split_line_t line_type);
const char *pms_to_str(pms_area_t area_type);
typedef enum
{
MEMPROT_PMS_OP_READ = 0,
MEMPROT_PMS_OP_WRITE,
MEMPROT_PMS_OP_FETCH,
MEMPROT_PMS_OP_INVALID = 0xFFFFFFFF
} pms_operation_type_t;
void *esp_memprot_get_main_split_addr(void);
void esp_memprot_set_split_line_lock(bool lock);
/**
* @brief Converts Memory protection type to string
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type);
/**
* @brief Converts Split line type to string
*
* @param line_type Split line type (see split_line_t enum)
*/
const char *esp_memprot_split_line_to_str(split_line_t line_type);
/**
* @brief Converts PMS Area type to string
*
* @param area_type PMS Area type (see pms_area_t enum)
*/
const char *esp_memprot_pms_to_str(pms_area_t area_type);
/**
* @brief Returns PMS splitting address for given Split line type
*
* The value is taken from PMS configuration registers (IRam0 range)
* For details on split lines see 'esp_memprot_set_prot_int' function description
*
* @param line_type Split line type (see split_line_t enum)
*
* @return appropriate split line address
*/
uint32_t *esp_memprot_get_split_addr(split_line_t line_type);
/**
* @brief Returns default main IRAM/DRAM splitting address
*
* The address value is given by _iram_text_end global (IRam0 range)
* @return Main I/D split line (IRam0_DRam0_Split_Addr)
*/
void *esp_memprot_get_default_main_split_addr(void);
/**
* @brief Sets a lock for the main IRAM/DRAM splitting address
*
* Locks can be unlocked only by digital system reset
*/
void esp_memprot_set_split_line_lock(void);
/**
* @brief Gets a lock status for the main IRAM/DRAM splitting address
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_split_line_lock(void);
/**
* @brief Sets required split line address
*
* @param line_type Split line type (see split_line_t enum)
* @param line_addr target address from a memory range relevant to given line_type (IRAM/DRAM)
*/
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr);
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type, bool lock);
/**
* @brief Sets a lock for PMS Area settings of required Memory type
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type);
/**
* @brief Gets a lock status for PMS Area settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type);
/**
* @brief Sets permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
*
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag
* @param w Write permission flag
* @param x Execute permission flag
*/
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x);
/**
* @brief Gets current permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
*
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag holder
* @param w Write permission flag holder
* @param x Execute permission flag holder
*/
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x);
/**
* @brief Sets permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
*
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag
* @param w Write permission flag
*/
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w);
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type, bool lock);
/**
* @brief Gets current permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
*
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
* @param r Read permission flag holder
* @param w Write permission flag holder
*/
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w);
/**
* @brief Sets a lock for PMS interrupt monitor settings of required Memory type
*
* Locks can be unlocked only by digital system reset
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type);
/**
* @brief Gets a lock status for PMS interrupt monitor settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (locked/unlocked)
*/
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type);
/**
* @brief Enable PMS violation interrupt monitoring of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
* @param enable/disable
*/
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable);
/**
* @brief Gets enable/disable status for PMS interrupt monitor settings of required Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (enabled/disabled)
*/
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type);
/**
* @brief Gets CPU ID for currently active PMS violation interrupt
*
* @return CPU ID (CPU_PRO for ESP32C3)
*/
int IRAM_ATTR esp_memprot_intr_get_cpuid(void);
/**
* @brief Clears current interrupt ON flag for given Memory type
*
* Interrupt clearing happens in two steps:
* 1. Interrupt CLR flag is set (to clear the interrupt ON status)
* 2. Interrupt CLR flag is reset (to allow further monitoring)
* This operation is non-atomic by PMS module design
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type);
/**
* @brief Returns active PMS violation interrupt (if any)
*
* This function iterates through supported Memory type status registers
* and returns the first interrupt-on flag. If none is found active,
* MEMPROT_NONE is returned.
* Order of checking (in current version):
* 1. MEMPROT_IRAM0_SRAM
* 2. MEMPROT_DRAM0_SRAM
*
* @return mem_type Memory protection type related to active interrupt found (see mem_type_prot_t enum)
*/
mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
/**
* @brief Checks whether any violation interrupt is active
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_is_locked_any(void);
/**
* @brief Checks whether any violation interrupt is enabled
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_is_intr_ena_any(void);
uint32_t IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
/**
* @brief Checks whether any violation interrupt is enabled
*
* @return true/false (yes/no)
*/
bool IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
/**
* @brief Returns the address which caused the violation interrupt (if any)
*
* The address is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return faulting address
*/
uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type);
uint32_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type);
uint32_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type);
uint32_t IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type);
/**
* @brief Returns the World identifier of the code causing the violation interrupt (if any)
*
* The value is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return World identifier (see pms_world_t enum)
*/
pms_world_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type);
/**
* @brief Returns Read or Write operation type which caused the violation interrupt (if any)
*
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return PMS operation type relevant to mem_type parameter (se pms_operation_type_t)
*/
pms_operation_type_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type);
/**
* @brief Returns LoadStore flag of the operation type which caused the violation interrupt (if any)
*
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
* Effective only on IRam0 access
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return true/false (LoadStore bit on/off)
*/
bool IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type);
/**
* @brief Returns byte-enables for the address which caused the violation interrupt (if any)
*
* The value is taken from appropriate PMS violation status register, based given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return byte-enables
*/
uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type);
/**
* @brief Returns raw contents of DRam0 status register 1
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_1(void);
/**
* @brief Returns raw contents of DRam0 status register 2
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_2(void);
/**
* @brief Returns raw contents of IRam0 status register
*
* @return 32-bit register value
*/
uint32_t IRAM_ATTR esp_memprot_get_iram_status_reg(void);
/**
* @brief Register PMS violation interrupt in global interrupt matrix for given Memory type
*
* Memory protection components uses specific interrupt number, see ETS_MEMPROT_ERR_INUM
* The registration makes the panic-handler routine being called when the interrupt appears
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*/
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type);
/**
* @brief Convenient routine for setting the PMS defaults
*
* Called on application startup, depending on CONFIG_ESP_SYSTEM_MEMPROT_FEATURE Kconfig settings
* For implementation details see 'esp_memprot_set_prot_int' description
*
* @param invoke_panic_handler register all interrupts for panic handling (true/false)
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
* @param mem_type_mask 32-bit field of specific PMS parts to configure (see 'esp_memprot_set_prot_int')
*/
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
/**
* @brief Internal routine for setting the PMS defaults
*
* Called on application startup from within 'esp_memprot_set_prot'. Allows setting a specific splitting address
* (main I/D split line) - see the parameter 'split_addr'. If the 'split_addr' equals to NULL, default I/D split line
* is used (&_iram_text_end) and all the remaining lines share the same address.
* The function sets all the split lines and PMS areas to the same space,
* ie there is a single instruction space and single data space at the end.
* The PMS split lines and permission areas scheme described below:
*
* DRam0/DMA IRam0
* -----------------------------------------------
* ... | IRam0_PMS_0 |
* DRam0_PMS_0 ----------------------------------------------- IRam0_line1_Split_addr
* ... | IRam0_PMS_1 |
* ... ----------------------------------------------- IRam0_line0_Split_addr
* | IRam0_PMS_2 |
* =============================================== IRam0_DRam0_Split_addr (main I/D)
* | DRam0_PMS_1 |
* DRam0_DMA_line0_Split_addr ----------------------------------------------- ...
* | DRam0_PMS_2 | ...
* DRam0_DMA_line1_Split_addr ----------------------------------------------- IRam0_PMS_3
* | DRam0_PMS_3 | ...
* -----------------------------------------------
*
* Default settings provided by 'esp_memprot_set_prot_int' are as follows:
*
* DRam0/DMA IRam0
* -----------------------------------------------
* | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 |
* | DRam0_PMS_0 | IRam0_line1_Split_addr
* DRam0_DMA_line0_Split_addr | | =
* = =============================================== IRam0_line0_Split_addr
* DRam0_DMA_line1_Split_addr | | =
* | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 | IRam0_DRam0_Split_addr (main I/D)
* | IRam0_PMS_3 |
* -----------------------------------------------
*
* Once the memprot feature is locked, it can be unlocked only by digital system reset
*
* @param invoke_panic_handler register all the violation interrupts for panic handling (true/false)
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
* @param split_addr specific main I/D adrees or NULL to use default ($_iram_text_end)
* @param mem_type_mask 32-bit field of specific PMS parts to configure (members of mem_type_prot_t)
*/
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask);
/**
* @brief Returns raw contents of PMS interrupt monitor register for given Memory type
*
* @param mem_type Memory protection type (see mem_type_prot_t enum)
*
* @return 32-bit register value
*/
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type);
#ifdef __cplusplus
}
#endif

View File

@@ -369,6 +369,8 @@ SECTIONS
{
/* C3 memprot requires 512 B alignment for split lines */
. = ALIGN (0x200);
/* iram_end_test section exists for use by memprot unit tests only */
*(.iram_end_test)
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg

View File

@@ -22,34 +22,31 @@
#include "soc/dport_access.h"
#include "soc/periph_defs.h"
#include "esp_intr_alloc.h"
#include "esp_log.h"
static const char *TAG = "memprot";
#include "esp32c3/memprot.h"
#include "hal/memprot_ll.h"
#include "esp32c3/memprot.h"
#include "riscv/interrupt.h"
#include "esp_log.h"
#include "esp32c3/rom/ets_sys.h"
extern int _iram_text_end;
const char *mem_type_to_str(mem_type_prot_t mem_type)
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type)
{
switch (mem_type) {
case MEMPROT_NONE:
return "MEMPROT_NONE";
return "NONE";
case MEMPROT_IRAM0_SRAM:
return "MEMPROT_IRAM0_SRAM";
return "IRAM0_SRAM";
case MEMPROT_DRAM0_SRAM:
return "MEMPROT_DRAM0_SRAM";
return "DRAM0_SRAM";
case MEMPROT_ALL:
return "MEMPROT_ALL";
return "ALL";
default:
return "UNKNOWN";
}
}
const char *split_line_to_str(split_line_t line_type)
const char *esp_memprot_split_line_to_str(split_line_t line_type)
{
switch (line_type) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
@@ -67,7 +64,7 @@ const char *split_line_to_str(split_line_t line_type)
}
}
const char *pms_to_str(pms_area_t area_type)
const char *esp_memprot_pms_to_str(pms_area_t area_type)
{
switch (area_type) {
case MEMPROT_IRAM0_PMS_AREA_0:
@@ -94,14 +91,32 @@ const char *pms_to_str(pms_area_t area_type)
/* split lines */
void *esp_memprot_get_main_split_addr()
void *esp_memprot_get_default_main_split_addr()
{
return &_iram_text_end;
}
void esp_memprot_set_split_line_lock(bool lock)
uint32_t *esp_memprot_get_split_addr(split_line_t line_type)
{
memprot_ll_set_iram0_dram0_split_line_lock(lock);
switch ( line_type ) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
return memprot_ll_get_iram0_split_line_main_I_D();
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
return memprot_ll_get_iram0_split_line_I_0();
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
return memprot_ll_get_iram0_split_line_I_1();
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
return memprot_ll_get_dram0_split_line_D_0();
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
return memprot_ll_get_dram0_split_line_D_1();
default:
abort();
}
}
void esp_memprot_set_split_line_lock()
{
memprot_ll_set_iram0_dram0_split_line_lock();
}
bool esp_memprot_get_split_line_lock()
@@ -111,11 +126,8 @@ bool esp_memprot_get_split_line_lock()
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr)
{
uint32_t addr = (uint32_t)line_addr;
ESP_LOGD(TAG, "Setting split line %s, addr: 0x%08X", split_line_to_str(line_type), addr);
//split-line must be divisible by 512
assert( addr % 0x200 == 0 );
//split-line must be divisible by 512 (PMS module restriction)
assert( ((uint32_t)line_addr) % 0x200 == 0 );
switch ( line_type ) {
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
@@ -134,52 +146,41 @@ void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr)
memprot_ll_set_dram0_split_line_D_1(line_addr);
break;
default:
ESP_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", addr);
abort();
}
}
// TODO - get split lines
/* PMS */
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type, bool lock)
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type)
{
ESP_LOGD(TAG, "esp_memprot_set_pms_lock(%s, %s)", mem_type_to_str(mem_type), lock ? "true" : "false");
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_pms_lock(lock);
memprot_ll_iram0_set_pms_lock();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_pms_lock(lock);
memprot_ll_dram0_set_pms_lock();
break;
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
{
ESP_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_pms_lock();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_pms_lock();
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
{
ESP_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", pms_to_str(area_type), r, w, x);
switch ( area_type ) {
case MEMPROT_IRAM0_PMS_AREA_0:
memprot_ll_iram0_set_pms_area_0(r, w, x);
@@ -194,15 +195,32 @@ void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
memprot_ll_iram0_set_pms_area_3(r, w, x);
break;
default:
ESP_LOGE(TAG, "Invalid area_type %d", pms_to_str(area_type));
abort();
}
}
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x)
{
switch ( area_type ) {
case MEMPROT_IRAM0_PMS_AREA_0:
memprot_ll_iram0_get_pms_area_0(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_1:
memprot_ll_iram0_get_pms_area_1(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_2:
memprot_ll_iram0_get_pms_area_2(r, w, x);
break;
case MEMPROT_IRAM0_PMS_AREA_3:
memprot_ll_iram0_get_pms_area_3(r, w, x);
break;
default:
abort();
}
}
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
{
ESP_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", pms_to_str(area_type), r, w);
switch ( area_type ) {
case MEMPROT_DRAM0_PMS_AREA_0:
memprot_ll_dram0_set_pms_area_0(r, w);
@@ -217,52 +235,61 @@ void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
memprot_ll_dram0_set_pms_area_3(r, w);
break;
default:
ESP_LOGE(TAG, "Invalid area_type %d", pms_to_str(area_type));
abort();
}
}
/* TODO - get single areas */
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w)
{
switch ( area_type ) {
case MEMPROT_DRAM0_PMS_AREA_0:
memprot_ll_dram0_get_pms_area_0(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_1:
memprot_ll_dram0_get_pms_area_1(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_2:
memprot_ll_dram0_get_pms_area_2(r, w);
break;
case MEMPROT_DRAM0_PMS_AREA_3:
memprot_ll_dram0_get_pms_area_3(r, w);
break;
default:
abort();
}
}
/* monitor */
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type, bool lock)
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type)
{
ESP_LOGD(TAG, "esp_memprot_set_monitor_lock(%s, %s)", mem_type_to_str(mem_type), lock ? "true" : "false");
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_lock(lock);
memprot_ll_iram0_set_monitor_lock();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_set_monitor_lock(lock);
memprot_ll_dram0_set_monitor_lock();
break;
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
{
ESP_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_lock();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_lock();
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
{
ESP_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_set_monitor_en(enable);
@@ -271,22 +298,18 @@ void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
memprot_ll_dram0_set_monitor_en(enable);
break;
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
{
ESP_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_en();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_en();
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
@@ -298,17 +321,17 @@ bool esp_memprot_is_intr_ena_any()
void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type)
{
ESP_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", mem_type_to_str(mem_type));
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
memprot_ll_iram0_clear_monitor_intr();
memprot_ll_iram0_reset_clear_monitor_intr();
break;
case MEMPROT_DRAM0_SRAM:
memprot_ll_dram0_clear_monitor_intr();
memprot_ll_dram0_reset_clear_monitor_intr();
break;
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
@@ -334,15 +357,14 @@ bool esp_memprot_is_locked_any()
esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM);
}
uint32_t esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_intr();
return memprot_ll_iram0_get_monitor_status_intr() == 1;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_intr();
return memprot_ll_dram0_get_monitor_status_intr() == 1;
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
@@ -355,44 +377,50 @@ uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type)
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_addr();
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
uint32_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
{
uint32_t world = 0;
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_world();
world = memprot_ll_iram0_get_monitor_status_fault_world();
break;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_world();
world = memprot_ll_dram0_get_monitor_status_fault_world();
break;
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
switch ( world ) {
case 0x01: return MEMPROT_PMS_WORLD_0;
case 0x10: return MEMPROT_PMS_WORLD_1;
default: return MEMPROT_PMS_WORLD_INVALID;
}
}
uint32_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_wr();
return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_wr();
return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
uint32_t esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
{
switch ( mem_type ) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_status_fault_loadstore();
return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1;
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
@@ -403,7 +431,6 @@ uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type)
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_status_fault_byte_en();
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
}
@@ -415,8 +442,6 @@ int esp_memprot_intr_get_cpuid()
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
{
ESP_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", mem_type_to_str(mem_type));
ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
switch (mem_type) {
@@ -427,7 +452,6 @@ void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
break;
default:
ESP_LOGE(TAG, "Invalid mem_type (%s), aborting", mem_type_to_str(mem_type));
abort();
}
@@ -445,8 +469,6 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask)
{
ESP_LOGD(TAG, "esp_memprot_set_prot(panic_handler: %u, lock: %u, split.addr: 0x%08X, mem.types: 0x%08X", invoke_panic_handler, lock_feature, (uint32_t)split_addr, (uint32_t)mem_type_mask);
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;
bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM;
@@ -474,7 +496,7 @@ void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void
}
//set split lines (must-have for all mem_types)
const void *line_addr = split_addr == NULL ? esp_memprot_get_main_split_addr() : split_addr;
const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr;
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr);
esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr);
@@ -507,14 +529,41 @@ void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void
//lock if required
if (lock_feature) {
esp_memprot_set_split_line_lock(true);
esp_memprot_set_split_line_lock();
if (use_iram0) {
esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM, true);
esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM, true);
esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM);
esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM);
}
if (use_dram0) {
esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM, true);
esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM, true);
esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM);
esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM);
}
}
}
uint32_t esp_memprot_get_dram_status_reg_1()
{
return memprot_ll_dram0_get_monitor_status_register_1();
}
uint32_t esp_memprot_get_dram_status_reg_2()
{
return memprot_ll_dram0_get_monitor_status_register_2();
}
uint32_t esp_memprot_get_iram_status_reg()
{
return memprot_ll_iram0_get_monitor_status_register();
}
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type)
{
switch (mem_type) {
case MEMPROT_IRAM0_SRAM:
return memprot_ll_iram0_get_monitor_enable_register();
case MEMPROT_DRAM0_SRAM:
return memprot_ll_dram0_get_monitor_enable_register();
default:
abort();
}
}