diff --git a/components/esp_hw_support/include/soc/esp32s2/memprot.h b/components/esp_hw_support/include/soc/esp32s2/memprot.h index 55ad7258bb..0ebd647457 100644 --- a/components/esp_hw_support/include/soc/esp32s2/memprot.h +++ b/components/esp_hw_support/include/soc/esp32s2/memprot.h @@ -4,7 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ - /* INTERNAL API * generic interface to MMU memory protection features */ @@ -13,6 +12,7 @@ #include #include #include "esp_attr.h" +#include "esp_err.h" #ifdef __cplusplus extern "C" { @@ -43,6 +43,8 @@ extern "C" { #define MEMPROT_UNLOCK false #define DEF_SPLIT_LINE NULL +#define MEMPROT_INVALID_ADDRESS -1 + //memory range types typedef enum { MEMPROT_NONE = 0x00000000, @@ -69,23 +71,27 @@ typedef enum { uint32_t *IRAM_ATTR esp_memprot_get_split_addr(mem_type_prot_t mem_type); /** - * @brief Initializes illegal memory access control (MMU) for required memory section. + * @brief Initializes illegal memory access control for required memory section. * * All memory access interrupts share ETS_MEMACCESS_ERR_INUM input channel, it is caller's * responsibility to properly detect actual intr. source as well as possible prioritization in case * of multiple source reported during one intr.handling routine run * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param mem_type Memory protection area type (see mem_type_prot_t enum)\ + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_intr_init(mem_type_prot_t mem_type); +esp_err_t esp_memprot_intr_init(mem_type_prot_t mem_type); /** * @brief Enable/disable the memory protection interrupt * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param enable enable/disable + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); +esp_err_t esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); /** * @brief Sets a request for clearing interrupt-on flag for specified memory region (register write) @@ -94,8 +100,10 @@ void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable); * Should be used only after the real interrupt appears, typically as the last step in interrupt handler's routine. * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_clear_intr(mem_type_prot_t mem_type); +esp_err_t esp_memprot_clear_intr(mem_type_prot_t mem_type); /** * @brief Detects which memory protection interrupt is active @@ -114,10 +122,11 @@ mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void); * @brief Gets interrupt status register contents for specified memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param fault_reg_val Contents of status register * - * @return Contents of status register + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type, uint32_t *fault_reg_val); /** * @brief Get details of given interrupt status @@ -130,8 +139,9 @@ uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type); * @param op_subtype Additional info for op_type [out] * IRAM0: 0 - instruction segment access, 1 - data segment access * DRAM0: 0 - non-atomic operation, 1 - atomic operation + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void IRAM_ATTR esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype); +esp_err_t IRAM_ATTR esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype); /** * @brief Gets string representation of required memory region identifier @@ -155,26 +165,30 @@ bool esp_memprot_is_locked_any(void); * Locks can be unlocked only by digital system reset * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_lock(mem_type_prot_t mem_type); +esp_err_t esp_memprot_set_lock(mem_type_prot_t mem_type); /** * @brief Gets lock status for required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param locked Settings locked: true/false (locked/unlocked) * - * @return true/false (locked/unlocked) + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -bool esp_memprot_get_lock(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_lock(mem_type_prot_t mem_type, bool *locked); /** * @brief Gets permission control configuration register contents for required memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param conf_reg_val Permission control register contents * - * @return Permission control register contents + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type, uint32_t *conf_reg_val); /** * @brief Gets interrupt permission settings for unified management block @@ -182,21 +196,23 @@ uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type); * Gets interrupt permission settings register contents for required memory region, returns settings for unified management blocks * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param perm_reg Permission settings register contents * - * @return Permission settings register contents + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type, uint32_t *perm_reg); /** * @brief Gets interrupt permission settings for split management block * - * Gets interrupt permission settings register contents for required memory region, returns settings for split management blocks + * Gets interrupt permission settings register contents for required memory region (unified management blocks) * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @return split_reg Unified management settings register contents * - * @return Permission settings register contents + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type, uint32_t *split_reg); /** * @brief Detects whether any of the memory protection interrupts is enabled @@ -209,28 +225,30 @@ bool esp_memprot_is_intr_ena_any(void); * @brief Gets interrupt-enabled flag for given memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param enable_bit Interrupt-enabled flag * - * @return Interrupt-enabled value + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type, uint32_t *enable_bit); /** * @brief Gets interrupt-active flag for given memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param intr_on_bit Interrupt-active flag * - * @return Interrupt-active value - */ -uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type); + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ +esp_err_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type, uint32_t *intr_on_bit); /** * @brief Gets interrupt-clear request flag for given memory region * * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param clear_bit Interrupt-clear request flag * - * @return Interrupt-clear request value + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type); +esp_err_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type, uint32_t *clear_bit); /** * @brief Gets read permission value for specified block and memory region @@ -240,10 +258,11 @@ uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type); * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param block Memory block identifier (0-3) + * @param read_bit Read permission value for required block * - * @return Read permission value for required block + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block); +esp_err_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *read_bit); /** * @brief Gets write permission value for specified block and memory region @@ -253,10 +272,11 @@ uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t b * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param block Memory block identifier (0-3) + * @param write_bit Write permission value for required block * - * @return Write permission value for required block + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block); +esp_err_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *write_bit); /** * @brief Gets execute permission value for specified block and memory region @@ -266,10 +286,11 @@ uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t * * @param mem_type Memory protection area type (see mem_type_prot_t enum) * @param block Memory block identifier (0-3) + * @param exec_bit Execute permission value for required block * - * @return Execute permission value for required block + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block); +esp_err_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *exec_bit); /** * @brief Sets permissions for specified block in DRAM region @@ -281,8 +302,10 @@ uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t b * @param block Memory block identifier (0-3) * @param write_perm Write permission flag * @param read_perm Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm); +esp_err_t esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm); /** * @brief Sets permissions for high and low memory segment in DRAM region @@ -297,8 +320,10 @@ void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t bloc * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); +esp_err_t esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); /** * @brief Sets permissions for specified block in IRAM region @@ -306,12 +331,17 @@ void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, b * Sets Read, Write and Execute permission for specified unified-management block (0-3) in given memory region. * Applicable only to IRAM memory types * - * @param mem_type Memory protection area type (see mem_type_prot_t enum) + * @param mem_type Memory protection area type (MEMPROT_IRAM0_SRAM) * @param block Memory block identifier (0-3) * @param write_perm Write permission flag + * @param read_perm Read permission flag * @param exec_perm Execute permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type + * ESP_ERR_INVALID_ARG on incorrect block number */ -void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm); +esp_err_t esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm); /** * @brief Sets permissions for high and low memory segment in IRAM region @@ -328,8 +358,10 @@ void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t bloc * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); +esp_err_t esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx); /** * @brief Activates memory protection for all supported memory region types @@ -339,8 +371,10 @@ 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) + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask); +esp_err_t esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask); /** * @brief Get permission settings bits for IRAM0 split mgmt. Only IRAM0 memory types allowed @@ -352,8 +386,10 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -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); +esp_err_t 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 DRAM0 split mgmt. Only DRAM0 memory types allowed @@ -363,8 +399,10 @@ void esp_memprot_get_perm_split_bits_iram(mem_type_prot_t mem_type, bool *lw, bo * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); +esp_err_t 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 @@ -378,8 +416,10 @@ void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bo * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr); +esp_err_t 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 @@ -389,8 +429,10 @@ void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, * @param lr Low segment Read permission flag * @param hw High segment Write permission flag * @param hr High segment Read permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr); +esp_err_t 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 @@ -402,25 +444,32 @@ void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, b * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success, ESP_ERR_INVALID_ARG on failure */ -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); +esp_err_t 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 + * @brief Configures the memory protection for high and low 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 mem_type Memory protection area type (MEMPROT_PERI2_RTCSLOW_0, MEMPROT_PERI2_RTCSLOW_1) + * @param split_addr Address to split the memory region to lower and higher segment (32bit aligned) * @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 + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type + * ESP_ERR_INVALID_STATE on splitting address out of PERIBUS2 range + * ESP_ERR_INVALID_SIZE on splitting address not 32-bit aligned */ -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); +esp_err_t 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 @@ -432,8 +481,12 @@ void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, * @param hw High segment Write permission flag * @param hr High segment Read permission flag * @param hx High segment Execute permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lw/lr/lx/hw/hr/hx args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx); +esp_err_t 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 @@ -441,8 +494,12 @@ void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, b * @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 + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lr/hr args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr); +esp_err_t 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 @@ -450,23 +507,33 @@ void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr); * @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 + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lw/hw args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw); +esp_err_t 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 + * @param mem_type Memory protection area type (MEMPROT_IRAM0_SRAM, MEMPROT_IRAM0_RTCFAST, MEMPROT_PERI2_RTCSLOW_0, MEMPROT_PERI2_RTCSLOW_1) + * @param lx Low segment Exec permission flag + * @param hx High segment Exec permission flag + * + * @return ESP_OK on success + * ESP_ERR_INVALID_ARG on NULL lx/hx args + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx); +esp_err_t 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) + * + * @return Required address or MEMPROT_INVALID_ADDRESS for invalid mem_type */ uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type); @@ -474,6 +541,8 @@ 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) + * + * @return Required address or MEMPROT_INVALID_ADDRESS for invalid mem_type */ uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type); @@ -483,8 +552,11 @@ uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_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 + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); +esp_err_t esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); /** * @brief Sets WRITE permission bit for required memory region @@ -492,17 +564,23 @@ void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr); * @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 + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw); +esp_err_t 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 mem_type Memory protection area type (MEMPROT_IRAM0_SRAM, MEMPROT_IRAM0_RTCFAST, MEMPROT_PERI2_RTCSLOW_0, MEMPROT_PERI2_RTCSLOW_1) * @param lr Low segment Exec permission flag * @param hr High segment Exec permission flag + * + * @return ESP_OK on success + * ESP_ERR_NOT_SUPPORTED on invalid mem_type */ -void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx); +esp_err_t esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx); #ifdef __cplusplus diff --git a/components/esp_hw_support/port/esp32s2/memprot.c b/components/esp_hw_support/port/esp32s2/memprot.c index d149cf6303..685acfa2f6 100644 --- a/components/esp_hw_support/port/esp32s2/memprot.c +++ b/components/esp_hw_support/port/esp32s2/memprot.c @@ -14,22 +14,30 @@ #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 "esp32s2/memprot.h" #include "hal/memprot_ll.h" #include "hal/memprot_peri_ll.h" +#include "esp32s2/memprot.h" #include "esp_fault.h" - #include "soc/cpu.h" +#include "esp32s2/rom/ets_sys.h" extern int _iram_text_end; extern int _data_start; extern int _rtc_text_end; extern int _rtc_dummy_end; +static inline esp_err_t esp_memprot_ll_err_to_esp_err(memprot_ll_err_t err) +{ + switch (err) { + case MEMP_LL_OK: return ESP_OK; + case MEMP_LL_FAIL: return ESP_FAIL; + case MEMP_LL_ERR_SPLIT_ADDR_INVALID: return ESP_ERR_INVALID_STATE; + case MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED: return ESP_ERR_INVALID_SIZE; + case MEMP_LL_ERR_UNI_BLOCK_INVALID: return ESP_ERR_NOT_FOUND; + default: + return ESP_FAIL; + } +} uint32_t *esp_memprot_iram0_sram_get_min_split_addr(void) { @@ -53,17 +61,17 @@ uint32_t *esp_memprot_dram0_rtcfast_get_min_split_addr(void) uint32_t *esp_memprot_peri1_rtcslow_get_min_split_addr(void) { - return (uint32_t *)(PERI1_RTCSLOW_ADDRESS_BASE); + return (uint32_t *)PERI1_RTCSLOW_ADDRESS_BASE; } uint32_t *esp_memprot_peri2_rtcslow_0_get_min_split_addr(void) { - return (uint32_t *)(PERI2_RTCSLOW_0_ADDRESS_BASE); + return (uint32_t *)PERI2_RTCSLOW_0_ADDRESS_BASE; } uint32_t *esp_memprot_peri2_rtcslow_1_get_min_split_addr(void) { - return (uint32_t *)(PERI2_RTCSLOW_1_ADDRESS_BASE); + return (uint32_t *)PERI2_RTCSLOW_1_ADDRESS_BASE; } uint32_t *esp_memprot_get_split_addr(mem_type_prot_t mem_type) @@ -84,8 +92,7 @@ uint32_t *esp_memprot_get_split_addr(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return esp_memprot_peri2_rtcslow_1_get_min_split_addr(); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return (uint32_t *)MEMPROT_INVALID_ADDRESS; } } @@ -107,541 +114,673 @@ const char *esp_memprot_type_to_str(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return "PERI2_RTCSLOW_1"; default: - return "UNKOWN"; + return "INVALID_MEM_TYPE"; } } -void esp_memprot_intr_init(mem_type_prot_t mem_type) +esp_err_t esp_memprot_intr_init(mem_type_prot_t mem_type) { ESP_INTR_DISABLE(ETS_MEMACCESS_ERR_INUM); switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_iram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_iram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_dram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_dram0_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; case MEMPROT_PERI1_RTCSLOW: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_peri1_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_peri1_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - intr_matrix_set(PRO_CPU_NUM, esp_memprot_peri2_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); + intr_matrix_set(PRO_CPU_NUM, memprot_ll_peri2_get_intr_source_num(), ETS_MEMACCESS_ERR_INUM); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } ESP_INTR_ENABLE(ETS_MEMACCESS_ERR_INUM); + + return ESP_OK; } -void esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable) +esp_err_t esp_memprot_intr_ena(mem_type_prot_t mem_type, bool enable) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_intr_ena(enable); + memprot_ll_iram0_intr_ena(enable); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_intr_ena(enable); + memprot_ll_dram0_intr_ena(enable); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_intr_ena(enable); + memprot_ll_peri1_intr_ena(enable); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_intr_ena(enable); + memprot_ll_peri2_intr_ena(enable); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } mem_type_prot_t esp_memprot_get_active_intr_memtype() { - if (esp_memprot_iram0_sram_is_intr_mine()) { + if (memprot_ll_iram0_sram_is_intr_mine()) { return MEMPROT_IRAM0_SRAM; - } else if (esp_memprot_iram0_rtcfast_is_intr_mine()) { + } else if (memprot_ll_iram0_rtcfast_is_intr_mine()) { return MEMPROT_IRAM0_RTCFAST; - } else if (esp_memprot_dram0_sram_is_intr_mine()) { + } else if (memprot_ll_dram0_sram_is_intr_mine()) { return MEMPROT_DRAM0_SRAM; - } else if (esp_memprot_dram0_rtcfast_is_intr_mine()) { + } else if (memprot_ll_dram0_rtcfast_is_intr_mine()) { return MEMPROT_DRAM0_RTCFAST; - } else if (esp_memprot_peri1_rtcslow_is_intr_mine()) { + } else if (memprot_ll_peri1_rtcslow_is_intr_mine()) { return MEMPROT_PERI1_RTCSLOW; - } else if (esp_memprot_peri2_rtcslow_0_is_intr_mine()) { + } else if (memprot_ll_peri2_rtcslow_0_is_intr_mine()) { return MEMPROT_PERI2_RTCSLOW_0; - } else if (esp_memprot_peri2_rtcslow_1_is_intr_mine()) { + } else if (memprot_ll_peri2_rtcslow_1_is_intr_mine()) { return MEMPROT_PERI2_RTCSLOW_1; } return MEMPROT_NONE; } -void esp_memprot_clear_intr(mem_type_prot_t mem_type) +esp_err_t esp_memprot_clear_intr(mem_type_prot_t mem_type) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_clear_intr(); + memprot_ll_iram0_clear_intr(); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_clear_intr(); + memprot_ll_dram0_clear_intr(); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_clear_intr(); + memprot_ll_peri1_clear_intr(); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_clear_intr(); + memprot_ll_peri2_clear_intr(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_lock(mem_type_prot_t mem_type) +esp_err_t esp_memprot_set_lock(mem_type_prot_t mem_type) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_set_lock(); + memprot_ll_iram0_set_lock(); break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_set_lock(); + memprot_ll_dram0_set_lock(); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_set_lock(); + memprot_ll_peri1_set_lock(); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_set_lock(); + memprot_ll_peri2_set_lock(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -bool esp_memprot_get_lock(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_lock(mem_type_prot_t mem_type, bool *locked) { + if (locked == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_lock_bit() > 0; + *locked = memprot_ll_iram0_get_lock_bit() > 0; + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_lock_bit() > 0; + *locked = memprot_ll_dram0_get_lock_bit() > 0; + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_lock_bit() > 0; + *locked = memprot_ll_peri1_get_lock_bit() > 0; + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_lock_bit() > 0; + *locked = memprot_ll_peri2_get_lock_bit() > 0; + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } bool esp_memprot_is_locked_any() { return - esp_memprot_iram0_get_lock_bit() > 0 || - esp_memprot_dram0_get_lock_bit() > 0 || - esp_memprot_peri1_get_lock_bit() > 0 || - esp_memprot_peri2_get_lock_bit() > 0; + memprot_ll_iram0_get_lock_bit() > 0 || + memprot_ll_dram0_get_lock_bit() > 0 || + memprot_ll_peri1_get_lock_bit() > 0 || + memprot_ll_peri2_get_lock_bit() > 0; } -uint32_t esp_memprot_get_lock_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type, uint32_t *conf_reg_val) { + if (conf_reg_val == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_lock_bit(); + *conf_reg_val = memprot_ll_iram0_get_conf_reg(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_lock_bit(); + *conf_reg_val = memprot_ll_dram0_get_conf_reg(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_lock_bit(); + *conf_reg_val = memprot_ll_peri1_rtcslow_get_conf_reg(); + break; case MEMPROT_PERI2_RTCSLOW_0: + *conf_reg_val = memprot_ll_peri2_rtcslow_0_get_conf_reg(); + break; case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_lock_bit(); + *conf_reg_val = memprot_ll_peri2_rtcslow_1_get_conf_reg(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type, uint32_t *fault_reg_val) { + if (fault_reg_val == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_conf_reg(); + *fault_reg_val = memprot_ll_iram0_get_fault_reg(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_conf_reg(); + *fault_reg_val = memprot_ll_dram0_get_fault_reg(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_rtcslow_get_conf_reg(); + *fault_reg_val = memprot_ll_peri1_get_fault_reg(); + break; case MEMPROT_PERI2_RTCSLOW_0: - return esp_memprot_peri2_rtcslow_0_get_conf_reg(); case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_rtcslow_1_get_conf_reg(); + *fault_reg_val = memprot_ll_peri2_get_fault_reg(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype) { - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_fault_reg(); - case MEMPROT_DRAM0_SRAM: - case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_fault_reg(); - case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_fault_reg(); - case MEMPROT_PERI2_RTCSLOW_0: - case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_fault_reg(); - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + if (*faulting_address == NULL || op_type == NULL || op_subtype == NULL) { + return ESP_ERR_INVALID_ARG; } -} -void esp_memprot_get_fault_status(mem_type_prot_t mem_type, uint32_t **faulting_address, uint32_t *op_type, uint32_t *op_subtype) -{ switch (mem_type) { case MEMPROT_IRAM0_SRAM: - *faulting_address = esp_memprot_iram0_sram_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_iram0_sram_get_fault_address(); + memprot_ll_iram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_IRAM0_RTCFAST: - *faulting_address = esp_memprot_iram0_rtcfast_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_iram0_rtcfast_get_fault_address(); + memprot_ll_iram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_DRAM0_SRAM: - *faulting_address = esp_memprot_dram0_sram_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_dram0_sram_get_fault_address(); + memprot_ll_dram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_DRAM0_RTCFAST: - *faulting_address = esp_memprot_dram0_rtcfast_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_dram0_rtcfast_get_fault_address(); + memprot_ll_dram0_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_PERI1_RTCSLOW: - *faulting_address = esp_memprot_peri1_rtcslow_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_peri1_rtcslow_get_fault_address(); + memprot_ll_peri1_get_fault_op_type(op_type, op_subtype); break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - *faulting_address = esp_memprot_peri2_rtcslow_get_fault_address(); + *faulting_address = (uint32_t *)memprot_ll_peri2_rtcslow_get_fault_address(); + memprot_ll_peri2_get_fault_op_type(op_type, op_subtype); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } - if (mem_type == MEMPROT_IRAM0_SRAM || mem_type == MEMPROT_IRAM0_RTCFAST) { - esp_memprot_iram0_get_fault_op_type(op_type, op_subtype); - } else if (mem_type == MEMPROT_DRAM0_SRAM || mem_type == MEMPROT_DRAM0_RTCFAST) { - esp_memprot_dram0_get_fault_op_type(op_type, op_subtype); - } else if (mem_type == MEMPROT_PERI1_RTCSLOW) { - esp_memprot_peri1_get_fault_op_type(op_type, op_subtype); - } else if (mem_type == MEMPROT_PERI2_RTCSLOW_0 || mem_type == MEMPROT_PERI2_RTCSLOW_1) { - esp_memprot_peri2_get_fault_op_type(op_type, op_subtype); - } + return ESP_OK; } bool esp_memprot_is_intr_ena_any() { return - esp_memprot_iram0_get_intr_ena_bit() > 0 || - esp_memprot_dram0_get_intr_ena_bit() > 0 || - esp_memprot_peri1_get_intr_ena_bit() > 0 || - esp_memprot_peri2_get_intr_ena_bit() > 0; + memprot_ll_iram0_get_intr_ena_bit() > 0 || + memprot_ll_dram0_get_intr_ena_bit() > 0 || + memprot_ll_peri1_get_intr_ena_bit() > 0 || + memprot_ll_peri2_get_intr_ena_bit() > 0; } -uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type, uint32_t *enable_bit) { + if (enable_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_intr_ena_bit(); + *enable_bit = memprot_ll_iram0_get_intr_ena_bit(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_intr_ena_bit(); + *enable_bit = memprot_ll_dram0_get_intr_ena_bit(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_intr_ena_bit(); + *enable_bit = memprot_ll_peri1_get_intr_ena_bit(); + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_intr_ena_bit(); + *enable_bit = memprot_ll_peri2_get_intr_ena_bit(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type, uint32_t *intr_on_bit) { + if (intr_on_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_intr_on_bit(); + *intr_on_bit = memprot_ll_iram0_get_intr_on_bit(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_intr_on_bit(); + *intr_on_bit = memprot_ll_dram0_get_intr_on_bit(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_intr_on_bit(); + *intr_on_bit = memprot_ll_peri1_get_intr_on_bit(); + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_intr_on_bit(); + *intr_on_bit = memprot_ll_peri2_get_intr_on_bit(); + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type, uint32_t *clear_bit) { + if (clear_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_get_intr_clr_bit(); + *clear_bit = memprot_ll_iram0_get_intr_clr_bit(); + break; case MEMPROT_DRAM0_SRAM: case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_get_intr_clr_bit(); + *clear_bit = memprot_ll_dram0_get_intr_clr_bit(); + break; case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_get_intr_clr_bit(); + *clear_bit = memprot_ll_peri1_get_intr_clr_bit(); + break; case MEMPROT_PERI2_RTCSLOW_0: case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_get_intr_clr_bit(); - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); - } -} - -uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_uni_block_read_bit(block); - case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_uni_block_read_bit(block); - default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); - } -} - -uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_uni_block_write_bit(block); - case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_uni_block_write_bit(block); - default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); - } -} - -uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_uni_block_exec_bit(block); - default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); - } -} - -void esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm) -{ - switch (mem_type) { - case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_uni_block_perm(block, write_perm, read_perm); + *clear_bit = memprot_ll_peri2_get_intr_clr_bit(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *read_bit) { + if (read_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = ESP_OK; + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_perm_uni_reg(); + if (!memprot_ll_iram0_sram_get_uni_block_read_bit(block, read_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_perm_reg(); + if (!memprot_ll_dram0_sram_get_uni_block_read_bit(block, read_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); + ret = ESP_ERR_NOT_SUPPORTED; + break; } + + return ret; } -uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type) +esp_err_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *write_bit) { + if (write_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = ESP_OK; + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - return esp_memprot_iram0_sram_get_perm_split_reg(); - case MEMPROT_IRAM0_RTCFAST: - return esp_memprot_iram0_rtcfast_get_perm_split_reg(); + if (!memprot_ll_iram0_sram_get_uni_block_write_bit(block, write_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; case MEMPROT_DRAM0_SRAM: - return esp_memprot_dram0_sram_get_perm_reg(); - case MEMPROT_DRAM0_RTCFAST: - return esp_memprot_dram0_rtcfast_get_perm_split_reg(); - case MEMPROT_PERI1_RTCSLOW: - return esp_memprot_peri1_rtcslow_get_conf_reg(); - case MEMPROT_PERI2_RTCSLOW_0: - return esp_memprot_peri2_rtcslow_0_get_conf_reg(); - case MEMPROT_PERI2_RTCSLOW_1: - return esp_memprot_peri2_rtcslow_1_get_conf_reg(); + if (!memprot_ll_dram0_sram_get_uni_block_write_bit(block, write_bit)) { + ret = ESP_ERR_NOT_FOUND; + } + break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + ret = ESP_ERR_NOT_SUPPORTED; + break; } + + return ret; } -void esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +esp_err_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block, uint32_t *exec_bit) +{ + if (exec_bit == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + if (!memprot_ll_iram0_sram_get_uni_block_exec_bit(block, exec_bit)) { + return ESP_ERR_NOT_FOUND; + } + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_set_uni_block_perm_dram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm) { switch (mem_type) { case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_sram_get_min_split_addr(), lw, lr, hw, hr); - break; - case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_rtcfast_get_min_split_addr(), lw, lr, hw, hr); - break; + return esp_memprot_ll_err_to_esp_err(memprot_ll_dram0_sram_set_uni_block_perm(block, write_perm, read_perm)); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } } -void esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm) +esp_err_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type, uint32_t *perm_reg) { + if (perm_reg == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_uni_block_perm(block, write_perm, read_perm, exec_perm); + *perm_reg = memprot_ll_iram0_sram_get_perm_uni_reg(); + break; + case MEMPROT_DRAM0_SRAM: + *perm_reg = memprot_ll_dram0_sram_get_perm_reg(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d (unified block management not supported)", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +esp_err_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type, uint32_t *split_reg) { + if (split_reg == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_sram_get_min_split_addr(), lw, lr, lx, hw, hr, hx); + *split_reg = memprot_ll_iram0_sram_get_perm_split_reg(); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_rtcfast_get_min_split_addr(), lw, lr, lx, hw, hr, hx); + *split_reg = memprot_ll_iram0_rtcfast_get_perm_split_reg(); + break; + case MEMPROT_DRAM0_SRAM: + *split_reg = memprot_ll_dram0_sram_get_perm_reg(); + break; + case MEMPROT_DRAM0_RTCFAST: + *split_reg = memprot_ll_dram0_rtcfast_get_perm_split_reg(); + break; + case MEMPROT_PERI1_RTCSLOW: + *split_reg = memprot_ll_peri1_rtcslow_get_conf_reg(); + break; + case MEMPROT_PERI2_RTCSLOW_0: + *split_reg = memprot_ll_peri2_rtcslow_0_get_conf_reg(); + break; + case MEMPROT_PERI2_RTCSLOW_1: + *split_reg = memprot_ll_peri2_rtcslow_1_get_conf_reg(); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -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) -{ - switch (mem_type) { - case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; - case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); - } -} - -void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +esp_err_t esp_memprot_set_prot_dram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { switch (mem_type) { case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); + return esp_memprot_ll_err_to_esp_err(memprot_ll_dram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_sram_get_min_split_addr(), lw, lr, hw, hr)); + case MEMPROT_DRAM0_RTCFAST: + return esp_memprot_ll_err_to_esp_err(memprot_ll_dram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_dram0_rtcfast_get_min_split_addr(), lw, lr, hw, hr)); + default: + return ESP_ERR_NOT_SUPPORTED; + } +} + +esp_err_t esp_memprot_set_uni_block_perm_iram(mem_type_prot_t mem_type, uint32_t block, bool write_perm, bool read_perm, bool exec_perm) +{ + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + if (!memprot_ll_iram0_sram_set_uni_block_perm(block, write_perm, read_perm, exec_perm)) { + return ESP_ERR_INVALID_ARG; + } + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_set_prot_iram(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +{ + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + return esp_memprot_ll_err_to_esp_err(memprot_ll_iram0_sram_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_sram_get_min_split_addr(), lw, lr, lx, hw, hr, hx)); + case MEMPROT_IRAM0_RTCFAST: + return esp_memprot_ll_err_to_esp_err(memprot_ll_iram0_rtcfast_set_prot(split_addr != NULL ? split_addr : esp_memprot_iram0_rtcfast_get_min_split_addr(), lw, lr, lx, hw, hr, hx)); + default: + return ESP_ERR_NOT_SUPPORTED; + } +} + +esp_err_t 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) +{ + if (lw == NULL || lr == NULL || lx == NULL || hw == NULL || hr == NULL || hx == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_IRAM0_SRAM: + memprot_ll_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + break; + case MEMPROT_IRAM0_RTCFAST: + memprot_ll_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +{ + if (lw == NULL || lr == NULL || hw == NULL || hr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_DRAM0_SRAM: + memprot_ll_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +esp_err_t esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr) +{ + if (lw == NULL || lr == NULL || hw == NULL || hr == NULL) { + return ESP_ERR_INVALID_ARG; + } + + switch (mem_type) { + case MEMPROT_PERI1_RTCSLOW: + memprot_ll_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); + break; + default: + return ESP_ERR_NOT_SUPPORTED; + } + + return ESP_OK; +} + +esp_err_t esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { switch (mem_type) { case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); - break; + return esp_memprot_ll_err_to_esp_err( + memprot_ll_peri1_rtcslow_set_prot( + split_addr != NULL ? split_addr : esp_memprot_peri1_rtcslow_get_min_split_addr(), + lw, + lr, + hw, + hr) + ); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } } -void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +esp_err_t 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) { + if (lw == NULL || lr == NULL || lx == NULL || hw == NULL || hr == NULL || hx == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { - case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_set_prot(split_addr != NULL ? split_addr : esp_memprot_peri1_rtcslow_get_min_split_addr(), lw, lr, hw, hr); + case MEMPROT_PERI2_RTCSLOW_0: + memprot_ll_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + break; + case MEMPROT_PERI2_RTCSLOW_1: + memprot_ll_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -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) +esp_err_t 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) { switch (mem_type) { case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; + return esp_memprot_ll_err_to_esp_err( + memprot_ll_peri2_rtcslow_0_set_prot( + split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_0_get_min_split_addr(), + lw, + lr, + lx, + hw, + hr, + hx) + ); case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); - break; + return esp_memprot_ll_err_to_esp_err( + memprot_ll_peri2_rtcslow_1_set_prot( + split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_1_get_min_split_addr(), + lw, + lr, + lx, + hw, + hr, + hx) + ); default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } } -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) +esp_err_t esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask) { - switch (mem_type) { - case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_prot(split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_0_get_min_split_addr(), lw, lr, lx, hw, hr, hx); - break; - case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_prot(split_addr != NULL ? split_addr : esp_memprot_peri2_rtcslow_1_get_min_split_addr(), lw, lr, lx, hw, hr, hx); - break; - default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); - } -} + esp_err_t ret; -void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask) -{ //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; @@ -650,17 +789,17 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t 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_iram0 && (ret = esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, false)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, false); + if (use_dram0 && (ret = esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, false)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, false); + if (use_peri1 && (ret = esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, false)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, false); + if (use_peri2 && (ret = esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, false)) != ESP_OK) { + return ret; } //connect to intr. matrix if not being debugged @@ -670,134 +809,172 @@ void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t //initialize for specific buses (any memory type does the job) if (invoke_panic_handler) { - if (use_iram0) { - esp_memprot_intr_init(MEMPROT_IRAM0_SRAM); + if (use_iram0 && (ret = esp_memprot_intr_init(MEMPROT_IRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_intr_init(MEMPROT_DRAM0_SRAM); + if (use_dram0 && (ret = esp_memprot_intr_init(MEMPROT_DRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_intr_init(MEMPROT_PERI1_RTCSLOW); + if (use_peri1 && (ret = esp_memprot_intr_init(MEMPROT_PERI1_RTCSLOW)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_intr_init(MEMPROT_PERI2_RTCSLOW_0); + if (use_peri2 && (ret = esp_memprot_intr_init(MEMPROT_PERI2_RTCSLOW_0)) != ESP_OK) { + return ret; } } //set permissions if (required_mem_prot & MEMPROT_IRAM0_SRAM) { - esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + ret = esp_memprot_set_prot_iram(MEMPROT_IRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_IRAM0_RTCFAST) { - esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + ret = esp_memprot_set_prot_iram(MEMPROT_IRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, EX_LOW_ENA, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_DRAM0_SRAM) { - esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + ret = esp_memprot_set_prot_dram(MEMPROT_DRAM0_SRAM, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_DRAM0_RTCFAST) { - esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + ret = esp_memprot_set_prot_dram(MEMPROT_DRAM0_RTCFAST, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_ENA, WR_HIGH_ENA, RD_HIGH_ENA); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_PERI1_RTCSLOW) { - esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS); + ret = esp_memprot_set_prot_peri1(MEMPROT_PERI1_RTCSLOW, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_0) { - esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, DEF_SPLIT_LINE, WR_LOW_ENA, RD_LOW_ENA, EX_LOW_DIS, WR_HIGH_ENA, RD_HIGH_ENA, EX_HIGH_DIS); + ret = esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_0, DEF_SPLIT_LINE, WR_LOW_ENA, RD_LOW_ENA, EX_LOW_DIS, WR_HIGH_ENA, RD_HIGH_ENA, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } if (required_mem_prot & MEMPROT_PERI2_RTCSLOW_1) { - esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, EX_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + ret = esp_memprot_set_prot_peri2(MEMPROT_PERI2_RTCSLOW_1, DEF_SPLIT_LINE, WR_LOW_DIS, RD_LOW_DIS, EX_LOW_DIS, WR_HIGH_DIS, RD_HIGH_DIS, EX_HIGH_DIS); + if (ret != ESP_OK) { + return ret; + } } //reenable protection (bus based) - if (use_iram0) { - esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, true); + if (use_iram0 && (ret = esp_memprot_intr_ena(MEMPROT_IRAM0_SRAM, true)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, true); + if (use_dram0 && (ret = esp_memprot_intr_ena(MEMPROT_DRAM0_SRAM, true)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, true); + if (use_peri1 && (ret = esp_memprot_intr_ena(MEMPROT_PERI1_RTCSLOW, true)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, true); + if (use_peri2 && (ret = esp_memprot_intr_ena(MEMPROT_PERI2_RTCSLOW_0, true)) != ESP_OK) { + return ret; } //lock if required (bus based) if (lock_feature) { - if (use_iram0) { - esp_memprot_set_lock(MEMPROT_IRAM0_SRAM); + if (use_iram0 && (ret = esp_memprot_set_lock(MEMPROT_IRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_dram0) { - esp_memprot_set_lock(MEMPROT_DRAM0_SRAM); + if (use_dram0 && (ret = esp_memprot_set_lock(MEMPROT_DRAM0_SRAM)) != ESP_OK) { + return ret; } - if (use_peri1) { - esp_memprot_set_lock(MEMPROT_PERI1_RTCSLOW); + if (use_peri1 && (ret = esp_memprot_set_lock(MEMPROT_PERI1_RTCSLOW)) != ESP_OK) { + return ret; } - if (use_peri2) { - esp_memprot_set_lock(MEMPROT_PERI2_RTCSLOW_0); + if (use_peri2 && (ret = esp_memprot_set_lock(MEMPROT_PERI2_RTCSLOW_0)) != ESP_OK) { + return ret; } } } + + return ESP_OK; } -void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +esp_err_t esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { + if (lw == NULL || lr == NULL || lx == NULL || hw == NULL || hr == NULL || hx == NULL) { + return ESP_ERR_INVALID_ARG; + } + switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_iram0_sram_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_dram0_sram_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_iram0_rtcfast_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_dram0_rtcfast_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); + memprot_ll_peri1_rtcslow_get_split_sgnf_bits(lw, lr, hw, hr); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_peri2_rtcslow_0_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); + memprot_ll_peri2_rtcslow_1_get_split_sgnf_bits(lw, lr, lx, hw, hr, hx); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr) +esp_err_t esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr) { bool _lw, _lr, _lx, _hw, _hr, _hx; - esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); - *lr = _lr; - *hr = _hr; + esp_err_t ret = esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); + if (ret == ESP_OK) { + *lr = _lr; + *hr = _hr; + } + return ret; } -void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw) +esp_err_t esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw) { bool _lw, _lr, _lx, _hw, _hr, _hx; - esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); - *lw = _lw; - *hw = _hw; + esp_err_t ret = esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); + if (ret == ESP_OK) { + *lw = _lw; + *hw = _hw; + } + + return ret; } -void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx) +esp_err_t esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx) { - if ( mem_type == MEMPROT_DRAM0_SRAM || + if (mem_type == MEMPROT_DRAM0_SRAM || mem_type == MEMPROT_DRAM0_RTCFAST || - mem_type == MEMPROT_PERI1_RTCSLOW ) { - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + mem_type == MEMPROT_PERI1_RTCSLOW) { + return ESP_ERR_NOT_SUPPORTED; } bool _lw, _lr, _lx, _hw, _hr, _hx; - esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); - *lx = _lx; - *hx = _hx; + esp_err_t ret = esp_memprot_get_permissions(mem_type, &_lw, &_lr, &_lx, &_hw, &_hr, &_hx); + if (ret == ESP_OK) { + *lx = _lx; + *hx = _hx; + } + + return ret; } uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type) @@ -818,8 +995,7 @@ uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return PERI2_RTCSLOW_1_ADDRESS_LOW; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return MEMPROT_INVALID_ADDRESS; } } @@ -841,88 +1017,90 @@ uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type) case MEMPROT_PERI2_RTCSLOW_1: return PERI2_RTCSLOW_1_ADDRESS_HIGH; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return MEMPROT_INVALID_ADDRESS; } } -void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr) +esp_err_t esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_read_perm(lr, hr); + memprot_ll_iram0_sram_set_read_perm(lr, hr); break; case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_read_perm(lr, hr); + memprot_ll_dram0_sram_set_read_perm(lr, hr); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_read_perm(lr, hr); + memprot_ll_iram0_rtcfast_set_read_perm(lr, hr); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_set_read_perm(lr, hr); + memprot_ll_dram0_rtcfast_set_read_perm(lr, hr); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_set_read_perm(lr, hr); + memprot_ll_peri1_rtcslow_set_read_perm(lr, hr); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_read_perm(lr, hr); + memprot_ll_peri2_rtcslow_0_set_read_perm(lr, hr); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_read_perm(lr, hr); + memprot_ll_peri2_rtcslow_1_set_read_perm(lr, hr); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw) +esp_err_t esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_write_perm(lw, hw); + memprot_ll_iram0_sram_set_write_perm(lw, hw); break; case MEMPROT_DRAM0_SRAM: - esp_memprot_dram0_sram_set_write_perm(lw, hw); + memprot_ll_dram0_sram_set_write_perm(lw, hw); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_write_perm(lw, hw); + memprot_ll_iram0_rtcfast_set_write_perm(lw, hw); break; case MEMPROT_DRAM0_RTCFAST: - esp_memprot_dram0_rtcfast_set_write_perm(lw, hw); + memprot_ll_dram0_rtcfast_set_write_perm(lw, hw); break; case MEMPROT_PERI1_RTCSLOW: - esp_memprot_peri1_rtcslow_set_write_perm(lw, hw); + memprot_ll_peri1_rtcslow_set_write_perm(lw, hw); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_write_perm(lw, hw); + memprot_ll_peri2_rtcslow_0_set_write_perm(lw, hw); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_write_perm(lw, hw); + memprot_ll_peri2_rtcslow_1_set_write_perm(lw, hw); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } -void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx) +esp_err_t esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx) { switch (mem_type) { case MEMPROT_IRAM0_SRAM: - esp_memprot_iram0_sram_set_exec_perm(lx, hx); + memprot_ll_iram0_sram_set_exec_perm(lx, hx); break; case MEMPROT_IRAM0_RTCFAST: - esp_memprot_iram0_rtcfast_set_exec_perm(lx, hx); + memprot_ll_iram0_rtcfast_set_exec_perm(lx, hx); break; case MEMPROT_PERI2_RTCSLOW_0: - esp_memprot_peri2_rtcslow_0_set_exec_perm(lx, hx); + memprot_ll_peri2_rtcslow_0_set_exec_perm(lx, hx); break; case MEMPROT_PERI2_RTCSLOW_1: - esp_memprot_peri2_rtcslow_1_set_exec_perm(lx, hx); + memprot_ll_peri2_rtcslow_1_set_exec_perm(lx, hx); break; default: - ESP_LOGE(TAG, "Invalid mem_type %d", mem_type); - abort(); + return ESP_ERR_NOT_SUPPORTED; } + + return ESP_OK; } diff --git a/components/esp_system/port/arch/xtensa/panic_arch.c b/components/esp_system/port/arch/xtensa/panic_arch.c index fb1e021df0..6ca03b520c 100644 --- a/components/esp_system/port/arch/xtensa/panic_arch.c +++ b/components/esp_system/port/arch/xtensa/panic_arch.c @@ -76,7 +76,7 @@ void panic_print_registers(const void *f, int core) && ((core == 0 && frame->exccause == PANIC_RSN_INTWDT_CPU0) || (core == 1 && frame->exccause == PANIC_RSN_INTWDT_CPU1)) #endif //!CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - ) { + ) { panic_print_str("\r\n"); @@ -264,27 +264,46 @@ static inline void print_cache_err_details(const void *f) } #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#define MEMPROT_OP_INVALID 0xFFFFFFFF 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_active_intr_memtype(); - esp_memprot_get_fault_status( mem_type, &fault_addr, &op_type, &op_subtype ); + char *operation_type; - char *operation_type = "Write"; - if ( op_type == 0 ) { - operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read"; + mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype(); + if (mem_type != MEMPROT_NONE) { +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged + if (esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype) != ESP_OK) { + op_type = MEMPROT_OP_INVALID; + } +#else + esp_memprot_get_fault_status(mem_type, &fault_addr, &op_type, &op_subtype); +#endif } - panic_print_str( operation_type ); - panic_print_str( " operation at address 0x" ); - panic_print_hex( (uint32_t)fault_addr ); - panic_print_str(" not permitted.\r\n"); + if (op_type == MEMPROT_OP_INVALID) { + operation_type = "Unknown"; + fault_addr = (uint32_t *)MEMPROT_OP_INVALID; + } else { + if (op_type == 0) { + operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read"; + } else { + operation_type = "Write"; + } + } + + panic_print_str(operation_type); + panic_print_str(" operation at address 0x"); + panic_print_hex((uint32_t)fault_addr); + panic_print_str(" not permitted ("); + panic_print_str(esp_memprot_type_to_str(mem_type)); + panic_print_str(")\r\n"); } #endif #elif CONFIG_IDF_TARGET_ESP32S3 -static inline void print_cache_err_details(const void* f) +static inline void print_cache_err_details(const void *f) { uint32_t vaddr = 0, size = 0; uint32_t status; @@ -355,7 +374,7 @@ static inline void print_cache_err_details(const void* f) void panic_arch_fill_info(void *f, panic_info_t *info) { - XtExcFrame *frame = (XtExcFrame*) f; + XtExcFrame *frame = (XtExcFrame *) f; static const char *reason[] = { "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError", "Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue", @@ -388,7 +407,7 @@ void panic_soc_fill_info(void *f, panic_info_t *info) { // [refactor-todo] this should be in the common port panic_handler.c, once // these special exceptions are supported in there. - XtExcFrame *frame = (XtExcFrame*) f; + XtExcFrame *frame = (XtExcFrame *) f; if (frame->exccause == PANIC_RSN_INTWDT_CPU0) { info->core = 0; info->exception = PANIC_EXCEPTION_IWDT; @@ -442,19 +461,19 @@ void panic_soc_fill_info(void *f, panic_info_t *info) #endif } -uint32_t panic_get_address(const void* f) +uint32_t panic_get_address(const void *f) { - return ((XtExcFrame*)f)->pc; + return ((XtExcFrame *)f)->pc; } -uint32_t panic_get_cause(const void* f) +uint32_t panic_get_cause(const void *f) { - return ((XtExcFrame*)f)->exccause; + return ((XtExcFrame *)f)->exccause; } void panic_set_address(void *f, uint32_t addr) { - ((XtExcFrame*)f)->pc = addr; + ((XtExcFrame *)f)->pc = addr; } void panic_print_backtrace(const void *f, int core) diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 9c91e94440..457b7c3992 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -305,7 +305,7 @@ void IRAM_ATTR call_start_cpu0(void) // from panic handler we can be reset by RWDT or TG0WDT if (rst_reas[0] == RESET_REASON_CORE_RTC_WDT || rst_reas[0] == RESET_REASON_CORE_MWDT0 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - || rst_reas[1] == RESET_REASON_CORE_RTC_WDT || rst_reas[1] == RESET_REASON_CORE_MWDT0 + || rst_reas[1] == RESET_REASON_CORE_RTC_WDT || rst_reas[1] == RESET_REASON_CORE_MWDT0 #endif ) { wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL}; @@ -513,15 +513,28 @@ void IRAM_ATTR call_start_cpu0(void) #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE // Memprot cannot be locked during OS startup as the lock-on prevents any PMS changes until a next reboot // If such a situation appears, it is likely an malicious attempt to bypass the system safety setup -> print error & reset - if ( esp_memprot_is_locked_any() ) { + if (esp_memprot_is_locked_any()) { ESP_EARLY_LOGE(TAG, "Memprot feature locked after the system reset! Potential safety corruption, rebooting."); esp_restart_noos_dig(); } + esp_err_t memp_err = ESP_OK; #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged + memp_err = esp_memprot_set_prot(true, true, NULL); +#else esp_memprot_set_prot(true, true, NULL); +#endif +#else +#if CONFIG_IDF_TARGET_ESP32S2 //specific for ESP32S2 unless IDF-3024 is merged + memp_err = esp_memprot_set_prot(true, false, NULL); #else esp_memprot_set_prot(true, false, NULL); #endif +#endif + if (memp_err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to set Memprot feature (error 0x%08X), rebooting.", memp_err); + esp_restart_noos_dig(); + } #endif bootloader_flash_update_id(); diff --git a/components/hal/esp32s2/include/hal/memprot_ll.h b/components/hal/esp32s2/include/hal/memprot_ll.h index eeaa73dcc8..fa77e2f3ab 100644 --- a/components/hal/esp32s2/include/hal/memprot_ll.h +++ b/components/hal/esp32s2/include/hal/memprot_ll.h @@ -14,7 +14,9 @@ #pragma once -#include "hal/assert.h" +#include +#include "soc/memprot_defs.h" +#include "hal/memprot_types.h" #ifdef __cplusplus extern "C" { @@ -25,23 +27,18 @@ extern "C" { * === IRAM0 common * ======================================================================================== */ -//IRAM0 interrupt status bitmasks -#define IRAM0_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 -#define IRAM0_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 -#define CONF_REG_ADDRESS_SHIFT 2 - -static inline void esp_memprot_iram0_clear_intr(void) +static inline void memprot_ll_iram0_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); } -static inline uint32_t esp_memprot_iram0_get_intr_source_num(void) +static inline uint32_t memprot_ll_iram0_get_intr_source_num(void) { return ETS_PMS_PRO_IRAM0_ILG_INTR_SOURCE; } -static inline void esp_memprot_iram0_intr_ena(bool enable) +static inline void memprot_ll_iram0_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN); @@ -50,55 +47,55 @@ static inline void esp_memprot_iram0_intr_ena(bool enable) } } -static inline uint32_t esp_memprot_iram0_get_conf_reg(void) +static inline uint32_t memprot_ll_iram0_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_4_REG); } -static inline uint32_t esp_memprot_iram0_get_fault_reg(void) +static inline uint32_t memprot_ll_iram0_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_5_REG); } -static inline void esp_memprot_iram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_iram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); + uint32_t status_bits = memprot_ll_iram0_get_fault_reg(); *op_type = (uint32_t)status_bits & IRAM0_INTR_ST_OP_RW_BIT; *op_subtype = (uint32_t)status_bits & IRAM0_INTR_ST_OP_TYPE_BIT; } -static inline bool esp_memprot_iram0_is_assoc_intr(void) +static inline bool memprot_ll_iram0_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR) > 0; } -static inline uint32_t esp_memprot_iram0_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_iram0_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_EN); } -static inline uint32_t esp_memprot_iram0_get_intr_on_bit(void) +static inline uint32_t memprot_ll_iram0_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_INTR); } -static inline uint32_t esp_memprot_iram0_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_iram0_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_4_REG, DPORT_PMS_PRO_IRAM0_ILG_CLR); } //resets automatically on CPU restart -static inline void esp_memprot_iram0_set_lock(void) +static inline void memprot_ll_iram0_set_lock(void) { DPORT_WRITE_PERI_REG( DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK); } -static inline uint32_t esp_memprot_iram0_get_lock_reg(void) +static inline uint32_t memprot_ll_iram0_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_0_REG); } -static inline uint32_t esp_memprot_iram0_get_lock_bit(void) +static inline uint32_t memprot_ll_iram0_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_0_REG, DPORT_PMS_PRO_IRAM0_LOCK); } @@ -108,52 +105,26 @@ static inline uint32_t esp_memprot_iram0_get_lock_bit(void) * === IRAM0 SRAM * ======================================================================================== */ -#define IRAM0_SRAM_BASE_ADDRESS 0x40000000 -#define IRAM0_SRAM_ADDRESS_LOW 0x40020000 -#define IRAM0_SRAM_ADDRESS_HIGH 0x4006FFFF - -#define IRAM0_SRAM_TOTAL_UNI_BLOCKS 4 -#define IRAM0_SRAM_UNI_BLOCK_0 0 -#define IRAM0_SRAM_UNI_BLOCK_1 1 -#define IRAM0_SRAM_UNI_BLOCK_2 2 -#define IRAM0_SRAM_UNI_BLOCK_3 3 - -//unified management (SRAM blocks 0-3) -#define IRAM0_SRAM_UNI_BLOCK_0_LOW 0x40020000 -#define IRAM0_SRAM_UNI_BLOCK_1_LOW 0x40022000 -#define IRAM0_SRAM_UNI_BLOCK_2_LOW 0x40024000 -#define IRAM0_SRAM_UNI_BLOCK_3_LOW 0x40026000 - -//split management (SRAM blocks 4-21) -#define IRAM0_SRAM_SPL_BLOCK_LOW 0x40028000 //block 4 low -#define IRAM0_SRAM_SPL_BLOCK_HIGH 0x4006FFFF //block 21 high - -#define IRAM0_INTR_ST_FAULTADDR_M 0x003FFFFC //bits 21:6 in the reg, as well as in real address -#define IRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x40000000 //high nonsignificant bits 31:22 of the faulting address - constant - -#define IRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_S) - -static inline uint32_t *esp_memprot_iram0_sram_get_fault_address(void) +static inline intptr_t memprot_ll_iram0_sram_get_fault_address(void) { - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); - return (uint32_t *)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_SRAM_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_iram0_get_fault_reg(); + return (intptr_t)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_SRAM_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_iram0_sram_is_intr_mine(void) +static inline bool memprot_ll_iram0_sram_is_intr_mine(void) { - if (esp_memprot_iram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_iram0_sram_get_fault_address(); - return (uint32_t)faulting_address >= IRAM0_SRAM_ADDRESS_LOW && (uint32_t)faulting_address <= IRAM0_SRAM_ADDRESS_HIGH; + if (memprot_ll_iram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_iram0_sram_get_fault_address(); + return faulting_address >= IRAM0_SRAM_ADDRESS_LOW && faulting_address <= IRAM0_SRAM_ADDRESS_HIGH; } return false; } //block 0-3 -static inline void esp_memprot_iram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm, bool exec_perm) +static inline bool memprot_ll_iram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm, bool exec_perm) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - uint32_t write_bit, read_bit, exec_bit; + switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W; @@ -176,7 +147,7 @@ static inline void esp_memprot_iram0_sram_set_uni_block_perm(uint32_t block, boo exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F; break; default: - abort(); + return false; } if (write_perm) { @@ -196,66 +167,78 @@ static inline void esp_memprot_iram0_sram_set_uni_block_perm(uint32_t block, boo } else { DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_IRAM0_1_REG, exec_bit); } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_uni_block_read_bit(uint32_t block) +static inline bool memprot_ll_iram0_sram_get_uni_block_read_bit(uint32_t block, uint32_t *read_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_R); + break; case IRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_R); + break; case IRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_R); + break; case IRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_R); + break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_uni_block_write_bit(uint32_t block) +static inline bool memprot_ll_iram0_sram_get_uni_block_write_bit(uint32_t block, uint32_t *write_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_W); + break; case IRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_W); + break; case IRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_W); + break; case IRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_W); + break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_uni_block_exec_bit(uint32_t block) +static inline bool memprot_ll_iram0_sram_get_uni_block_exec_bit(uint32_t block, uint32_t *exec_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_0_F); + break; case IRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_1_F); + break; case IRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_2_F); + break; case IRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_F); + *exec_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_1_REG, DPORT_PMS_PRO_IRAM0_SRAM_3_F); + break; default: - abort(); + return false; } + + return true; } -static inline void esp_memprot_iram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit, uint32_t *exec_bit) +static inline bool memprot_ll_iram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit, uint32_t *exec_bit) { - HAL_ASSERT(block < IRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case IRAM0_SRAM_UNI_BLOCK_0: *write_bit = DPORT_PMS_PRO_IRAM0_SRAM_0_W; @@ -278,25 +261,33 @@ static inline void esp_memprot_iram0_sram_get_uni_block_sgnf_bits(uint32_t block *exec_bit = DPORT_PMS_PRO_IRAM0_SRAM_3_F; break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_iram0_sram_get_perm_uni_reg(void) +static inline uint32_t memprot_ll_iram0_sram_get_perm_uni_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_1_REG); } -static inline uint32_t esp_memprot_iram0_sram_get_perm_split_reg(void) +static inline uint32_t memprot_ll_iram0_sram_get_perm_split_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_2_REG); } -static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_iram0_sram_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; - HAL_ASSERT(addr <= IRAM0_SRAM_SPL_BLOCK_HIGH); - HAL_ASSERT(addr % 0x4 == 0); + + //sanity check: split address required above unified mgmt region & 32bit aligned + if (addr > IRAM0_SRAM_SPL_BLOCK_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //find possible split.address in low region blocks int uni_blocks_low = -1; @@ -318,7 +309,9 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw uint32_t uni_block_perm = 0; for (int x = 0; x < IRAM0_SRAM_TOTAL_UNI_BLOCKS; x++) { - esp_memprot_iram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit, &exec_bit); + if (!memprot_ll_iram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit, &exec_bit)) { + return MEMP_LL_ERR_UNI_BLOCK_INVALID; + } if (x <= uni_blocks_low) { if (lw) { uni_block_perm |= write_bit; @@ -346,7 +339,7 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw uint32_t reg_split_addr = 0; if (addr >= IRAM0_SRAM_SPL_BLOCK_LOW) { - reg_split_addr = IRAM0_SRAM_ADDR_TO_CONF_REG( addr ); //cfg reg - [16:0] + reg_split_addr = IRAM0_SRAM_ADDR_TO_CONF_REG(addr); //cfg reg - [16:0] } //prepare high & low permission mask (bits: [22:20] high range, [19:17] low range) @@ -373,9 +366,11 @@ static inline void esp_memprot_iram0_sram_set_prot(uint32_t *split_addr, bool lw //write IRAM SRAM uni & splt cfg. registers DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_IRAM0_1_REG, uni_block_perm); DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_IRAM0_2_REG, (uint32_t)(reg_split_addr | permission_mask)); + + return MEMP_LL_OK; } -static inline void esp_memprot_iram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_iram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_R); @@ -385,19 +380,19 @@ static inline void esp_memprot_iram0_sram_get_split_sgnf_bits(bool *lw, bool *lr *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_F); } -static inline void esp_memprot_iram0_sram_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_iram0_sram_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_R, hr ? 1 : 0); } -static inline void esp_memprot_iram0_sram_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_iram0_sram_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_W, hw ? 1 : 0); } -static inline void esp_memprot_iram0_sram_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_iram0_sram_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_2_REG, DPORT_PMS_PRO_IRAM0_SRAM_4_H_F, hx ? 1 : 0); @@ -409,37 +404,37 @@ static inline void esp_memprot_iram0_sram_set_exec_perm(bool lx, bool hx) * === IRAM0 RTC FAST * ======================================================================================== */ -#define IRAM0_RTCFAST_ADDRESS_LOW 0x40070000 -#define IRAM0_RTCFAST_ADDRESS_HIGH 0x40071FFF -#define IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x40070000 //RTCFAST faulting address high bits (31:22, constant) - -#define IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR_S) - - -static inline uint32_t *esp_memprot_iram0_rtcfast_get_fault_address(void) +static inline intptr_t memprot_ll_iram0_rtcfast_get_fault_address(void) { - uint32_t status_bits = esp_memprot_iram0_get_fault_reg(); - return (uint32_t *)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_iram0_get_fault_reg(); + return (intptr_t)((status_bits & IRAM0_INTR_ST_FAULTADDR_M) | IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_iram0_rtcfast_is_intr_mine(void) +static inline bool memprot_ll_iram0_rtcfast_is_intr_mine(void) { - if (esp_memprot_iram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_iram0_rtcfast_get_fault_address(); - return (uint32_t)faulting_address >= IRAM0_RTCFAST_ADDRESS_LOW && (uint32_t)faulting_address <= IRAM0_RTCFAST_ADDRESS_HIGH; + if (memprot_ll_iram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_iram0_rtcfast_get_fault_address(); + return faulting_address >= IRAM0_RTCFAST_ADDRESS_LOW && faulting_address <= IRAM0_RTCFAST_ADDRESS_HIGH; } return false; } -static inline uint32_t esp_memprot_iram0_rtcfast_get_perm_split_reg(void) +static inline uint32_t memprot_ll_iram0_rtcfast_get_perm_split_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_IRAM0_3_REG); } -static inline void esp_memprot_iram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx) +static inline memprot_ll_err_t memprot_ll_iram0_rtcfast_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; - HAL_ASSERT(addr % 0x4 == 0); + + //32bit aligned + if (addr < IRAM0_RTCFAST_ADDRESS_LOW || addr > IRAM0_RTCFAST_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //conf reg [10:0] uint32_t reg_split_addr = IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr); @@ -467,9 +462,11 @@ static inline void esp_memprot_iram0_rtcfast_set_prot(uint32_t *split_addr, bool //write IRAM0 RTCFAST cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_IRAM0_3_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_iram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_iram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_R); @@ -479,19 +476,19 @@ static inline void esp_memprot_iram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *hx = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_F); } -static inline void esp_memprot_iram0_rtcfast_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_iram0_rtcfast_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_R, hr ? 1 : 0); } -static inline void esp_memprot_iram0_rtcfast_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_iram0_rtcfast_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_W, hw ? 1 : 0); } -static inline void esp_memprot_iram0_rtcfast_set_exec_perm(bool lx, bool hx) +static inline void memprot_ll_iram0_rtcfast_set_exec_perm(bool lx, bool hx) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_L_F, lx ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_IRAM0_3_REG, DPORT_PMS_PRO_IRAM0_RTCFAST_H_F, hx ? 1 : 0); @@ -503,19 +500,12 @@ static inline void esp_memprot_iram0_rtcfast_set_exec_perm(bool lx, bool hx) * === DRAM0 common * ======================================================================================== */ -//DRAM0 interrupt status bitmasks -#define DRAM0_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) -#define DRAM0_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) -#define DRAM0_INTR_ST_OP_RW_BIT BIT(4) //read: 0, write: 1 -#define DRAM0_INTR_ST_OP_ATOMIC_BIT BIT(5) //non-atomic: 0, atomic: 1 - - -static inline uint32_t esp_memprot_dram0_get_intr_source_num(void) +static inline uint32_t memprot_ll_dram0_get_intr_source_num(void) { return ETS_PMS_PRO_DRAM0_ILG_INTR_SOURCE; } -static inline void esp_memprot_dram0_intr_ena(bool enable) +static inline void memprot_ll_dram0_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN); @@ -524,112 +514,87 @@ static inline void esp_memprot_dram0_intr_ena(bool enable) } } -static inline bool esp_memprot_dram0_is_assoc_intr(void) +static inline bool memprot_ll_dram0_is_assoc_intr(void) { return DPORT_GET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR) > 0; } -static inline void esp_memprot_dram0_clear_intr(void) +static inline void memprot_ll_dram0_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); } -static inline uint32_t esp_memprot_dram0_get_intr_ena_bit(void) +static inline uint32_t memprot_ll_dram0_get_intr_ena_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_EN); } -static inline uint32_t esp_memprot_dram0_get_intr_on_bit(void) +static inline uint32_t memprot_ll_dram0_get_intr_on_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_INTR); } -static inline uint32_t esp_memprot_dram0_get_intr_clr_bit(void) +static inline uint32_t memprot_ll_dram0_get_intr_clr_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_3_REG, DPORT_PMS_PRO_DRAM0_ILG_CLR); } //lock resets automatically on CPU restart -static inline void esp_memprot_dram0_set_lock(void) +static inline void memprot_ll_dram0_set_lock(void) { DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK); } -static inline uint32_t esp_memprot_dram0_get_lock_reg(void) +static inline uint32_t memprot_ll_dram0_get_lock_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_0_REG); } -static inline uint32_t esp_memprot_dram0_get_lock_bit(void) +static inline uint32_t memprot_ll_dram0_get_lock_bit(void) { return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_0_REG, DPORT_PMS_PRO_DRAM0_LOCK); } -static inline uint32_t esp_memprot_dram0_get_conf_reg(void) +static inline uint32_t memprot_ll_dram0_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_3_REG); } -static inline uint32_t esp_memprot_dram0_get_fault_reg(void) +static inline uint32_t memprot_ll_dram0_get_fault_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_4_REG); } -static inline void esp_memprot_dram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) +static inline void memprot_ll_dram0_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); + uint32_t status_bits = memprot_ll_dram0_get_fault_reg(); *op_type = status_bits & DRAM0_INTR_ST_OP_RW_BIT; *op_subtype = status_bits & DRAM0_INTR_ST_OP_ATOMIC_BIT; } - /** * ======================================================================================== * === DRAM0 SRAM * ======================================================================================== */ -#define DRAM0_SRAM_ADDRESS_LOW 0x3FFB0000 -#define DRAM0_SRAM_ADDRESS_HIGH 0x3FFFFFFF - -#define DRAM0_SRAM_TOTAL_UNI_BLOCKS 4 -#define DRAM0_SRAM_UNI_BLOCK_0 0 -#define DRAM0_SRAM_UNI_BLOCK_1 1 -#define DRAM0_SRAM_UNI_BLOCK_2 2 -#define DRAM0_SRAM_UNI_BLOCK_3 3 - -//unified management (SRAM blocks 0-3) -#define DRAM0_SRAM_UNI_BLOCK_0_LOW 0x3FFB0000 -#define DRAM0_SRAM_UNI_BLOCK_1_LOW 0x3FFB2000 -#define DRAM0_SRAM_UNI_BLOCK_2_LOW 0x3FFB4000 -#define DRAM0_SRAM_UNI_BLOCK_3_LOW 0x3FFB6000 - -//split management (SRAM blocks 4-21) -#define DRAM0_SRAM_SPL_BLOCK_HIGH 0x3FFFFFFF //block 21 high -#define DRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x3FF00000 //SRAM high bits 31:22 of the faulting address - constant - -#define DRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S) - - -static inline uint32_t *esp_memprot_dram0_sram_get_fault_address(void) +static inline intptr_t memprot_ll_dram0_sram_get_fault_address(void) { - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); - return (uint32_t *)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_SRAM_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_dram0_get_fault_reg(); + return (intptr_t)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_SRAM_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_dram0_sram_is_intr_mine(void) +static inline bool memprot_ll_dram0_sram_is_intr_mine(void) { - if (esp_memprot_dram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_dram0_sram_get_fault_address(); - return (uint32_t)faulting_address >= DRAM0_SRAM_ADDRESS_LOW && (uint32_t)faulting_address <= DRAM0_SRAM_ADDRESS_HIGH; + if (memprot_ll_dram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_dram0_sram_get_fault_address(); + return faulting_address >= DRAM0_SRAM_ADDRESS_LOW && faulting_address <= DRAM0_SRAM_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_dram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit) +static inline bool memprot_ll_dram0_sram_get_uni_block_sgnf_bits(uint32_t block, uint32_t *write_bit, uint32_t *read_bit) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case DRAM0_SRAM_UNI_BLOCK_0: *write_bit = DPORT_PMS_PRO_DRAM0_SRAM_0_W; @@ -648,79 +613,97 @@ static inline void esp_memprot_dram0_sram_get_uni_block_sgnf_bits(uint32_t block *read_bit = DPORT_PMS_PRO_DRAM0_SRAM_3_R; break; default: - abort(); + return false; } + + return true; } -static inline void esp_memprot_dram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm) +static inline memprot_ll_err_t memprot_ll_dram0_sram_set_uni_block_perm(uint32_t block, bool write_perm, bool read_perm) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - - uint32_t write_bit, read_bit; - esp_memprot_dram0_sram_get_uni_block_sgnf_bits(block, &write_bit, &read_bit); + //get block-specific WR flags offset within the conf.register + uint32_t write_bit_offset, read_bit_offset; + if (!memprot_ll_dram0_sram_get_uni_block_sgnf_bits(block, &write_bit_offset, &read_bit_offset)) { + return MEMP_LL_ERR_UNI_BLOCK_INVALID; + } + //set/reset required flags if (write_perm) { - DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit); + DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit_offset); } else { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, write_bit_offset); } if (read_perm) { - DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit); + DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit_offset); } else { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PMS_PRO_DRAM0_1_REG, read_bit_offset); } + + return MEMP_LL_OK; } -static inline uint32_t esp_memprot_dram0_sram_get_uni_block_read_bit(uint32_t block) +static inline bool memprot_ll_dram0_sram_get_uni_block_read_bit(uint32_t block, uint32_t *read_bit) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case DRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_R); + break; case DRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_R); + break; case DRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_R); + break; case DRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_R); + *read_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_R); + break; default: - abort(); + return false; } + + return true; } -static inline uint32_t esp_memprot_dram0_sram_get_uni_block_write_bit(uint32_t block) +static inline bool memprot_ll_dram0_sram_get_uni_block_write_bit(uint32_t block, uint32_t *write_bit) { - HAL_ASSERT(block < DRAM0_SRAM_TOTAL_UNI_BLOCKS); - switch (block) { case DRAM0_SRAM_UNI_BLOCK_0: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_0_W); + break; case DRAM0_SRAM_UNI_BLOCK_1: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_1_W); + break; case DRAM0_SRAM_UNI_BLOCK_2: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_2_W); + break; case DRAM0_SRAM_UNI_BLOCK_3: - return DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_W); + *write_bit = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_3_W); + break; default: - abort(); + return false; } + + return true; } //DRAM0 has both unified blocks and split address configured in 1 register -static inline uint32_t esp_memprot_dram0_sram_get_perm_reg(void) +static inline uint32_t memprot_ll_dram0_sram_get_perm_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG); } -static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +static inline memprot_ll_err_t memprot_ll_dram0_sram_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { uint32_t addr = (uint32_t)split_addr; - //low boundary check provided by LD script. see comment in esp_memprot_iram0_sram_set_prot() - HAL_ASSERT(addr <= DRAM0_SRAM_SPL_BLOCK_HIGH); - HAL_ASSERT(addr % 0x4 == 0 ); + //low boundary check provided by LD script. see comment in memprot_ll_iram0_sram_set_prot() + if (addr > DRAM0_SRAM_SPL_BLOCK_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //set low region int uni_blocks_low = -1; @@ -740,7 +723,9 @@ static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw //set unified mgmt region uint32_t write_bit, read_bit, uni_block_perm = 0; for (int x = 0; x < DRAM0_SRAM_TOTAL_UNI_BLOCKS; x++) { - esp_memprot_dram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit); + if (!memprot_ll_dram0_sram_get_uni_block_sgnf_bits(x, &write_bit, &read_bit)) { + return MEMP_LL_ERR_UNI_BLOCK_INVALID; + } if (x <= uni_blocks_low) { if (lw) { uni_block_perm |= write_bit; @@ -778,9 +763,11 @@ static inline void esp_memprot_dram0_sram_set_prot(uint32_t *split_addr, bool lw //write DRAM0 SRAM cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_1_REG, reg_split_addr | permission_mask | uni_block_perm); + + return MEMP_LL_OK; } -static inline void esp_memprot_dram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) +static inline void memprot_ll_dram0_sram_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_R); @@ -788,13 +775,13 @@ static inline void esp_memprot_dram0_sram_get_split_sgnf_bits(bool *lw, bool *lr *hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_R); } -static inline void esp_memprot_dram0_sram_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_dram0_sram_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_R, hr ? 1 : 0); } -static inline void esp_memprot_dram0_sram_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_dram0_sram_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_1_REG, DPORT_PMS_PRO_DRAM0_SRAM_4_H_W, hw ? 1 : 0); @@ -806,34 +793,35 @@ static inline void esp_memprot_dram0_sram_set_write_perm(bool lw, bool hw) * === DRAM0 RTC FAST * ======================================================================================== */ -#define DRAM0_RTCFAST_ADDRESS_LOW 0x3FF9E000 -#define DRAM0_RTCFAST_ADDRESS_HIGH 0x3FF9FFFF -#define DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x3FF00000 //RTCFAST high bits 31:22 of the faulting address - constant -#define DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR_S) - - -static inline uint32_t *esp_memprot_dram0_rtcfast_get_fault_address(void) +static inline intptr_t memprot_ll_dram0_rtcfast_get_fault_address(void) { - uint32_t status_bits = esp_memprot_dram0_get_fault_reg(); - return (uint32_t *)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); + uint32_t status_bits = memprot_ll_dram0_get_fault_reg(); + return (intptr_t)(((status_bits & DRAM0_INTR_ST_FAULTADDR_M) >> DRAM0_INTR_ST_FAULTADDR_S) | DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI); } -static inline bool esp_memprot_dram0_rtcfast_is_intr_mine(void) +static inline bool memprot_ll_dram0_rtcfast_is_intr_mine(void) { - if (esp_memprot_dram0_is_assoc_intr()) { - uint32_t *faulting_address = esp_memprot_dram0_rtcfast_get_fault_address(); - return (uint32_t)faulting_address >= DRAM0_RTCFAST_ADDRESS_LOW && (uint32_t)faulting_address <= DRAM0_RTCFAST_ADDRESS_HIGH; + if (memprot_ll_dram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_dram0_rtcfast_get_fault_address(); + return faulting_address >= DRAM0_RTCFAST_ADDRESS_LOW && faulting_address <= DRAM0_RTCFAST_ADDRESS_HIGH; } return false; } -static inline void esp_memprot_dram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) +static inline memprot_ll_err_t memprot_ll_dram0_rtcfast_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //addr: 32bit aligned, inside corresponding range + if (addr < DRAM0_RTCFAST_ADDRESS_LOW || addr > DRAM0_RTCFAST_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } //conf reg [10:0] - uint32_t reg_split_addr = DRAM0_RTCFAST_ADDR_TO_CONF_REG( addr ); + uint32_t reg_split_addr = DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr); //prepare high & low permission mask uint32_t permission_mask = 0; @@ -852,9 +840,11 @@ static inline void esp_memprot_dram0_rtcfast_set_prot(uint32_t *split_addr, bool //write DRAM0 RTC FAST cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DRAM0_2_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_dram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) +static inline void memprot_ll_dram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) { *lw = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_W); *lr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_R); @@ -862,18 +852,18 @@ static inline void esp_memprot_dram0_rtcfast_get_split_sgnf_bits(bool *lw, bool *hr = DPORT_REG_GET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_H_R); } -static inline uint32_t esp_memprot_dram0_rtcfast_get_perm_split_reg(void) +static inline uint32_t memprot_ll_dram0_rtcfast_get_perm_split_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DRAM0_2_REG); } -static inline void esp_memprot_dram0_rtcfast_set_read_perm(bool lr, bool hr) +static inline void memprot_ll_dram0_rtcfast_set_read_perm(bool lr, bool hr) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_R, lr ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_H_R, hr ? 1 : 0); } -static inline void esp_memprot_dram0_rtcfast_set_write_perm(bool lw, bool hw) +static inline void memprot_ll_dram0_rtcfast_set_write_perm(bool lw, bool hw) { DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_L_W, lw ? 1 : 0); DPORT_REG_SET_FIELD(DPORT_PMS_PRO_DRAM0_2_REG, DPORT_PMS_PRO_DRAM0_RTCFAST_H_W, hw ? 1 : 0); diff --git a/components/hal/esp32s2/include/hal/memprot_peri_ll.h b/components/hal/esp32s2/include/hal/memprot_peri_ll.h index d699df6cf4..4611f7a35d 100644 --- a/components/hal/esp32s2/include/hal/memprot_peri_ll.h +++ b/components/hal/esp32s2/include/hal/memprot_peri_ll.h @@ -14,38 +14,31 @@ #pragma once -#include "hal/assert.h" +#include +#include "soc/memprot_defs.h" +#include "hal/memprot_types.h" #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) +static inline void memprot_ll_peri1_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_CLR); DPORT_CLEAR_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) +static inline uint32_t memprot_ll_peri1_get_intr_source_num(void) { return ETS_PMS_PRO_DPORT_ILG_INTR_SOURCE; } -static inline void esp_memprot_peri1_intr_ena(bool enable) +static inline void memprot_ll_peri1_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_DPORT_6_REG, DPORT_PMS_PRO_DPORT_ILG_EN); @@ -54,95 +47,94 @@ static inline void esp_memprot_peri1_intr_ena(bool enable) } } -static inline uint32_t esp_memprot_peri1_get_ctrl_reg(void) +static inline uint32_t memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline void memprot_ll_peri1_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_peri1_get_fault_reg(); + uint32_t status_bits = memprot_ll_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) +static inline bool memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline void memprot_ll_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) +static inline uint32_t memprot_ll_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 - -#define PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR) << DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR_S) - -static inline uint32_t *esp_memprot_peri1_rtcslow_get_fault_address(void) +static inline intptr_t memprot_ll_peri1_rtcslow_get_fault_address(void) { - uint32_t status_bits = esp_memprot_peri1_get_fault_reg(); + uint32_t status_bits = memprot_ll_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); + return (intptr_t)(fault_address | high_bits); } -static inline bool esp_memprot_peri1_rtcslow_is_intr_mine(void) +static inline bool memprot_ll_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; + if (memprot_ll_dram0_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_peri1_rtcslow_get_fault_address(); + return faulting_address >= PERI1_RTCSLOW_ADDRESS_LOW && 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) +static inline memprot_ll_err_t memprot_ll_peri1_rtcslow_set_prot(uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr) { uint32_t addr = (uint32_t)split_addr; - HAL_ASSERT(addr % 0x4 == 0); + + //check corresponding range fit & aligment to 32bit boundaries + if (addr < PERI1_RTCSLOW_ADDRESS_LOW || addr > PERI1_RTCSLOW_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t reg_split_addr = PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr); @@ -163,9 +155,11 @@ static inline void esp_memprot_peri1_rtcslow_set_prot(uint32_t *split_addr, bool //write PERIBUS1 RTC SLOW cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_peri1_rtcslow_get_split_sgnf_bits(bool *lw, bool *lr, bool *hw, bool *hr) +static inline void memprot_ll_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); @@ -173,46 +167,40 @@ static inline void esp_memprot_peri1_rtcslow_get_split_sgnf_bits(bool *lw, bool *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) +static inline void memprot_ll_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) +static inline void memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline void memprot_ll_peri2_clear_intr(void) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_CLR); DPORT_CLEAR_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) +static inline uint32_t memprot_ll_peri2_get_intr_source_num(void) { return ETS_PMS_PRO_AHB_ILG_INTR_SOURCE; } -static inline void esp_memprot_peri2_intr_ena(bool enable) +static inline void memprot_ll_peri2_intr_ena(bool enable) { if (enable) { DPORT_SET_PERI_REG_MASK(DPORT_PMS_PRO_AHB_3_REG, DPORT_PMS_PRO_AHB_ILG_EN); @@ -221,90 +209,90 @@ static inline void esp_memprot_peri2_intr_ena(bool enable) } } -static inline uint32_t esp_memprot_peri2_get_ctrl_reg(void) +static inline uint32_t memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline void memprot_ll_peri2_get_fault_op_type(uint32_t *op_type, uint32_t *op_subtype) { - uint32_t status_bits = esp_memprot_peri2_get_fault_reg(); + uint32_t status_bits = memprot_ll_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) +static inline bool memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline void memprot_ll_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) +static inline uint32_t memprot_ll_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) +static inline intptr_t memprot_ll_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); + uint32_t status_bits = memprot_ll_peri2_get_fault_reg(); + return (intptr_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 - -#define PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR_S) - -static inline bool esp_memprot_peri2_rtcslow_0_is_intr_mine(void) +static inline bool memprot_ll_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; + if (memprot_ll_peri2_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_peri2_rtcslow_get_fault_address(); + return faulting_address >= PERI2_RTCSLOW_0_ADDRESS_LOW && 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) +static inline memprot_ll_err_t memprot_ll_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; - HAL_ASSERT(addr % 0x4 == 0); + + //check corresponding range fit & aligment to 32bit boundaries + if (addr < PERI2_RTCSLOW_0_ADDRESS_LOW || addr > PERI2_RTCSLOW_0_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t reg_split_addr = PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr); @@ -331,9 +319,11 @@ static inline void esp_memprot_peri2_rtcslow_0_set_prot(uint32_t *split_addr, bo //write PERIBUS1 RTC SLOW cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_1_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_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); @@ -343,25 +333,25 @@ static inline void esp_memprot_peri2_rtcslow_0_get_split_sgnf_bits(bool *lw, boo *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) +static inline void memprot_ll_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) +static inline void memprot_ll_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) +static inline void memprot_ll_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) +static inline uint32_t memprot_ll_peri2_rtcslow_0_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_1_REG); } @@ -371,25 +361,26 @@ static inline uint32_t esp_memprot_peri2_rtcslow_0_get_conf_reg(void) * === 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 - -#define PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR_S) - -static inline bool esp_memprot_peri2_rtcslow_1_is_intr_mine(void) +static inline bool memprot_ll_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; + if (memprot_ll_peri2_is_assoc_intr()) { + uint32_t faulting_address = (uint32_t)memprot_ll_peri2_rtcslow_get_fault_address(); + return faulting_address >= PERI2_RTCSLOW_1_ADDRESS_LOW && 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) +static inline memprot_ll_err_t memprot_ll_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; - HAL_ASSERT(addr % 0x4 == 0); + + //check corresponding range fit & aligment to 32bit boundaries + if (addr < PERI2_RTCSLOW_1_ADDRESS_LOW || addr > PERI2_RTCSLOW_1_ADDRESS_HIGH) { + return MEMP_LL_ERR_SPLIT_ADDR_INVALID; + } + if (addr % 0x4 != 0) { + return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED; + } uint32_t reg_split_addr = PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr); @@ -416,9 +407,11 @@ static inline void esp_memprot_peri2_rtcslow_1_set_prot(uint32_t *split_addr, bo //write PERIBUS1 RTC SLOW cfg register DPORT_WRITE_PERI_REG(DPORT_PMS_PRO_AHB_2_REG, reg_split_addr | permission_mask); + + return MEMP_LL_OK; } -static inline void esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx) +static inline void memprot_ll_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); @@ -428,25 +421,25 @@ static inline void esp_memprot_peri2_rtcslow_1_get_split_sgnf_bits(bool *lw, boo *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) +static inline void memprot_ll_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) +static inline void memprot_ll_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) +static inline void memprot_ll_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) +static inline uint32_t memprot_ll_peri2_rtcslow_1_get_conf_reg(void) { return DPORT_READ_PERI_REG(DPORT_PMS_PRO_DPORT_2_REG); } diff --git a/components/hal/include/hal/memprot_types.h b/components/hal/include/hal/memprot_types.h new file mode 100644 index 0000000000..42231f43ea --- /dev/null +++ b/components/hal/include/hal/memprot_types.h @@ -0,0 +1,35 @@ +// Copyright 2015-2021 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 + +/** + * @brief Memprot LL error codes + * + */ +typedef enum { + MEMP_LL_OK = 0, + MEMP_LL_FAIL = 1, + MEMP_LL_ERR_SPLIT_ADDR_INVALID = 2, + MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED = 3, + MEMP_LL_ERR_UNI_BLOCK_INVALID = 4 +} memprot_ll_err_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32s2/include/soc/memprot_defs.h b/components/soc/esp32s2/include/soc/memprot_defs.h new file mode 100644 index 0000000000..f4b4ab9423 --- /dev/null +++ b/components/soc/esp32s2/include/soc/memprot_defs.h @@ -0,0 +1,131 @@ +// 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 + +#include "soc/soc.h" +#include "soc/sensitive_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//IRAM0 interrupt status bitmasks +#define IRAM0_INTR_ST_OP_TYPE_BIT BIT(1) //instruction: 0, data: 1 +#define IRAM0_INTR_ST_OP_RW_BIT BIT(0) //read: 0, write: 1 + +#define CONF_REG_ADDRESS_SHIFT 2 + +//IRAM0 range +#define IRAM0_SRAM_BASE_ADDRESS 0x40000000 +#define IRAM0_SRAM_ADDRESS_LOW 0x40020000 +#define IRAM0_SRAM_ADDRESS_HIGH 0x4006FFFF + +//IRAM0 unified managemnt blocks +#define IRAM0_SRAM_TOTAL_UNI_BLOCKS 4 +#define IRAM0_SRAM_UNI_BLOCK_0 0 +#define IRAM0_SRAM_UNI_BLOCK_1 1 +#define IRAM0_SRAM_UNI_BLOCK_2 2 +#define IRAM0_SRAM_UNI_BLOCK_3 3 + +//unified management addr range (blocks 0-3) +#define IRAM0_SRAM_UNI_BLOCK_0_LOW 0x40020000 +#define IRAM0_SRAM_UNI_BLOCK_1_LOW 0x40022000 +#define IRAM0_SRAM_UNI_BLOCK_2_LOW 0x40024000 +#define IRAM0_SRAM_UNI_BLOCK_3_LOW 0x40026000 + +//split management addr range (blocks 4-21) +#define IRAM0_SRAM_SPL_BLOCK_LOW 0x40028000 //block 4 low +#define IRAM0_SRAM_SPL_BLOCK_HIGH 0x4006FFFF //block 21 high + +#define IRAM0_INTR_ST_FAULTADDR_M 0x003FFFFC //bits 21:6 in the reg, as well as in real address +#define IRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x40000000 //high nonsignificant bits 31:22 of the faulting address - constant + +#define IRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_IRAM0_SRAM_4_SPLTADDR_S) + +//IRAM0 RTCFAST +#define IRAM0_RTCFAST_ADDRESS_LOW 0x40070000 +#define IRAM0_RTCFAST_ADDRESS_HIGH 0x40071FFF +#define IRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x40070000 //RTCFAST faulting address high bits (31:22, constant) + +#define IRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_IRAM0_RTCFAST_SPLTADDR_S) + +//DRAM0 interrupt status bitmasks +#define DRAM0_INTR_ST_FAULTADDR_M 0x03FFFFC0 //(bits 25:6 in the reg) +#define DRAM0_INTR_ST_FAULTADDR_S 0x4 //(bits 21:2 of real address) +#define DRAM0_INTR_ST_OP_RW_BIT BIT(4) //read: 0, write: 1 +#define DRAM0_INTR_ST_OP_ATOMIC_BIT BIT(5) //non-atomic: 0, atomic: 1 + +#define DRAM0_SRAM_ADDRESS_LOW 0x3FFB0000 +#define DRAM0_SRAM_ADDRESS_HIGH 0x3FFFFFFF + +#define DRAM0_SRAM_TOTAL_UNI_BLOCKS 4 +#define DRAM0_SRAM_UNI_BLOCK_0 0 +#define DRAM0_SRAM_UNI_BLOCK_1 1 +#define DRAM0_SRAM_UNI_BLOCK_2 2 +#define DRAM0_SRAM_UNI_BLOCK_3 3 + +//unified management (SRAM blocks 0-3) +#define DRAM0_SRAM_UNI_BLOCK_0_LOW 0x3FFB0000 +#define DRAM0_SRAM_UNI_BLOCK_1_LOW 0x3FFB2000 +#define DRAM0_SRAM_UNI_BLOCK_2_LOW 0x3FFB4000 +#define DRAM0_SRAM_UNI_BLOCK_3_LOW 0x3FFB6000 + +//split management (SRAM blocks 4-21) +#define DRAM0_SRAM_SPL_BLOCK_HIGH 0x3FFFFFFF //block 21 high +#define DRAM0_SRAM_INTR_ST_FAULTADDR_HI 0x3FF00000 //SRAM high bits 31:22 of the faulting address - constant + +#define DRAM0_SRAM_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR) << DPORT_PMS_PRO_DRAM0_SRAM_4_SPLTADDR_S) + +//DRAM0 RTCFAST +#define DRAM0_RTCFAST_ADDRESS_LOW 0x3FF9E000 +#define DRAM0_RTCFAST_ADDRESS_HIGH 0x3FF9FFFF +#define DRAM0_RTCFAST_INTR_ST_FAULTADDR_HI 0x3FF00000 //RTCFAST high bits 31:22 of the faulting address - constant +#define DRAM0_RTCFAST_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR) << DPORT_PMS_PRO_DRAM0_RTCFAST_SPLTADDR_S) + +//RTCSLOW +#define RTCSLOW_MEMORY_SIZE 0x00002000 + +//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) + +#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 + +#define PERI1_RTCSLOW_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR) << DPORT_PMS_PRO_DPORT_RTCSLOW_SPLTADDR_S) + +//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) + +#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 + +#define PERI2_RTCSLOW_0_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_0_SPLTADDR_S) + +#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 + +#define PERI2_RTCSLOW_1_ADDR_TO_CONF_REG(addr) (((addr >> CONF_REG_ADDRESS_SHIFT) & DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR) << DPORT_PMS_PRO_AHB_RTCSLOW_1_SPLTADDR_S) + +#ifdef __cplusplus +} +#endif diff --git a/tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c b/tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c index 1ad8333ea6..0dc7bf9c90 100644 --- a/tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c +++ b/tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c @@ -313,13 +313,23 @@ static void __attribute__((unused)) dump_bus_permissions(mem_type_prot_t mem_typ 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) - ); + esp_err_t res = esp_memprot_get_fault_status(mem_type, &faulting_address, &op_type, &op_subtype); + if ( res == ESP_OK ) { + uint32_t fault_reg; + res = esp_memprot_get_fault_reg(mem_type, &fault_reg); + esp_rom_printf( + " FAULT [split addr: 0x%08X, fault addr: 0x%08X, fault status: ", + (uint32_t) test_memprot_get_split_addr(mem_type), + (uint32_t) faulting_address + ); + if ( res == ESP_OK ) { + esp_rom_printf("0x%08X]\n", fault_reg ); + } else { + esp_rom_printf("]\n", res ); + } + } else { + esp_rom_printf(" FAULT [failed to get fault details, error 0x%08X]\n", res); + } } @@ -328,13 +338,17 @@ static void __attribute__((unused)) dump_status_register(mem_type_prot_t mem_typ */ 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"); + uint32_t fault; + esp_err_t res = esp_memprot_get_fault_reg(mem_type, &fault); + if ( res == ESP_OK ) { + bool test_result = expected_status ? fault == 0 : fault != 0; + if (test_result) { + esp_rom_printf("OK\n"); + } else { + dump_status_register(mem_type); + } } else { - dump_status_register(mem_type); + esp_rom_printf(" FAULT [failed to get test results, error 0x%08X]\n", res); } }