Răsfoiți Sursa

System/Security: Memprot API unified (ESP32C3,ESP32S3)

Unified Memory protection API for all PMS-aware chips

Closes JIRA IDF-3849
Martin Vychodil 4 ani în urmă
părinte
comite
7d9652dccf
40 a modificat fișierele cu 3461 adăugiri și 3090 ștergeri
  1. 2 1
      components/esp_common/CMakeLists.txt
  2. 7 13
      components/esp_common/include/esp_err.h
  3. 30 0
      components/esp_common/src/esp_err_to_name.c
  4. 199 0
      components/esp_hw_support/include/esp_memprot.h
  5. 28 0
      components/esp_hw_support/include/esp_memprot_err.h
  6. 36 0
      components/esp_hw_support/include/esp_memprot_types.h
  7. 199 0
      components/esp_hw_support/include/esp_private/esp_memprot_internal.h
  8. 0 449
      components/esp_hw_support/include/soc/esp32c3/memprot.h
  9. 175 0
      components/esp_hw_support/include/soc/esp32c3/soc_memprot_types.h
  10. 0 448
      components/esp_hw_support/include/soc/esp32h2/memprot.h
  11. 117 0
      components/esp_hw_support/include/soc/esp32h2/soc_memprot_types.h
  12. 117 0
      components/esp_hw_support/include/soc/esp32s2/soc_memprot_types.h
  13. 0 484
      components/esp_hw_support/include/soc/esp32s3/memprot.h
  14. 119 0
      components/esp_hw_support/include/soc/esp32s3/soc_memprot_types.h
  15. 5 1
      components/esp_hw_support/port/esp32c3/CMakeLists.txt
  16. 869 0
      components/esp_hw_support/port/esp32c3/esp_memprot.c
  17. 0 617
      components/esp_hw_support/port/esp32c3/memprot.c
  18. 5 1
      components/esp_hw_support/port/esp32h2/CMakeLists.txt
  19. 215 0
      components/esp_hw_support/port/esp32h2/esp_memprot.c
  20. 0 608
      components/esp_hw_support/port/esp32h2/memprot.c
  21. 4 1
      components/esp_hw_support/port/esp32s3/CMakeLists.txt
  22. 215 0
      components/esp_hw_support/port/esp32s3/esp_memprot.c
  23. 0 17
      components/esp_hw_support/port/esp32s3/memprot.c
  24. 63 0
      components/esp_hw_support/port/esp_memprot_conv.c
  25. 13 6
      components/esp_system/esp_system.c
  26. 3 2
      components/esp_system/ld/esp32c3/sections.ld.in
  27. 54 30
      components/esp_system/port/arch/riscv/panic_arch.c
  28. 7 11
      components/esp_system/port/arch/xtensa/panic_arch.c
  29. 36 23
      components/esp_system/port/cpu_start.c
  30. 16 7
      components/esp_system/port/panic_handler.c
  31. 418 171
      components/hal/esp32c3/include/hal/memprot_ll.h
  32. 30 15
      components/hal/include/hal/memprot_types.h
  33. 100 0
      components/soc/esp32c3/include/soc/memprot_defs.h
  34. 0 4
      tools/ci/check_copyright_ignore.txt
  35. 1 1
      tools/test_apps/system/memprot/README.md
  36. 2 1
      tools/test_apps/system/memprot/app_test.py
  37. 2 3
      tools/test_apps/system/memprot/main/Kconfig.projbuild
  38. 371 175
      tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c
  39. 0 1
      tools/test_apps/system/memprot/sdkconfig.ci
  40. 3 0
      tools/test_apps/system/memprot/sdkconfig.defaults

+ 2 - 1
components/esp_common/CMakeLists.txt

@@ -33,7 +33,8 @@ set(optional_reqs ulp
                     esp_netif
                     soc
                     esp-tls
-                    esp_https_ota)
+                    esp_https_ota
+                    esp_hw_support)
 
 idf_build_get_property(build_components BUILD_COMPONENTS)
 foreach(req ${optional_reqs})

+ 7 - 13
components/esp_common/include/esp_err.h

@@ -1,16 +1,9 @@
-// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
 #pragma once
 
 #include <stdint.h>
@@ -46,6 +39,7 @@ typedef int esp_err_t;
 #define ESP_ERR_MESH_BASE           0x4000  /*!< Starting number of MESH error codes */
 #define ESP_ERR_FLASH_BASE          0x6000  /*!< Starting number of flash error codes */
 #define ESP_ERR_HW_CRYPTO_BASE      0xc000  /*!< Starting number of HW cryptography module error codes */
+#define ESP_ERR_MEMPROT_BASE        0xd000  /*!< Starting number of Memory Protection API error codes */
 
 /**
   * @brief Returns string for esp_err_t error codes

+ 30 - 0
components/esp_common/src/esp_err_to_name.c

@@ -23,6 +23,9 @@
 #if __has_include("esp_image_format.h")
 #include "esp_image_format.h"
 #endif
+#if __has_include("esp_memprot_err.h")
+#include "esp_memprot_err.h"
+#endif
 #if __has_include("esp_mesh.h")
 #include "esp_mesh.h"
 #endif
@@ -758,6 +761,33 @@ static const esp_err_msg_t esp_err_msg_table[] = {
 #   endif
 #   ifdef      ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING
     ERR_TBL_IT(ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING),           /* 49157 0xc005 */
+#   endif
+    // components/esp_common/include/esp_err.h
+#   ifdef      ESP_ERR_MEMPROT_BASE
+    ERR_TBL_IT(ESP_ERR_MEMPROT_BASE),                           /* 53248 0xd000 Starting number of Memory Protection API
+                                                                                error codes */
+#   endif
+    // components/esp_hw_support/include/esp_memprot_err.h
+#   ifdef      ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID
+    ERR_TBL_IT(ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID),            /* 53249 0xd001 */
+#   endif
+#   ifdef      ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID
+    ERR_TBL_IT(ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID),             /* 53250 0xd002 */
+#   endif
+#   ifdef      ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE
+    ERR_TBL_IT(ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE),        /* 53251 0xd003 */
+#   endif
+#   ifdef      ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED
+    ERR_TBL_IT(ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED),           /* 53252 0xd004 */
+#   endif
+#   ifdef      ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID
+    ERR_TBL_IT(ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID),          /* 53253 0xd005 */
+#   endif
+#   ifdef      ESP_ERR_MEMPROT_WORLD_INVALID
+    ERR_TBL_IT(ESP_ERR_MEMPROT_WORLD_INVALID),                  /* 53254 0xd006 */
+#   endif
+#   ifdef      ESP_ERR_MEMPROT_AREA_INVALID
+    ERR_TBL_IT(ESP_ERR_MEMPROT_AREA_INVALID),                   /* 53255 0xd007 */
 #   endif
 };
 #endif //CONFIG_ESP_ERR_TO_NAME_LOOKUP

+ 199 - 0
components/esp_hw_support/include/esp_memprot.h

@@ -0,0 +1,199 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// ESP Memory Protection API (PMS)
+// - allows configuration and violation-interrupt handling of the PMS module operations
+// - not intended for public use.
+
+#pragma once
+
+#include "sdkconfig.h"
+#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "esp_err.h"
+#include "esp_memprot_err.h"
+#include "soc_memprot_types.h"
+#include "esp_memprot_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ESP_MEMPROT_ERR_CHECK(retval, fnc) if ((retval=fnc) != ESP_OK) { return retval; }
+
+/**
+* @brief Basic PMS interrupt source info
+*/
+typedef struct {
+    esp_mprot_mem_t mem_type;   /*!< Memory type containing the faulting address  */
+    int core;                   /*!< CPU/Core ID running the faulting instruction  */
+} esp_memp_intr_source_t;
+
+/**
+ * @brief Clears current interrupt ON flag for given Memory type and CPU/Core ID
+ *
+ * This operation is non-atomic for some chips by PMS module design
+ * In such a case the interrupt clearing happens in two steps:
+ *      1. Interrupt CLR flag is set (clears interrupt-ON status and inhibits linked interrupt processing)
+ *      2. Interrupt CLR flag is reset (resumes the interrupt monitoring)
+ *
+ * @param mem_type Memory type (see esp_mprot_mem_t enum)
+ * @param core Target CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_INVALID_ARG on passing invalid pointer
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ */
+esp_err_t esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core);
+
+/**
+ * @brief Checks whether any of the PMS settings is locked
+ *
+ * @param[out] locked Any lock on? (true/false)
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_INVALID_ARG on invalid locked ptr
+ *         Other failures: error code of any failing esp_mprot_get_*_lock() routine (called internally)
+ */
+esp_err_t esp_mprot_is_conf_locked_any(bool *locked);
+
+/**
+ * @brief Checks whether any PMS violation-interrupt monitoring is enabled
+ *
+ * @param[out] locked Any PMS violation interrupt monitor is enabled (true/false)
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_INVALID_ARG on invalid enabled ptr
+ *         Other failures: error code of esp_mprot_get_monitor_en() routine (called internally for all Memory types)
+ */
+esp_err_t esp_mprot_is_intr_ena_any(bool *enabled);
+
+/**
+ * @brief Returns active PMS violation-interrupt Memory type if any (MEMPROT_TYPE_NONE when none detected)
+ * and the CPU/CoreID which was running the faulty code (-1 when no interrupt available)
+ *
+ * If there are more interrupts indicated on (shouldn't happen), the order of precedence is given by 'esp_mprot_mem_t' enum definition (low->high)
+ *
+ * @param[out] mem_type Out-pointer for Memory type given by the faulting address (see esp_mprot_mem_t enum)
+ * @param[out] core Out-pointer for CPU/Core ID (see *_CPU_NUM defs in soc.h)
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_INVALID_ARG on passing invalid pointer(s)
+ */
+esp_err_t esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr);
+
+/**
+ * @brief Returns the address which caused the violation interrupt for given Memory type and CPU/Core ID.
+ * This function is to be called after a basic resolving of (current) interrupt's parameters (ie corresponding
+ * Memory type and CPU ID see esp_mprot_get_active_intr()). This is to minimize processing time of actual exception
+ * as this API is typicaly used in a panic-handling code.
+ * If there is no active interrupt available for the Memory type/CPU ID required, fault_addr is set to NULL.
+ *
+ * @param mem_type memory type
+ * @param[out] fault_addr Address of the operation which caused the PMS violation interrupt
+ * @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ *         ESP_ERR_INVALID_ARG on invalid fault_addr pointer
+ */
+esp_err_t esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core);
+
+/**
+ * @brief Returns PMS World identifier of the code causing the violation interrupt
+ *
+ * The value is read from appropriate PMS violation status register and thus might be 0 if the interrupt is not currently active.
+ *
+ * @param mem_type Memory type
+ * @param[out] world PMS World type (see esp_mprot_pms_world_t)
+ * @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ *         ESP_ERR_INVALID_ARG on passing invalid pointer(s)
+ *         ESP_ERR_MEMPROT_WORLD_INVALID on invalid World identifier fetched from the register
+ */
+esp_err_t esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core);
+
+/**
+ * @brief Returns an operation type which caused the violation interrupt
+ *
+ * The operation resolving is processed over various PMS status register flags, according to given Memory type argument.
+ * If the interrupt is not active the result returned is irrelevant (likely evaluated to MEMPROT_OP_READ).
+ *
+ * @param mem_type Memory type
+ * @param[out] oper Operation type (see MEMPROT_OP_* defines)
+ * @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ *         ESP_ERR_INVALID_ARG on invalid oper pointer
+ */
+esp_err_t esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core);
+
+/**
+ * @brief Checks whether given memory type supports byte-enables info
+ *
+ * Byte-enables status is available only for DMA/DRAM operations
+  *
+ * @param mem_type memory type
+ *
+ * @return byte-enables info available true/false
+ */
+bool esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type);
+
+/**
+ * @brief Returns byte-enables for the address which caused the violation interrupt
+ *
+ * The value is taken from appropriate PMS violation status register, based on given Memory type
+ *
+ * @param mem_type Memory type (MEMPROT_TYPE_DRAM0_SRAM)
+ * @param[out] byte_en Byte-enables bits
+ * @param core Faulting instruction CPU/Core ID (see *_CPU_NUM defs in soc.h). Can be NULL on 1-CPU systems
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ *         ESP_ERR_INVALID_ARGUMENT on invalid byte_en pointer
+ */
+esp_err_t esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core);
+
+/**
+ * @brief Convenient routine for setting the PMS defaults
+ *
+ * Called on system startup, depending on ESP_SYSTEM_MEMPROT_FEATURE Kconfig value
+ *
+ * @param memp_config pointer to Memprot configuration structure (esp_memp_config_t). The structure si chip-specific,
+ * for details and defaults see appropriate [target-chip]/soc_memprot_types.h
+ *
+ * @return ESP_OK on success
+ *         Other failures: error code of the failing routine called internally. No specific error processing provided in such a case
+ *         due to large number of embedded calls (ie no global unique error table is provided and thus one error code can have different meanings,
+ *         depending on the routine issuing the error)
+ */
+esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config);
+
+/**
+ * @brief Generates PMS configuration string of actual device (diagnostics)
+ *
+ * The functions generates a string from current configuration, control and status registers of the PMS (or similar) module of actual device.
+ * The values are fetched using HAL LL calls to help finding possible errors in the Memprot API implementation
+ *
+ * @param[out] dump_info_string configuration string buffer pointer. The string is allocated by the callee and must be freed by the caller.
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_NO_MEM on buffer allocation failure
+ *         ESP_ERR_INVALID_ARGUMENT on invalid dump_info_string pointer
+ */
+esp_err_t esp_mprot_dump_configuration(char **dump_info_string);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST

+ 28 - 0
components/esp_hw_support/include/esp_memprot_err.h

@@ -0,0 +1,28 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+*
+* SPDX-License-Identifier: Apache-2.0
+*/
+
+#pragma once
+
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @brief ESP Memprot API error code definition
+*/
+#define ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID     (ESP_ERR_MEMPROT_BASE + 1)   /**< Memory type invalid in given context */
+#define ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID      (ESP_ERR_MEMPROT_BASE + 2)   /**< Splitting address invalid in given context */
+#define ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE (ESP_ERR_MEMPROT_BASE + 3)   /**< Splitting address out of range */
+#define ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED    (ESP_ERR_MEMPROT_BASE + 4)   /**< Splitting address not aligned to required boundaries */
+#define ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID   (ESP_ERR_MEMPROT_BASE + 5)   /**< Required unified-management block is not valid */
+#define ESP_ERR_MEMPROT_WORLD_INVALID           (ESP_ERR_MEMPROT_BASE + 6)   /**< Required World identifier is not valid */
+#define ESP_ERR_MEMPROT_AREA_INVALID            (ESP_ERR_MEMPROT_BASE + 7)   /**< Required Area identifier is not valid */
+
+#ifdef __cplusplus
+}
+#endif

+ 36 - 0
components/esp_hw_support/include/esp_memprot_types.h

@@ -0,0 +1,36 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief PMS World type (attribute per PMS area, similar to x86 Ring scheme)
+ */
+typedef enum {
+    MEMPROT_PMS_WORLD_NONE                      = 0x00000000,
+    MEMPROT_PMS_WORLD_0                         = 0x00000001,
+    MEMPROT_PMS_WORLD_1                         = 0x00000002,
+    MEMPROT_PMS_WORLD_2                         = 0x00000004,
+    MEMPROT_PMS_WORLD_ALL                       = 0x7FFFFFFF,
+    MEMPROT_PMS_WORLD_INVALID                   = 0x80000000
+} esp_mprot_pms_world_t;
+
+/**
+ * @brief Memory operation/permission type recognized by PMS
+ */
+#define MEMPROT_OP_NONE                         0x00000000
+#define MEMPROT_OP_READ                         0x00000001
+#define MEMPROT_OP_WRITE                        0x00000002
+#define MEMPROT_OP_EXEC                         0x00000004
+#define MEMPROT_OP_INVALID                      0x80000000
+
+#ifdef __cplusplus
+}
+#endif

+ 199 - 0
components/esp_hw_support/include/esp_private/esp_memprot_internal.h

@@ -0,0 +1,199 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include "sdkconfig.h"
+#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "esp_err.h"
+#include "esp_memprot_err.h"
+#include "hal/memprot_types.h"
+#include "soc_memprot_types.h"
+#include "esp_memprot_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @brief Convert Memprot low level errors to esp_err_t
+*/
+esp_err_t esp_mprot_ll_err_to_esp_err(const memprot_ll_err_t err);
+
+/**
+ * @brief Convert Memprot low level PMS World IDs to esp_mprot_pms_world_t
+ */
+esp_mprot_pms_world_t esp_mprot_ll_world_to_hl_world(const memprot_ll_world_t world);
+
+/**
+ * @brief Converts operation type to string, no combination of operations allowed
+ *
+ * @param oper_type PMS operation type
+ */
+const char *esp_mprot_oper_type_to_str(const uint32_t oper_type);
+
+/**
+ * @brief Converts PMS World type to string
+ *
+ * @param area_type PMS World type
+ */
+const char *esp_mprot_pms_world_to_str(const esp_mprot_pms_world_t world_type);
+
+/**
+ * @brief Sets splitting address for given line type in the target Memory type
+ *
+ * @param mem_type memory type
+ * @param line_type split address type
+ * @param line_addr target address from a memory range relevant to given line_addr
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ *         ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID on invalid line_type
+ *         ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE on splitting line out of given memory-type range
+ *         ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED on splitting line not aligned to PMS-required boundaries
+ */
+esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr);
+
+/**
+ * @brief Gets PMS splitting address for given split_addr type
+ *
+ * The value is read from the PMS configuration registers
+ *
+ * @param mem_type memory type
+ * @param line_type Split line type (see esp_mprot_split_addr_t enum)
+ * @param[out] line_addr Split line address from the configuration register
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_INVALID_ARG on line_addr is pointer
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ *         ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID on invalid line_type
+ */
+esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr);
+
+/**
+ * @brief Returns default main I/D splitting address for given Memory type
+ *
+ * @param mem_type memory type
+ * @param[out] def_split_addr Main I/D splitting address of required mem_type
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_INVALID_ARG on invalid def_split_addr pointer
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ */
+esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr);
+
+/**
+ * @brief Sets a lock for the main IRAM/DRAM splitting addresses
+ * Locks can be unlocked only by digital system reset
+ *
+ * @param mem_type memory type
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ */
+esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type);
+
+/**
+ * @brief Gets a lock status for the splitting address configuration of given Memory type
+ *
+ * @param mem_type memory type
+ * @param[out] locked mem_type related lock status
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_INVALID_ARGUMENT on invalid locked pointer
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ */
+esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked);
+
+/**
+ * @brief Sets a lock for PMS Area settings of required Memory type
+ * Locks can be unlocked only by digital system reset
+ *
+ * @param mem_type memory type
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ */
+esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type);
+
+/**
+ * @brief Gets a lock status for PMS Area settings of required Memory type
+ *
+ * @param mem_type memory type
+ * @param[out] locked mem_type related lock status
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ *         ESP_ERR_INVALID_ARGUMENT on invalid locked pointer
+ */
+esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked);
+
+/**
+ * @brief Sets permissions for given PMS Area
+ *
+ * @param area_type PMS area type
+ * @param flags combination of MEMPROT_OP_* defines
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ */
+esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags);
+
+/**
+ * @brief Gets current permissions for given PMS Area
+ *
+ * @param area_type PMS area type
+ * @param[out] flags combination of MEMPROT_OP_* defines
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ *         ESP_ERR_INVALID_ARG on invalid flags pointer
+ */
+esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags);
+
+/**
+ * @brief Sets a lock for PMS interrupt monitor settings of required Memory type
+ *
+ * Locks can be unlocked only by digital system reset
+ *
+ * @param mem_type memory type (see esp_mprot_mem_t enum)
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ */
+esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type);
+
+/**
+ * @brief Gets a lock status for PMS interrupt monitor settings of required Memory type
+ *
+ * @param mem_type memory type
+ * @param[out] locked mem_type related lock status
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ *         ESP_ERR_INVALID_ARG on invalid locked pointer
+ */
+esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked);
+
+/**
+ * @brief Enable PMS violation interrupt monitoring of required Memory type
+ *
+ * @param mem_type memory type
+ * @param enable enable/disable violation interrupt monitoring
+ *
+ * @return ESP_OK on success
+ *         ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID on invalid mem_type
+ */
+esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE || CONFIG_ESP_SYSTEM_MEMPROT_TEST

+ 0 - 449
components/esp_hw_support/include/soc/esp32c3/memprot.h

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

+ 175 - 0
components/esp_hw_support/include/soc/esp32c3/soc_memprot_types.h

@@ -0,0 +1,175 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+//////////////////////////////////////////////////////////
+// ESP32-C3 PMS memory protection types
+//
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Memory types recognized by PMS
+ */
+typedef enum {
+    MEMPROT_TYPE_NONE                           = 0x00000000,
+    MEMPROT_TYPE_IRAM0_SRAM                     = 0x00000001,
+    MEMPROT_TYPE_DRAM0_SRAM                     = 0x00000002,
+    MEMPROT_TYPE_IRAM0_RTCFAST                  = 0x00000004,
+    MEMPROT_TYPE_ALL                            = 0x7FFFFFFF,
+    MEMPROT_TYPE_INVALID                        = 0x80000000,
+    MEMPROT_TYPE_IRAM0_ANY                      = MEMPROT_TYPE_IRAM0_SRAM | MEMPROT_TYPE_IRAM0_RTCFAST
+} esp_mprot_mem_t;
+
+/**
+ * @brief Splitting address (line) type
+ */
+typedef enum {
+    MEMPROT_SPLIT_ADDR_NONE                     = 0x00000000,
+    MEMPROT_SPLIT_ADDR_IRAM0_DRAM0              = 0x00000001,
+    MEMPROT_SPLIT_ADDR_IRAM0_LINE_0             = 0x00000002,
+    MEMPROT_SPLIT_ADDR_IRAM0_LINE_1             = 0x00000004,
+    MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0         = 0x00000008,
+    MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1         = 0x00000010,
+    MEMPROT_SPLIT_ADDR_ALL                      = 0x7FFFFFFF,
+    MEMPROT_SPLIT_ADDR_INVALID                  = 0x80000000,
+    MEMPROT_SPLIT_ADDR_MAIN                     = MEMPROT_SPLIT_ADDR_IRAM0_DRAM0
+} esp_mprot_split_addr_t;
+
+/**
+ * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
+ */
+typedef enum {
+    MEMPROT_PMS_AREA_NONE                       = 0x00000000,
+    MEMPROT_PMS_AREA_IRAM0_0                    = 0x00000001,
+    MEMPROT_PMS_AREA_IRAM0_1                    = 0x00000002,
+    MEMPROT_PMS_AREA_IRAM0_2                    = 0x00000004,
+    MEMPROT_PMS_AREA_IRAM0_3                    = 0x00000008,
+    MEMPROT_PMS_AREA_DRAM0_0                    = 0x00000010,
+    MEMPROT_PMS_AREA_DRAM0_1                    = 0x00000020,
+    MEMPROT_PMS_AREA_DRAM0_2                    = 0x00000040,
+    MEMPROT_PMS_AREA_DRAM0_3                    = 0x00000080,
+    MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO           = 0x00000100,
+    MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI           = 0x00000200,
+    MEMPROT_PMS_AREA_ALL                        = 0x7FFFFFFF,
+    MEMPROT_PMS_AREA_INVALID                    = 0x80000000
+} esp_mprot_pms_area_t;
+
+/**
+* @brief Memory protection configuration
+*/
+typedef struct {
+    bool invoke_panic_handler;  /*!< Register PMS violation interrupt for panic-handling */
+    bool lock_feature;          /*!< Lock all PMS settings */
+    void *split_addr;           /*!< Main I/D splitting address */
+    uint32_t mem_type_mask;     /*!< Memory types required to protect. See esp_mprot_mem_t enum */
+} esp_memp_config_t;
+
+#define ESP_MEMPROT_DEFAULT_CONFIG() { \
+    .invoke_panic_handler = true, \
+    .lock_feature = true, \
+    .split_addr = NULL, \
+    .mem_type_mask = MEMPROT_TYPE_ALL \
+}
+
+/**
+ * @brief Converts Memory protection type to string
+ *
+ * @param mem_type Memory protection type
+ */
+static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_NONE:
+        return "NONE";
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        return "IRAM0_SRAM";
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        return "DRAM0_SRAM";
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        return "IRAM0_RTCFAST";
+    case MEMPROT_TYPE_IRAM0_ANY:
+        return "IRAM0_ANY";
+    case MEMPROT_TYPE_ALL:
+        return "ALL";
+    default:
+        return "INVALID";
+    }
+}
+
+/**
+ * @brief Converts Splitting address type to string
+ *
+ * @param line_type Split line type
+ */
+static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
+{
+    switch (line_type) {
+    case MEMPROT_SPLIT_ADDR_NONE:
+        return "SPLIT_ADDR_NONE";
+    case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
+        return "SPLIT_ADDR_IRAM0_DRAM0";
+    case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
+        return "SPLIT_ADDR_IRAM0_LINE_0";
+    case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
+        return "SPLIT_ADDR_IRAM0_LINE_1";
+    case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
+        return "SPLIT_ADDR_DRAM0_DMA_LINE_0";
+    case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
+        return "SPLIT_ADDR_DRAM0_DMA_LINE_1";
+    case MEMPROT_SPLIT_ADDR_ALL:
+        return "SPLIT_ADDR_ALL";
+    default:
+        return "SPLIT_ADDR_INVALID";
+    }
+}
+
+/**
+ * @brief Converts PMS Area type to string
+ *
+ * @param area_type PMS Area type
+ */
+static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
+{
+    switch (area_type) {
+    case MEMPROT_PMS_AREA_NONE:
+        return "PMS_AREA_NONE";
+    case MEMPROT_PMS_AREA_IRAM0_0:
+        return "PMS_AREA_IRAM0_0";
+    case MEMPROT_PMS_AREA_IRAM0_1:
+        return "PMS_AREA_IRAM0_1";
+    case MEMPROT_PMS_AREA_IRAM0_2:
+        return "PMS_AREA_IRAM0_2";
+    case MEMPROT_PMS_AREA_IRAM0_3:
+        return "PMS_AREA_IRAM0_3";
+    case MEMPROT_PMS_AREA_DRAM0_0:
+        return "PMS_AREA_DRAM0_0";
+    case MEMPROT_PMS_AREA_DRAM0_1:
+        return "PMS_AREA_DRAM0_1";
+    case MEMPROT_PMS_AREA_DRAM0_2:
+        return "PMS_AREA_DRAM0_2";
+    case MEMPROT_PMS_AREA_DRAM0_3:
+        return "PMS_AREA_DRAM0_3";
+    case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
+        return "PMS_AREA_IRAM0_RTCFAST_LO";
+    case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
+        return "PMS_AREA_IRAM0_RTCFAST_HI";
+    case MEMPROT_PMS_AREA_ALL:
+        return "PMS_AREA_ALL";
+    default:
+        return "PMS_AREA_INVALID";
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 0 - 448
components/esp_hw_support/include/soc/esp32h2/memprot.h

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

+ 117 - 0
components/esp_hw_support/include/soc/esp32h2/soc_memprot_types.h

@@ -0,0 +1,117 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+//////////////////////////////////////////////////////////
+// ESP32-H2 PMS memory protection types
+//
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Memory types recognized by PMS
+ */
+typedef enum {
+    MEMPROT_TYPE_NONE                           = 0x00000000,
+    MEMPROT_TYPE_ALL                            = 0x7FFFFFFF,
+    MEMPROT_TYPE_INVALID                        = 0x80000000
+} esp_mprot_mem_t;
+
+/**
+ * @brief Splitting address (line) type
+ */
+typedef enum {
+    MEMPROT_SPLIT_ADDR_NONE                     = 0x00000000,
+    MEMPROT_SPLIT_ADDR_ALL                      = 0x7FFFFFFF,
+    MEMPROT_SPLIT_ADDR_INVALID                  = 0x80000000
+} esp_mprot_split_addr_t;
+
+/**
+ * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
+ */
+typedef enum {
+    MEMPROT_PMS_AREA_NONE                       = 0x00000000,
+    MEMPROT_PMS_AREA_ALL                        = 0x7FFFFFFF,
+    MEMPROT_PMS_AREA_INVALID                    = 0x80000000
+} esp_mprot_pms_area_t;
+
+/**
+* @brief Memory protection configuration
+*/
+typedef struct {
+    bool invoke_panic_handler;  /*!< Register PMS violation interrupt for panic-handling */
+    bool lock_feature;          /*!< Lock all PMS settings */
+    void *split_addr;           /*!< Main I/D splitting address */
+    uint32_t mem_type_mask;     /*!< Memory types required to protect. See esp_mprot_mem_t enum */
+} esp_memp_config_t;
+
+#define ESP_MEMPROT_DEFAULT_CONFIG() {\
+    .invoke_panic_handler = true, \
+    .lock_feature = true, \
+    .split_addr = NULL, \
+    .mem_type_mask = MEMPROT_TYPE_ALL \
+}
+
+/**
+ * @brief Converts Memory protection type to string
+ *
+ * @param mem_type Memory protection type
+ */
+static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_NONE:
+        return "MEMPROT_TYPE_NONE";
+    case MEMPROT_TYPE_ALL:
+        return "MEMPROT_TYPE_ALL";
+    default:
+        return "MEMPROT_TYPE_INVALID";
+    }
+}
+
+/**
+ * @brief Converts Splitting address type to string
+ *
+ * @param line_type Split line type
+ */
+static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
+{
+    switch (line_type) {
+    case MEMPROT_SPLIT_ADDR_NONE:
+        return "MEMPROT_SPLIT_ADDR_NONE";
+    case MEMPROT_SPLIT_ADDR_ALL:
+        return "MEMPROT_SPLIT_ADDR_ALL";
+    default:
+        return "MEMPROT_SPLIT_ADDR_INVALID";
+    }
+}
+
+/**
+ * @brief Converts PMS Area type to string
+ *
+ * @param area_type PMS Area type
+ */
+static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
+{
+    switch (area_type) {
+    case MEMPROT_PMS_AREA_NONE:
+        return "MEMPROT_PMS_AREA_NONE";
+    case MEMPROT_PMS_AREA_ALL:
+        return "MEMPROT_PMS_AREA_ALL";
+    default:
+        return "MEMPROT_PMS_AREA_INVALID";
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 117 - 0
components/esp_hw_support/include/soc/esp32s2/soc_memprot_types.h

@@ -0,0 +1,117 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+//////////////////////////////////////////////////////////
+// ESP32-S2 PMS memory protection types
+//
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Memory types recognized by PMS
+ */
+typedef enum {
+    MEMPROT_TYPE_NONE                           = 0x00000000,
+    MEMPROT_TYPE_ALL                            = 0x7FFFFFFF,
+    MEMPROT_TYPE_INVALID                        = 0x80000000
+} esp_mprot_mem_t;
+
+/**
+ * @brief Splitting address (line) type
+ */
+typedef enum {
+    MEMPROT_SPLIT_ADDR_NONE                     = 0x00000000,
+    MEMPROT_SPLIT_ADDR_ALL                      = 0x7FFFFFFF,
+    MEMPROT_SPLIT_ADDR_INVALID                  = 0x80000000
+} esp_mprot_split_addr_t;
+
+/**
+ * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
+ */
+typedef enum {
+    MEMPROT_PMS_AREA_NONE                       = 0x00000000,
+    MEMPROT_PMS_AREA_ALL                        = 0x7FFFFFFF,
+    MEMPROT_PMS_AREA_INVALID                    = 0x80000000
+} esp_mprot_pms_area_t;
+
+/**
+* @brief Memory protection configuration
+*/
+typedef struct {
+    bool invoke_panic_handler;  /*!< Register PMS violation interrupt for panic-handling */
+    bool lock_feature;          /*!< Lock all PMS settings */
+    void *split_addr;           /*!< Main I/D splitting address */
+    uint32_t mem_type_mask;     /*!< Memory types required to protect. See esp_mprot_mem_t enum */
+} esp_memp_config_t;
+
+#define ESP_MEMPROT_DEFAULT_CONFIG() { \
+    .invoke_panic_handler = true, \
+    .lock_feature = true, \
+    .split_addr = NULL, \
+    .mem_type_mask = MEMPROT_TYPE_ALL \
+}
+
+/**
+ * @brief Converts Memory protection type to string
+ *
+ * @param mem_type Memory protection type
+ */
+static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_NONE:
+        return "MEMPROT_TYPE_NONE";
+    case MEMPROT_TYPE_ALL:
+        return "MEMPROT_TYPE_ALL";
+    default:
+        return "MEMPROT_TYPE_INVALID";
+    }
+}
+
+/**
+ * @brief Converts Splitting address type to string
+ *
+ * @param line_type Split line type
+ */
+static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
+{
+    switch (line_type) {
+    case MEMPROT_SPLIT_ADDR_NONE:
+        return "MEMPROT_SPLIT_ADDR_NONE";
+    case MEMPROT_SPLIT_ADDR_ALL:
+        return "MEMPROT_SPLIT_ADDR_ALL";
+    default:
+        return "MEMPROT_SPLIT_ADDR_INVALID";
+    }
+}
+
+/**
+ * @brief Converts PMS Area type to string
+ *
+ * @param area_type PMS Area type
+ */
+static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
+{
+    switch (area_type) {
+    case MEMPROT_PMS_AREA_NONE:
+        return "MEMPROT_PMS_AREA_NONE";
+    case MEMPROT_PMS_AREA_ALL:
+        return "MEMPROT_PMS_AREA_ALL";
+    default:
+        return "MEMPROT_PMS_AREA_INVALID";
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 0 - 484
components/esp_hw_support/include/soc/esp32s3/memprot.h

@@ -1,484 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-
-/* INTERNAL API
- * generic interface to MMU memory protection features
- */
-
-#pragma once
-#include <stdbool.h>
-#include <stdint.h>
-#include "esp_attr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef enum {
-    MEMPROT_NONE =              0x00000000,
-    MEMPROT_IRAM0_SRAM =        0x00000001,
-    MEMPROT_DRAM0_SRAM =        0x00000002,
-    MEMPROT_IRAM0_RTCFAST =     0x00000004,
-    MEMPROT_DRAM0_RTCFAST =     0x00000008,
-    MEMPROT_PERI1_RTCSLOW =     0x00000010,
-    MEMPROT_PERI2_RTCSLOW_0 =   0x00000020,
-    MEMPROT_PERI2_RTCSLOW_1 =   0x00000040,
-    MEMPROT_ALL =               0xFFFFFFFF
-} mem_type_prot_t;
-
-
-/**
- * @brief Returns splitting address for required memory region
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- *
- * @return Splitting address for the memory region required.
- * The address is given by region-specific global symbol exported from linker script,
- * it is not read out from related configuration register.
- */
-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.
- *
- * 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)
- */
-void 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
- */
-void 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)
- *
- * @note When called without actual interrupt-on flag set, subsequent occurrence of related interrupt is ignored.
- * 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)
- */
-void esp_memprot_clear_intr(mem_type_prot_t mem_type);
-
-/**
- * @brief Detects which memory protection interrupt is active
- *
- * @note Check order
- *          MEMPROT_IRAM0_SRAM
- *          MEMPROT_IRAM0_RTCFAST
- *          MEMPROT_DRAM0_SRAM
- *          MEMPROT_DRAM0_RTCFAST
- *
- * @return Memory protection area type (see mem_type_prot_t enum)
- */
-mem_type_prot_t IRAM_ATTR esp_memprot_get_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)
- *
- * @return Contents of status register
- */
-uint32_t esp_memprot_get_fault_reg(mem_type_prot_t mem_type);
-
-/**
- * @brief Get details of given interrupt status
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param faulting_address Faulting address causing the interrupt [out]
- * @param op_type Operation being processed at the faulting address [out]
- *               IRAM0: 0 - read, 1 - write
- *               DRAM0: 0 - read, 1 - write
- * @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
- */
-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);
-
-/**
- * @brief Gets string representation of required memory region identifier
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- *
- * @return mem_type as string
- */
-const char *IRAM_ATTR esp_memprot_type_to_str(mem_type_prot_t mem_type);
-
-/**
- * @brief Detects whether any of the interrupt locks is active (requires digital system reset to unlock)
- *
- * @return true/false
- */
-bool esp_memprot_is_locked_any(void);
-
-/**
- * @brief Sets lock for specified memory region.
- *
- * Locks can be unlocked only by digital system reset
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- */
-void 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)
- *
- * @return true/false (locked/unlocked)
- */
-bool esp_memprot_get_lock(mem_type_prot_t mem_type);
-
-/**
- * @brief Gets permission control configuration register contents for required memory region
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- *
- * @return Permission control register contents
- */
-uint32_t esp_memprot_get_conf_reg(mem_type_prot_t mem_type);
-
-/**
- * @brief Gets interrupt permission settings for unified management block
- *
- * 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)
- *
- * @return Permission settings register contents
- */
-uint32_t esp_memprot_get_perm_uni_reg(mem_type_prot_t mem_type);
-
-/**
- * @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
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- *
- * @return Permission settings register contents
- */
-uint32_t esp_memprot_get_perm_split_reg(mem_type_prot_t mem_type);
-
-/**
- * @brief Detects whether any of the memory protection interrupts is enabled
- *
- * @return true/false
- */
-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)
- *
- * @return Interrupt-enabled value
- */
-uint32_t esp_memprot_get_intr_ena_bit(mem_type_prot_t mem_type);
-
-/**
- * @brief Gets interrupt-active flag for given memory region
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- *
- * @return Interrupt-active value
- */
-uint32_t esp_memprot_get_intr_on_bit(mem_type_prot_t mem_type);
-
-/**
- * @brief Gets interrupt-clear request flag for given memory region
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- *
- * @return Interrupt-clear request value
- */
-uint32_t esp_memprot_get_intr_clr_bit(mem_type_prot_t mem_type);
-
-/**
- * @brief Gets read permission value for specified block and memory region
- *
- * Returns read permission bit value for required unified-management block (0-3) in given memory region.
- * Applicable to all memory types.
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param block Memory block identifier (0-3)
- *
- * @return Read permission value for required block
- */
-uint32_t esp_memprot_get_uni_block_read_bit(mem_type_prot_t mem_type, uint32_t block);
-
-/**
- * @brief Gets write permission value for specified block and memory region
- *
- * Returns write permission bit value for required unified-management block (0-3) in given memory region.
- * Applicable to all memory types.
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param block Memory block identifier (0-3)
- *
- * @return Write permission value for required block
- */
-uint32_t esp_memprot_get_uni_block_write_bit(mem_type_prot_t mem_type, uint32_t block);
-
-/**
- * @brief Gets execute permission value for specified block and memory region
- *
- * Returns execute permission bit value for required 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 block Memory block identifier (0-3)
- *
- * @return Execute permission value for required block
- */
-uint32_t esp_memprot_get_uni_block_exec_bit(mem_type_prot_t mem_type, uint32_t block);
-
-/**
- * @brief Sets permissions for specified block in DRAM region
- *
- * Sets Read and Write permission for specified unified-management block (0-3) in given memory region.
- * Applicable only to DRAM memory types
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param block Memory block identifier (0-3)
- * @param write_perm Write permission flag
- * @param read_perm Read permission flag
- */
-void 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
- *
- * Sets Read and Write permission for both low and high memory segments given by splitting address.
- * The splitting address must be equal to or higher then beginning of block 5
- * Applicable only to DRAM memory types
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param split_addr Address to split the memory region to lower and higher segment
- * @param lw Low segment Write permission flag
- * @param lr Low segment Read permission flag
- * @param hw High segment Write permission flag
- * @param hr High segment Read permission flag
- */
-void esp_memprot_set_prot_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
- *
- * 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 block Memory block identifier (0-3)
- * @param write_perm Write permission flag
- * @param exec_perm Execute permission flag
- */
-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);
-
-/**
- * @brief Sets permissions for high and low memory segment in IRAM region
- *
- * Sets Read, Write and Execute permission for both low and high memory segments given by splitting address.
- * The splitting address must be equal to or higher then beginning of block 5
- * Applicable only to IRAM memory types
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param split_addr Address to split the memory region to lower and higher segment
- * @param lw Low segment Write permission flag
- * @param lr Low segment Read permission flag
- * @param lx Low segment Execute permission flag
- * @param hw High segment Write permission flag
- * @param hr High segment Read permission flag
- * @param hx High segment Execute permission flag
- */
-void esp_memprot_set_prot_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
- *
- * @note The feature is disabled when JTAG interface is connected
- *
- * @param invoke_panic_handler map mem.prot interrupt to ETS_MEMACCESS_ERR_INUM and thus invokes panic handler when fired ('true' not suitable for testing)
- * @param lock_feature sets LOCK bit, see esp_memprot_set_lock() ('true' not suitable for testing)
- * @param mem_type_mask holds a set of required memory protection types (bitmask built of mem_type_prot_t). NULL means default (MEMPROT_ALL in this version)
- */
-void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
-
-/**
- * @brief Get permission settings bits for IRAM0 split mgmt. Only IRAM0 memory types allowed
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lw Low segment Write permission flag
- * @param lr Low segment Read permission flag
- * @param lx Low segment Execute permission flag
- * @param hw High segment Write permission flag
- * @param hr High segment Read permission flag
- * @param hx High segment Execute permission flag
- */
-void esp_memprot_get_perm_split_bits_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
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lw Low segment Write permission flag
- * @param lr Low segment Read permission flag
- * @param hw High segment Write permission flag
- * @param hr High segment Read permission flag
- */
-void esp_memprot_get_perm_split_bits_dram(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr);
-
-/**
- * @brief Sets permissions for high and low memory segment in PERIBUS1 region
- *
- * Sets Read and Write permission for both low and high memory segments given by splitting address.
- * Applicable only to PERIBUS1 memory types
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param split_addr Address to split the memory region to lower and higher segment
- * @param lw Low segment Write permission flag
- * @param lr Low segment Read permission flag
- * @param hw High segment Write permission flag
- * @param hr High segment Read permission flag
- */
-void esp_memprot_set_prot_peri1(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool hw, bool hr);
-
-/**
- * @brief Get permission settings bits for PERIBUS1 split mgmt. Only PERIBUS1 memory types allowed
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lw Low segment Write permission flag
- * @param lr Low segment Read permission flag
- * @param hw High segment Write permission flag
- * @param hr High segment Read permission flag
- */
-void esp_memprot_get_perm_split_bits_peri1(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *hw, bool *hr);
-
-/**
- * @brief Get permission settings bits for PERIBUS2 split mgmt. Only PERIBUS2 memory types allowed
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lw Low segment Write permission flag
- * @param lr Low segment Read permission flag
- * @param lx Low segment Execute permission flag
- * @param hw High segment Write permission flag
- * @param hr High segment Read permission flag
- * @param hx High segment Execute permission flag
- */
-void esp_memprot_get_perm_split_bits_peri2(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx);
-
-/**
- * @brief Sets permissions for high and low memory segment in PERIBUS2 region
- *
- * Sets Read Write permission for both low and high memory segments given by splitting address.
- * Applicable only to PERIBUS2 memory types
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param split_addr Address to split the memory region to lower and higher segment
- * @param lw Low segment Write permission flag
- * @param lr Low segment Read permission flag
- * @param lx Low segment Execute permission flag
- * @param hw High segment Write permission flag
- * @param hr High segment Read permission flag
- * @param hx High segment Execute permission flag
- */
-void esp_memprot_set_prot_peri2(mem_type_prot_t mem_type, uint32_t *split_addr, bool lw, bool lr, bool lx, bool hw, bool hr, bool hx);
-
-/**
- * @brief Get permissions for specified memory type. Irrelevant bits are ignored
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lw Low segment Write permission flag
- * @param lr Low segment Read permission flag
- * @param lx Low segment Execute permission flag
- * @param hw High segment Write permission flag
- * @param hr High segment Read permission flag
- * @param hx High segment Execute permission flag
- */
-void esp_memprot_get_permissions(mem_type_prot_t mem_type, bool *lw, bool *lr, bool *lx, bool *hw, bool *hr, bool *hx);
-
-/**
- * @brief Get Read permission settings for low and high regions of given memory type
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lr Low segment Read permission flag
- * @param hr High segment Read permission flag
- */
-void esp_memprot_get_perm_read(mem_type_prot_t mem_type, bool *lr, bool *hr);
-
-/**
- * @brief Get Write permission settings for low and high regions of given memory type
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lr Low segment Write permission flag
- * @param hr High segment Write permission flag
- */
-void esp_memprot_get_perm_write(mem_type_prot_t mem_type, bool *lw, bool *hw);
-
-/**
- * @brief Get Execute permission settings for low and high regions of given memory type
- * Applicable only to IBUS-compatible memory types
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lr Low segment Exec permission flag
- * @param hr High segment Exec permission flag
- */
-void esp_memprot_get_perm_exec(mem_type_prot_t mem_type, bool *lx, bool *hx);
-
-/**
- * @brief Returns the lowest address in required memory region
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- */
-uint32_t esp_memprot_get_low_limit(mem_type_prot_t mem_type);
-
-/**
- * @brief Returns the highest address in required memory region
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- */
-uint32_t esp_memprot_get_high_limit(mem_type_prot_t mem_type);
-
-/**
- * @brief Sets READ permission bit for required memory region
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lr Low segment Read permission flag
- * @param hr High segment Read permission flag
- */
-void esp_memprot_set_read_perm(mem_type_prot_t mem_type, bool lr, bool hr);
-
-/**
- * @brief Sets WRITE permission bit for required memory region
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lr Low segment Write permission flag
- * @param hr High segment Write permission flag
- */
-void esp_memprot_set_write_perm(mem_type_prot_t mem_type, bool lw, bool hw);
-
-/**
- * @brief Sets EXECUTE permission bit for required memory region
- *
- * @param mem_type Memory protection area type (see mem_type_prot_t enum)
- * @param lr Low segment Exec permission flag
- * @param hr High segment Exec permission flag
- */
-void esp_memprot_set_exec_perm(mem_type_prot_t mem_type, bool lx, bool hx);
-
-
-#ifdef __cplusplus
-}
-#endif

+ 119 - 0
components/esp_hw_support/include/soc/esp32s3/soc_memprot_types.h

@@ -0,0 +1,119 @@
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+//////////////////////////////////////////////////////////
+// ESP32-S3 PMS memory protection types
+//
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Memory types recognized by PMS
+ */
+typedef enum {
+    MEMPROT_TYPE_NONE                           = 0x00000000,
+    MEMPROT_TYPE_ALL                            = 0x7FFFFFFF,
+    MEMPROT_TYPE_INVALID                        = 0x80000000
+} esp_mprot_mem_t;
+
+/**
+ * @brief Splitting address (line) type
+ */
+typedef enum {
+    MEMPROT_SPLIT_ADDR_NONE                     = 0x00000000,
+    MEMPROT_SPLIT_ADDR_ALL                      = 0x7FFFFFFF,
+    MEMPROT_SPLIT_ADDR_INVALID                  = 0x80000000
+} esp_mprot_split_addr_t;
+
+/**
+ * @brief PMS area type (memory space between adjacent splitting addresses or above/below the main splt.address)
+ */
+typedef enum {
+    MEMPROT_PMS_AREA_NONE                       = 0x00000000,
+    MEMPROT_PMS_AREA_ALL                        = 0x7FFFFFFF,
+    MEMPROT_PMS_AREA_INVALID                    = 0x80000000
+} esp_mprot_pms_area_t;
+
+/**
+* @brief Memory protection configuration
+*/
+typedef struct {
+    bool invoke_panic_handler;  /*!< Register PMS violation interrupt for panic-handling */
+    bool lock_feature;          /*!< Lock all PMS settings */
+    void *split_addr;           /*!< Main I/D splitting address */
+    uint32_t mem_type_mask;     /*!< Memory types required to protect. See esp_mprot_mem_t enum */
+    int target_cpu[];           /*!< Array of CPU/core IDs required to receive given PMS protection */
+} esp_memp_config_t;
+
+#define ESP_MEMPROT_DEFAULT_CONFIG() { \
+    .invoke_panic_handler = true, \
+    .lock_feature = true, \
+    .split_addr = NULL, \
+    .mem_type_mask = MEMPROT_TYPE_ALL,\
+    .target_cpu[] = {PRO_CPU_NUM, APP_CPU_NUM} \
+}
+
+/**
+ * @brief Converts Memory protection type to string
+ *
+ * @param mem_type Memory protection type
+ */
+static inline const char *esp_mprot_mem_type_to_str(const esp_mprot_mem_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_NONE:
+        return "MEMPROT_TYPE_NONE";
+    case MEMPROT_TYPE_ALL:
+        return "MEMPROT_TYPE_ALL";
+    default:
+        return "MEMPROT_TYPE_INVALID";
+    }
+}
+
+/**
+ * @brief Converts Splitting address type to string
+ *
+ * @param line_type Split line type
+ */
+static inline const char *esp_mprot_split_addr_to_str(const esp_mprot_split_addr_t line_type)
+{
+    switch (line_type) {
+    case MEMPROT_SPLIT_ADDR_NONE:
+        return "MEMPROT_SPLIT_ADDR_NONE";
+    case MEMPROT_SPLIT_ADDR_ALL:
+        return "MEMPROT_SPLIT_ADDR_ALL";
+    default:
+        return "MEMPROT_SPLIT_ADDR_INVALID";
+    }
+}
+
+/**
+ * @brief Converts PMS Area type to string
+ *
+ * @param area_type PMS Area type
+ */
+static inline const char *esp_mprot_pms_area_to_str(const esp_mprot_pms_area_t area_type)
+{
+    switch (area_type) {
+    case MEMPROT_PMS_AREA_NONE:
+        return "MEMPROT_PMS_AREA_NONE";
+    case MEMPROT_PMS_AREA_ALL:
+        return "MEMPROT_PMS_AREA_ALL";
+    default:
+        return "MEMPROT_PMS_AREA_INVALID";
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 5 - 1
components/esp_hw_support/port/esp32c3/CMakeLists.txt

@@ -10,11 +10,15 @@ set(srcs "cpu_util_esp32c3.c"
 
 if(NOT BOOTLOADER_BUILD)
     list(APPEND srcs "../async_memcpy_impl_gdma.c"
-                     "memprot.c"
                      "esp_hmac.c"
                      "esp_crypto_lock.c"
                      "esp_ds.c"
                      "dport_access.c")
+
+    if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
+        list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c")
+    endif()
+
 endif()
 
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

+ 869 - 0
components/esp_hw_support/port/esp32c3/esp_memprot.c

@@ -0,0 +1,869 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <string.h>
+#include "sdkconfig.h"
+#include "soc/periph_defs.h"
+#include "esp_intr_alloc.h"
+#include "hal/memprot_ll.h"
+#include "riscv/interrupt.h"
+#include "esp32c3/rom/ets_sys.h"
+#include "esp_cpu.h"
+#include "esp_fault.h"
+#include "esp_attr.h"
+#include "hal/memprot_types.h"
+#include "esp_private/esp_memprot_internal.h"
+#include "esp_memprot.h"
+
+extern int _iram_text_end;
+extern int _rtc_text_end;
+
+static void *esp_memprot_iram0_get_def_split_addr(void)
+{
+    return &_iram_text_end;
+}
+
+static void *esp_memprot_dram0_get_def_split_addr(void)
+{
+    return MAP_IRAM_TO_DRAM(&_iram_text_end);
+}
+
+static void *esp_memprot_rtcfast_get_min_split_addr(void)
+{
+    return &_rtc_text_end;
+}
+
+esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        switch (line_type) {
+        case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
+            return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_main_I_D(line_addr));
+        case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
+            return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_I_0(line_addr));
+        case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
+            return esp_mprot_ll_err_to_esp_err(memprot_ll_set_iram0_split_line_I_1(line_addr));
+        default:
+            return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
+        } break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        switch (line_type) {
+        case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
+            return esp_mprot_ll_err_to_esp_err(memprot_ll_set_dram0_split_line_D_0(line_addr));
+        case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
+            return esp_mprot_ll_err_to_esp_err(memprot_ll_set_dram0_split_line_D_1(line_addr));
+        default:
+            return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
+        } break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        if (line_type == MEMPROT_SPLIT_ADDR_MAIN) {
+            /* so far only WORLD_0 is supported */
+            return esp_mprot_ll_err_to_esp_err(memprot_ll_set_rtcfast_split_line(line_addr, MEMP_LL_WORLD_0));
+        } else {
+            return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
+        }
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+}
+
+esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr)
+{
+    if (line_addr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        switch (line_type) {
+        case MEMPROT_SPLIT_ADDR_IRAM0_DRAM0:
+            *line_addr = memprot_ll_get_iram0_split_line_main_I_D();
+            break;
+        case MEMPROT_SPLIT_ADDR_IRAM0_LINE_0:
+            *line_addr = memprot_ll_get_iram0_split_line_I_0();
+            break;
+        case MEMPROT_SPLIT_ADDR_IRAM0_LINE_1:
+            *line_addr = memprot_ll_get_iram0_split_line_I_1();
+            break;
+        default:
+            return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
+        } break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        switch (line_type) {
+        case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0:
+            *line_addr = memprot_ll_get_dram0_split_line_D_0();
+            break;
+        case MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1:
+            *line_addr = memprot_ll_get_dram0_split_line_D_1();
+            break;
+        default:
+            return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
+        } break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        if (line_type == MEMPROT_SPLIT_ADDR_MAIN) {
+            /* so far only WORLD_0 is supported */
+            return esp_mprot_ll_err_to_esp_err(memprot_ll_get_rtcfast_split_line(MEMP_LL_WORLD_0, line_addr));
+        } else {
+            return ESP_ERR_MEMPROT_SPLIT_ADDR_INVALID;
+        }
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr)
+{
+    if (def_split_addr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        *def_split_addr = esp_memprot_iram0_get_def_split_addr();
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        *def_split_addr = esp_memprot_dram0_get_def_split_addr();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        *def_split_addr = esp_memprot_rtcfast_get_min_split_addr();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        memprot_ll_set_iram0_dram0_split_line_lock();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        //caution: RTCFAST shares the lock with other PIF PMS constraints!
+        memprot_ll_set_pif_constraint_lock();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        *locked = memprot_ll_get_iram0_dram0_split_line_lock();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        *locked = memprot_ll_get_pif_constraint_lock();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        memprot_ll_iram0_set_pms_lock();
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        memprot_ll_dram0_set_pms_lock();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        //caution: RTCFAST shares the lock with other PIF PMS constraints!
+        memprot_ll_set_pif_constraint_lock();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        *locked = memprot_ll_iram0_get_pms_lock();
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        *locked = memprot_ll_dram0_get_pms_lock();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        *locked = memprot_ll_get_pif_constraint_lock();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags)
+{
+    bool r = flags & MEMPROT_OP_READ;
+    bool w = flags & MEMPROT_OP_WRITE;
+    bool x = flags & MEMPROT_OP_EXEC;
+
+    switch (area_type) {
+    case MEMPROT_PMS_AREA_IRAM0_0:
+        memprot_ll_iram0_set_pms_area_0(r, w, x);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_1:
+        memprot_ll_iram0_set_pms_area_1(r, w, x);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_2:
+        memprot_ll_iram0_set_pms_area_2(r, w, x);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_3:
+        memprot_ll_iram0_set_pms_area_3(r, w, x);
+        break;
+    case MEMPROT_PMS_AREA_DRAM0_0:
+        memprot_ll_dram0_set_pms_area_0(r, w);
+        break;
+    case MEMPROT_PMS_AREA_DRAM0_1:
+        memprot_ll_dram0_set_pms_area_1(r, w);
+        break;
+    case MEMPROT_PMS_AREA_DRAM0_2:
+        memprot_ll_dram0_set_pms_area_2(r, w);
+        break;
+    case MEMPROT_PMS_AREA_DRAM0_3:
+        memprot_ll_dram0_set_pms_area_3(r, w);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
+        memprot_ll_rtcfast_set_pms_area(r, w, x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
+        memprot_ll_rtcfast_set_pms_area(r, w, x, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH);
+        break;
+    default:
+        return ESP_ERR_NOT_SUPPORTED;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags)
+{
+    if (flags == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    bool r = false;
+    bool w = false;
+    bool x = false;
+
+    switch (area_type) {
+    case MEMPROT_PMS_AREA_IRAM0_0:
+        memprot_ll_iram0_get_pms_area_0(&r, &w, &x);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_1:
+        memprot_ll_iram0_get_pms_area_1(&r, &w, &x);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_2:
+        memprot_ll_iram0_get_pms_area_2(&r, &w, &x);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_3:
+        memprot_ll_iram0_get_pms_area_3(&r, &w, &x);
+        break;
+    case MEMPROT_PMS_AREA_DRAM0_0:
+        memprot_ll_dram0_get_pms_area_0(&r, &w);
+        break;
+    case MEMPROT_PMS_AREA_DRAM0_1:
+        memprot_ll_dram0_get_pms_area_1(&r, &w);
+        break;
+    case MEMPROT_PMS_AREA_DRAM0_2:
+        memprot_ll_dram0_get_pms_area_2(&r, &w);
+        break;
+    case MEMPROT_PMS_AREA_DRAM0_3:
+        memprot_ll_dram0_get_pms_area_3(&r, &w);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO:
+        memprot_ll_rtcfast_get_pms_area(&r, &w, &x, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW);
+        break;
+    case MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI:
+        memprot_ll_rtcfast_get_pms_area(&r, &w, &x, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH);
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    *flags = 0;
+    if (r) {
+        *flags |= MEMPROT_OP_READ;
+    }
+    if (w) {
+        *flags |= MEMPROT_OP_WRITE;
+    }
+    if (x) {
+        *flags |= MEMPROT_OP_EXEC;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        memprot_ll_iram0_set_monitor_lock();
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        memprot_ll_dram0_set_monitor_lock();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        memprot_ll_rtcfast_set_monitor_lock();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        *locked = memprot_ll_iram0_get_monitor_lock();
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        *locked = memprot_ll_dram0_get_monitor_lock();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        *locked = memprot_ll_rtcfast_get_monitor_lock();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable)
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        memprot_ll_iram0_set_monitor_en(enable);
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        memprot_ll_dram0_set_monitor_en(enable);
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        memprot_ll_rtcfast_set_monitor_en(enable);
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled)
+{
+    if (enabled == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        *enabled = memprot_ll_iram0_get_monitor_en();
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        *enabled = memprot_ll_dram0_get_monitor_en();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        *enabled = memprot_ll_rtcfast_get_monitor_en();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused)))
+{
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        memprot_ll_iram0_set_monitor_intrclr();
+        memprot_ll_iram0_reset_monitor_intrclr();
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        memprot_ll_dram0_set_monitor_intrclr();
+        memprot_ll_dram0_reset_monitor_intrclr();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        memprot_ll_rtcfast_set_monitor_intrclr();
+        memprot_ll_rtcfast_reset_monitor_intrclr();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr)
+{
+    if (active_memp_intr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    active_memp_intr->core = PRO_CPU_NUM;
+
+    if (memprot_ll_iram0_get_monitor_status_intr() > 0) {
+        active_memp_intr->mem_type = MEMPROT_TYPE_IRAM0_SRAM;
+    } else if (memprot_ll_dram0_get_monitor_status_intr() > 0) {
+        active_memp_intr->mem_type = MEMPROT_TYPE_DRAM0_SRAM;
+    } else if (memprot_ll_rtcfast_get_monitor_status_intr() > 0) {
+        active_memp_intr->mem_type = MEMPROT_TYPE_IRAM0_RTCFAST;
+    } else {
+        active_memp_intr->mem_type = MEMPROT_TYPE_NONE;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    bool lock_on = false;
+    esp_err_t res;
+
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on))
+    *locked |= lock_on;
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on))
+    *locked |= lock_on;
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on))
+    *locked |= lock_on;
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_pms_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on))
+    *locked |= lock_on;
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM, &lock_on))
+    *locked |= lock_on;
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM, &lock_on));
+    *locked |= lock_on;
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST, &lock_on));
+    *locked |= lock_on;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled)
+{
+    if (enabled == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    bool ena_on = false;
+    esp_err_t res;
+
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, &ena_on))
+    *enabled |= ena_on;
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, &ena_on))
+    *enabled |= ena_on;
+    ESP_MEMPROT_ERR_CHECK(res, esp_mprot_get_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, &ena_on))
+    *enabled |= ena_on;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused)))
+{
+    if (fault_addr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        *fault_addr = (void *)memprot_ll_iram0_get_monitor_status_fault_addr();
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        *fault_addr = (void *)memprot_ll_dram0_get_monitor_status_fault_addr();
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        *fault_addr = (void *)memprot_ll_rtcfast_get_monitor_status_fault_addr();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused)))
+{
+    if (world == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    esp_mprot_pms_world_t res;
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        res = esp_mprot_ll_world_to_hl_world(memprot_ll_iram0_get_monitor_status_fault_world());
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        res = esp_mprot_ll_world_to_hl_world(memprot_ll_dram0_get_monitor_status_fault_world());
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        res = esp_mprot_ll_world_to_hl_world(memprot_ll_rtcfast_get_monitor_status_fault_world());
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    if (res == MEMPROT_PMS_WORLD_INVALID) {
+        return ESP_ERR_MEMPROT_WORLD_INVALID;
+    }
+
+    *world = res;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused)))
+{
+    if (oper == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    uint32_t operation = MEMPROT_OP_NONE;
+
+    if ((mem_type == MEMPROT_TYPE_IRAM0_SRAM && memprot_ll_iram0_get_monitor_status_fault_loadstore() == 0) ||
+            (mem_type == MEMPROT_TYPE_IRAM0_RTCFAST && memprot_ll_rtcfast_get_monitor_status_fault_loadstore() == 0)) {
+        operation = MEMPROT_OP_EXEC;
+    }
+
+    if (operation == MEMPROT_OP_NONE) {
+        switch (mem_type) {
+        case MEMPROT_TYPE_IRAM0_SRAM:
+            operation = memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ;
+            break;
+        case MEMPROT_TYPE_DRAM0_SRAM:
+            operation = memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ;
+            break;
+        case MEMPROT_TYPE_IRAM0_RTCFAST:
+            operation = memprot_ll_rtcfast_get_monitor_status_fault_wr() == 1 ? MEMPROT_OP_WRITE : MEMPROT_OP_READ;
+            break;
+        default:
+            return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+        }
+    }
+
+    *oper = operation;
+
+    return ESP_OK;
+}
+
+bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type)
+{
+    return mem_type == MEMPROT_TYPE_DRAM0_SRAM;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused)))
+{
+    if (byte_en == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        *byte_en = memprot_ll_dram0_get_monitor_status_fault_byte_en();
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    return ESP_OK;
+}
+
+/* internal */
+static esp_err_t esp_mprot_set_intr_matrix(const esp_mprot_mem_t mem_type)
+{
+    ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        intr_matrix_set(PRO_CPU_NUM, memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        intr_matrix_set(PRO_CPU_NUM, memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
+        break;
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        intr_matrix_set(PRO_CPU_NUM, memprot_ll_rtcfast_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
+        break;
+    default:
+        return ESP_ERR_MEMPROT_MEMORY_TYPE_INVALID;
+    }
+
+    /* Set the type and priority to cache error interrupts. */
+    esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL);
+    esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
+
+    ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config)
+{
+    if (memp_config == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    if (memp_config->mem_type_mask == MEMPROT_TYPE_NONE) {
+        return ESP_ERR_NO_MEM;
+    }
+
+    //debugger connected:
+    // 1.check the signal repeatedly to avoid possible glitching attempt
+    // 2.leave the Memprot unset to allow debug operations
+    if (esp_cpu_in_ocd_debug_mode()) {
+        ESP_FAULT_ASSERT(esp_cpu_in_ocd_debug_mode());
+        return ESP_OK;
+    }
+
+    bool use_iram0 = memp_config->mem_type_mask & MEMPROT_TYPE_IRAM0_SRAM;
+    bool use_dram0 = memp_config->mem_type_mask & MEMPROT_TYPE_DRAM0_SRAM;
+    bool use_rtcfast = memp_config->mem_type_mask & MEMPROT_TYPE_IRAM0_RTCFAST;
+    esp_err_t ret = ESP_OK;
+
+    //disable protection (must be unlocked)
+    if (use_iram0) {
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, false))
+    }
+    if (use_dram0) {
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, false))
+    }
+    if (use_rtcfast) {
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, false))
+    }
+
+    //panic handling
+    if (memp_config->invoke_panic_handler) {
+        if (use_iram0) {
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_SRAM))
+        }
+        if (use_dram0) {
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_DRAM0_SRAM))
+        }
+        if (use_rtcfast) {
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_intr_matrix(MEMPROT_TYPE_IRAM0_RTCFAST))
+        }
+    }
+
+    //set split lines (must-have for all mem_types). This version sets only the main I/D which is then shared for all PMS regions
+    void *line_addr = memp_config->split_addr;
+    if (line_addr == NULL) {
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_SRAM, &line_addr))
+    }
+
+    ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_1, line_addr))
+    ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_LINE_0, line_addr))
+    ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_SRAM, MEMPROT_SPLIT_ADDR_IRAM0_DRAM0, line_addr))
+    ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_0, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr))))
+    ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_DRAM0_SRAM, MEMPROT_SPLIT_ADDR_DRAM0_DMA_LINE_1, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr))))
+
+    //set permissions
+    if (use_iram0) {
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, MEMPROT_OP_NONE))
+    }
+    if (use_dram0) {
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, MEMPROT_OP_NONE ))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
+    }
+    if (use_rtcfast) {
+        //RTCFAST split-line cannot be set manually - always use default
+        void *rtc_fast_line;
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_get_default_main_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, &rtc_fast_line));
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr(MEMPROT_TYPE_IRAM0_RTCFAST, MEMPROT_SPLIT_ADDR_MAIN, rtc_fast_line))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, MEMPROT_OP_READ | MEMPROT_OP_EXEC))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, MEMPROT_OP_READ | MEMPROT_OP_WRITE))
+    }
+
+    //reenable the protection
+    if (use_iram0) {
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, NULL))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_SRAM, true))
+    }
+    if (use_dram0) {
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, NULL))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_DRAM0_SRAM, true))
+    }
+    if (use_rtcfast) {
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, NULL))
+        ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_en(MEMPROT_TYPE_IRAM0_RTCFAST, true))
+    }
+
+    //lock if required
+    if (memp_config->lock_feature) {
+        if (use_iram0) {
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_SRAM))
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_SRAM))
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_SRAM))
+        }
+        if (use_dram0) {
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_DRAM0_SRAM))
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_DRAM0_SRAM))
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_DRAM0_SRAM))
+        }
+        if (use_rtcfast) {
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_split_addr_lock(MEMPROT_TYPE_IRAM0_RTCFAST))
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_pms_lock(MEMPROT_TYPE_IRAM0_RTCFAST))
+            ESP_MEMPROT_ERR_CHECK(ret, esp_mprot_set_monitor_lock(MEMPROT_TYPE_IRAM0_RTCFAST))
+        }
+    }
+
+    return ret;
+}
+
+esp_err_t esp_mprot_dump_configuration(char **dump_info_string)
+{
+    if (dump_info_string == NULL) {
+        return ESP_ERR_INVALID_ARG;;
+    }
+
+    *dump_info_string = calloc(1024, 1);
+
+    if (*dump_info_string == NULL) {
+        return ESP_ERR_NO_MEM;
+    }
+
+    bool line_lock = memprot_ll_get_iram0_dram0_split_line_lock();
+    uint32_t line_ID = (uint32_t)memprot_ll_get_iram0_split_line_main_I_D();
+    uint32_t line_I0 = (uint32_t)memprot_ll_get_iram0_split_line_I_0();
+    uint32_t line_I1 = (uint32_t)memprot_ll_get_iram0_split_line_I_1();
+    uint32_t line_D0 = (uint32_t)memprot_ll_get_dram0_split_line_D_0();
+    uint32_t line_D1 = (uint32_t)memprot_ll_get_dram0_split_line_D_1();
+    uint32_t line_ID_cat = (uint32_t)memprot_ll_get_iram0_split_line_main_I_D_cat();
+    uint32_t line_I0_cat = (uint32_t)memprot_ll_get_iram0_split_line_I_0_cat();
+    uint32_t line_I1_cat = (uint32_t)memprot_ll_get_iram0_split_line_I_1_cat();
+    uint32_t line_D0_cat = (uint32_t)memprot_ll_get_dram0_split_line_D_0_cat();
+    uint32_t line_D1_cat = (uint32_t)memprot_ll_get_dram0_split_line_D_1_cat();
+
+    sprintf(*dump_info_string,
+            "Split line settings (lock=%u):\n"
+            " IRAM0:\n   line ID (main): 0x%08X (cat=0x%08X)\n   line I0: 0x%08X (cat=0x%08X)\n   line I1: 0x%08X (cat=0x%08X)\n"
+            " DRAM0:\n   line D0: 0x%08X (cat=0x%08X)\n   line D1: 0x%08X (cat=0x%08X)\n",
+            line_lock, line_ID, line_ID_cat, line_I0, line_I0_cat, line_I1, line_I1_cat, line_D0, line_D0_cat, line_D1, line_D1_cat);
+
+    uint32_t offset = strlen(*dump_info_string);
+
+    void *line_RTC = NULL;
+    esp_err_t err = esp_mprot_ll_err_to_esp_err(memprot_ll_get_rtcfast_split_line(MEMP_LL_WORLD_0, &line_RTC));
+    if (err != ESP_OK) {
+        sprintf((*dump_info_string + offset), " RTCFAST:\n   line main: N/A (world=0) - %s\n", esp_err_to_name(err));
+    } else {
+        sprintf((*dump_info_string + offset), " RTCFAST:\n   line main: 0x%08X (world=0)\n", (uint32_t)line_RTC);
+    }
+
+    offset = strlen(*dump_info_string);
+
+    bool ar0i, ar1i, ar2i, ar3i;
+    bool aw0i, aw1i, aw2i, aw3i;
+    bool ax0i, ax1i, ax2i, ax3i;
+    bool ar0d, ar1d, ar2d, ar3d;
+    bool aw0d, aw1d, aw2d, aw3d;
+
+    bool pms_lock_i = memprot_ll_iram0_get_pms_lock();
+    memprot_ll_iram0_get_pms_area_0(&ar0i, &aw0i, &ax0i);
+    memprot_ll_iram0_get_pms_area_1(&ar1i, &aw1i, &ax1i);
+    memprot_ll_iram0_get_pms_area_2(&ar2i, &aw2i, &ax2i);
+    memprot_ll_iram0_get_pms_area_3(&ar3i, &aw3i, &ax3i);
+
+    bool pms_lock_d = memprot_ll_dram0_get_pms_lock();
+    memprot_ll_dram0_get_pms_area_0(&ar0d, &aw0d);
+    memprot_ll_dram0_get_pms_area_1(&ar1d, &aw1d);
+    memprot_ll_dram0_get_pms_area_2(&ar2d, &aw2d);
+    memprot_ll_dram0_get_pms_area_3(&ar3d, &aw3d);
+
+    bool rtc_line_lock = memprot_ll_get_pif_constraint_lock();
+
+    sprintf((*dump_info_string + offset),
+            "PMS area settings:\n"
+            " IRAM0 (lock=%u):\n   area 0: r=%u,w=%u,x=%u\n   area 1: r=%u,w=%u,x=%u\n   area 2: r=%u,w=%u,x=%u\n   area 3: r=%u,w=%u,x=%u\n"
+            " DRAM0 (lock=%u):\n   area 0: r=%u,w=%u\n   area 1: r=%u,w=%u\n   area 2: r=%u,w=%u\n   area 3: r=%u,w=%u\n"
+            " RTCFAST (lock=%u):\n",
+            pms_lock_i, ar0i, aw0i, ax0i, ar1i, aw1i, ax1i, ar2i, aw2i, ax2i, ar3i, aw3i, ax3i,
+            pms_lock_d, ar0d, aw0d, ar1d, aw1d, ar2d, aw2d, ar3d, aw3d, rtc_line_lock);
+
+    offset = strlen(*dump_info_string);
+
+    bool arl0rtc, awl0rtc, axl0rtc;
+    bool arh0rtc, awh0rtc, axh0rtc;
+
+    err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(&arl0rtc, &awl0rtc, &axl0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_LOW));
+    if (err != ESP_OK) {
+        sprintf((*dump_info_string + offset), "   area low: N/A - %s\n", esp_err_to_name(err));
+    } else {
+        sprintf((*dump_info_string + offset), "   area low: r=%u,w=%u,x=%u\n", arl0rtc, awl0rtc, axl0rtc);
+    }
+
+    offset = strlen(*dump_info_string);
+
+    err = esp_mprot_ll_err_to_esp_err(memprot_ll_rtcfast_get_pms_area(&arh0rtc, &awh0rtc, &axh0rtc, MEMP_LL_WORLD_0, MEMP_LL_AREA_HIGH));
+    if (err != ESP_OK) {
+        sprintf((*dump_info_string + offset), "   area high: N/A - %s\n", esp_err_to_name(err));
+    } else {
+        sprintf((*dump_info_string + offset), "   area high: r=%u,w=%u,x=%u\n", arh0rtc, awh0rtc, axh0rtc);
+    }
+
+    offset = strlen(*dump_info_string);
+
+    bool monitor_lock_i = memprot_ll_iram0_get_monitor_lock();
+    bool monitor_en_i = memprot_ll_iram0_get_monitor_en();
+    bool monitor_clr_i = memprot_ll_iram0_get_monitor_intrclr();
+    bool monitor_lock_d = memprot_ll_dram0_get_monitor_lock();
+    bool monitor_en_d = memprot_ll_dram0_get_monitor_en();
+    bool monitor_clr_d = memprot_ll_dram0_get_monitor_intrclr();
+    bool monitor_lock_rtc = memprot_ll_rtcfast_get_monitor_lock();
+    bool monitor_en_rtc = memprot_ll_rtcfast_get_monitor_en();
+    bool monitor_clr_rtc = memprot_ll_rtcfast_get_monitor_intrclr();
+
+    sprintf((*dump_info_string + offset),
+            "Monitor settings:\n"
+            " IRAM0 (lock=%u):\n   enabled=%u\n   intr_clr=%u\n"
+            " DRAM0 (lock=%u):\n   enabled=%u\n   intr_clr=%u\n"
+            " RTCFAST (lock=%u):\n   enabled=%u\n   intr_clr=%u\n",
+            monitor_lock_i, monitor_en_i, monitor_clr_i,
+            monitor_lock_d, monitor_en_d, monitor_clr_d,
+            monitor_lock_rtc, monitor_en_rtc, monitor_clr_rtc);
+
+    return ESP_OK;
+}

+ 0 - 617
components/esp_hw_support/port/esp32c3/memprot.c

@@ -1,617 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/* INTERNAL API
- * implementation of PMS memory protection features
- */
-
-#include <stdio.h>
-#include "sdkconfig.h"
-#include "soc/sensitive_reg.h"
-#include "soc/dport_access.h"
-#include "soc/periph_defs.h"
-#include "esp_intr_alloc.h"
-#include "hal/memprot_ll.h"
-#include "esp32c3/memprot.h"
-#include "riscv/interrupt.h"
-#include "esp32c3/rom/ets_sys.h"
-#include "esp_log.h"
-#include "esp_fault.h"
-#include "soc/cpu.h"
-
-extern int _iram_text_end;
-static const char *TAG = "memprot";
-
-const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type)
-{
-    switch (mem_type) {
-    case MEMPROT_NONE:
-        return "NONE";
-    case MEMPROT_IRAM0_SRAM:
-        return "IRAM0_SRAM";
-    case MEMPROT_DRAM0_SRAM:
-        return "DRAM0_SRAM";
-    case MEMPROT_ALL:
-        return "ALL";
-    default:
-        return "UNKNOWN";
-    }
-}
-
-const char *esp_memprot_split_line_to_str(split_line_t line_type)
-{
-    switch (line_type) {
-    case MEMPROT_IRAM0_DRAM0_SPLITLINE:
-        return "MEMPROT_IRAM0_DRAM0_SPLITLINE";
-    case MEMPROT_IRAM0_LINE_0_SPLITLINE:
-        return "MEMPROT_IRAM0_LINE_0_SPLITLINE";
-    case MEMPROT_IRAM0_LINE_1_SPLITLINE:
-        return "MEMPROT_IRAM0_LINE_1_SPLITLINE";
-    case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
-        return "MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE";
-    case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
-        return "MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE";
-    default:
-        return "UNKNOWN";
-    }
-}
-
-const char *esp_memprot_pms_to_str(pms_area_t area_type)
-{
-    switch (area_type) {
-    case MEMPROT_IRAM0_PMS_AREA_0:
-        return "MEMPROT_IRAM0_PMS_AREA_0";
-    case MEMPROT_IRAM0_PMS_AREA_1:
-        return "MEMPROT_IRAM0_PMS_AREA_1";
-    case MEMPROT_IRAM0_PMS_AREA_2:
-        return "MEMPROT_IRAM0_PMS_AREA_2";
-    case MEMPROT_IRAM0_PMS_AREA_3:
-        return "MEMPROT_IRAM0_PMS_AREA_3";
-    case MEMPROT_DRAM0_PMS_AREA_0:
-        return "MEMPROT_DRAM0_PMS_AREA_0";
-    case MEMPROT_DRAM0_PMS_AREA_1:
-        return "MEMPROT_DRAM0_PMS_AREA_1";
-    case MEMPROT_DRAM0_PMS_AREA_2:
-        return "MEMPROT_DRAM0_PMS_AREA_2";
-    case MEMPROT_DRAM0_PMS_AREA_3:
-        return "MEMPROT_DRAM0_PMS_AREA_3";
-    default:
-        return "UNKNOWN";
-    }
-}
-
-
-/* split lines */
-
-void *esp_memprot_get_default_main_split_addr()
-{
-    return &_iram_text_end;
-}
-
-uint32_t *esp_memprot_get_split_addr(split_line_t line_type)
-{
-    switch ( line_type ) {
-    case MEMPROT_IRAM0_DRAM0_SPLITLINE:
-        return memprot_ll_get_iram0_split_line_main_I_D();
-    case MEMPROT_IRAM0_LINE_0_SPLITLINE:
-        return memprot_ll_get_iram0_split_line_I_0();
-    case MEMPROT_IRAM0_LINE_1_SPLITLINE:
-        return memprot_ll_get_iram0_split_line_I_1();
-    case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
-        return memprot_ll_get_dram0_split_line_D_0();
-    case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
-        return memprot_ll_get_dram0_split_line_D_1();
-    default:
-        abort();
-    }
-}
-
-void esp_memprot_set_split_line_lock()
-{
-    memprot_ll_set_iram0_dram0_split_line_lock();
-}
-
-bool esp_memprot_get_split_line_lock()
-{
-    return memprot_ll_get_iram0_dram0_split_line_lock();
-}
-
-void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr)
-{
-    ESP_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", esp_memprot_split_line_to_str(line_type), (uint32_t)line_addr);
-
-    //split-line must be divisible by 512 (PMS module restriction)
-    assert( ((uint32_t)line_addr) % 0x200 == 0 );
-
-    switch ( line_type ) {
-    case MEMPROT_IRAM0_DRAM0_SPLITLINE:
-        memprot_ll_set_iram0_split_line_main_I_D(line_addr);
-        break;
-    case MEMPROT_IRAM0_LINE_0_SPLITLINE:
-        memprot_ll_set_iram0_split_line_I_0(line_addr);
-        break;
-    case MEMPROT_IRAM0_LINE_1_SPLITLINE:
-        memprot_ll_set_iram0_split_line_I_1(line_addr);
-        break;
-    case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
-        memprot_ll_set_dram0_split_line_D_0(line_addr);
-        break;
-    case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
-        memprot_ll_set_dram0_split_line_D_1(line_addr);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", (uint32_t)line_addr);
-        abort();
-    }
-}
-
-
-/* PMS */
-
-void esp_memprot_set_pms_lock(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        memprot_ll_iram0_set_pms_lock();
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        memprot_ll_dram0_set_pms_lock();
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_pms_lock();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_pms_lock();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", esp_memprot_pms_to_str(area_type), r, w, x);
-
-    switch ( area_type ) {
-    case MEMPROT_IRAM0_PMS_AREA_0:
-        memprot_ll_iram0_set_pms_area_0(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_1:
-        memprot_ll_iram0_set_pms_area_1(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_2:
-        memprot_ll_iram0_set_pms_area_2(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_3:
-        memprot_ll_iram0_set_pms_area_3(r, w, x);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
-        abort();
-    }
-}
-
-void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_iram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
-
-    switch ( area_type ) {
-    case MEMPROT_IRAM0_PMS_AREA_0:
-        memprot_ll_iram0_get_pms_area_0(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_1:
-        memprot_ll_iram0_get_pms_area_1(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_2:
-        memprot_ll_iram0_get_pms_area_2(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_3:
-        memprot_ll_iram0_get_pms_area_3(r, w, x);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
-        abort();
-    }
-}
-
-void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
-
-    switch ( area_type ) {
-    case MEMPROT_DRAM0_PMS_AREA_0:
-        memprot_ll_dram0_set_pms_area_0(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_1:
-        memprot_ll_dram0_set_pms_area_1(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_2:
-        memprot_ll_dram0_set_pms_area_2(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_3:
-        memprot_ll_dram0_set_pms_area_3(r, w);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
-        abort();
-    }
-}
-
-void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_dram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
-
-    switch ( area_type ) {
-    case MEMPROT_DRAM0_PMS_AREA_0:
-        memprot_ll_dram0_get_pms_area_0(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_1:
-        memprot_ll_dram0_get_pms_area_1(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_2:
-        memprot_ll_dram0_get_pms_area_2(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_3:
-        memprot_ll_dram0_get_pms_area_3(r, w);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
-        abort();
-    }
-}
-
-
-/* monitor */
-
-void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        memprot_ll_iram0_set_monitor_lock();
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        memprot_ll_dram0_set_monitor_lock();
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_lock();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_lock();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        memprot_ll_iram0_set_monitor_en(enable);
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        memprot_ll_dram0_set_monitor_en(enable);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_en();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_en();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_is_intr_ena_any()
-{
-    return esp_memprot_get_monitor_en(MEMPROT_IRAM0_SRAM) || esp_memprot_get_monitor_en(MEMPROT_DRAM0_SRAM);
-}
-
-void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        memprot_ll_iram0_clear_monitor_intr();
-        memprot_ll_iram0_reset_clear_monitor_intr();
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        memprot_ll_dram0_clear_monitor_intr();
-        memprot_ll_dram0_reset_clear_monitor_intr();
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-mem_type_prot_t esp_memprot_get_active_intr_memtype()
-{
-    if ( memprot_ll_iram0_get_monitor_status_intr() > 0 ) {
-        return MEMPROT_IRAM0_SRAM;
-    } else if ( memprot_ll_dram0_get_monitor_status_intr() ) {
-        return MEMPROT_DRAM0_SRAM;
-    }
-
-    return MEMPROT_NONE;
-}
-
-bool esp_memprot_is_locked_any()
-{
-    return
-        esp_memprot_get_split_line_lock() ||
-        esp_memprot_get_pms_lock(MEMPROT_IRAM0_SRAM) ||
-        esp_memprot_get_pms_lock(MEMPROT_DRAM0_SRAM) ||
-        esp_memprot_get_monitor_lock(MEMPROT_IRAM0_SRAM) ||
-        esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM);
-}
-
-bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_status_intr() == 1;
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_status_intr() == 1;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_status_fault_addr();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_status_fault_addr();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
-{
-    uint32_t world = 0;
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        world = memprot_ll_iram0_get_monitor_status_fault_world();
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        world = memprot_ll_dram0_get_monitor_status_fault_world();
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-
-    switch ( world ) {
-    case 0x01: return MEMPROT_PMS_WORLD_0;
-    case 0x10: return MEMPROT_PMS_WORLD_1;
-    default: return MEMPROT_PMS_WORLD_INVALID;
-    }
-}
-
-pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_status_fault_byte_en();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-int esp_memprot_intr_get_cpuid()
-{
-    return PRO_CPU_NUM;
-}
-
-void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
-
-    switch (mem_type) {
-    case MEMPROT_IRAM0_SRAM:
-        intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-
-    /* Set the type and priority to cache error interrupts. */
-    esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL);
-    esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
-
-    ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);
-}
-
-void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask)
-{
-    esp_memprot_set_prot_int(invoke_panic_handler, lock_feature, NULL, mem_type_mask);
-}
-
-void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_prot(panic_handler: %u, lock: %u, split.addr: 0x%08X, mem.types: 0x%08X", invoke_panic_handler, lock_feature, (uint32_t)split_addr, (uint32_t)mem_type_mask);
-
-    uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask;
-    bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM;
-    bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM;
-
-    if (required_mem_prot == MEMPROT_NONE) {
-        return;
-    }
-
-    //disable protection
-    if (use_iram0) {
-        esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, false);
-    }
-    if (use_dram0) {
-        esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, false);
-    }
-
-    //if being debugged check we are not glitched and dont enable Memprot
-    if (esp_cpu_in_ocd_debug_mode()) {
-        ESP_FAULT_ASSERT(esp_cpu_in_ocd_debug_mode());
-    } else {
-
-        if (invoke_panic_handler) {
-            if (use_iram0) {
-                esp_memprot_set_intr_matrix(MEMPROT_IRAM0_SRAM);
-            }
-            if (use_dram0) {
-                esp_memprot_set_intr_matrix(MEMPROT_DRAM0_SRAM);
-            }
-        }
-
-        //set split lines (must-have for all mem_types)
-        const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr;
-        esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr);
-        esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr);
-        esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr);
-        esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE,
-                                   (void *) (MAP_IRAM_TO_DRAM((uint32_t) line_addr)));
-        esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE,
-                                   (void *) (MAP_IRAM_TO_DRAM((uint32_t) line_addr)));
-
-        //set permissions
-        if (required_mem_prot & MEMPROT_IRAM0_SRAM) {
-            esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, true, false, true);
-            esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, true, false, true);
-            esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, true, false, true);
-            esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, true, true, false);
-        }
-        if (required_mem_prot & MEMPROT_DRAM0_SRAM) {
-            esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_0, true, false);
-            esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, true, true);
-            esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, true, true);
-            esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, true, true);
-        }
-
-        //reenable the protection
-        if (use_iram0) {
-            esp_memprot_monitor_clear_intr(MEMPROT_IRAM0_SRAM);
-            esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, true);
-        }
-        if (use_dram0) {
-            esp_memprot_monitor_clear_intr(MEMPROT_DRAM0_SRAM);
-            esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, true);
-        }
-
-        //lock if required
-        if (lock_feature) {
-            esp_memprot_set_split_line_lock();
-            if (use_iram0) {
-                esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM);
-                esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM);
-            }
-            if (use_dram0) {
-                esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM);
-                esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM);
-            }
-        }
-    }
-}
-
-uint32_t esp_memprot_get_dram_status_reg_1()
-{
-    return memprot_ll_dram0_get_monitor_status_register_1();
-}
-
-uint32_t esp_memprot_get_dram_status_reg_2()
-{
-    return memprot_ll_dram0_get_monitor_status_register_2();
-}
-
-uint32_t esp_memprot_get_iram_status_reg()
-{
-    return memprot_ll_iram0_get_monitor_status_register();
-}
-
-uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type)
-{
-    switch (mem_type) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_enable_register();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_enable_register();
-    default:
-        abort();
-    }
-}

+ 5 - 1
components/esp_hw_support/port/esp32h2/CMakeLists.txt

@@ -10,11 +10,15 @@ set(srcs "cpu_util_esp32h2.c"
 
 if(NOT BOOTLOADER_BUILD)
     list(APPEND srcs "../async_memcpy_impl_gdma.c"
-                     "memprot.c"
                      "esp_hmac.c"
                      "esp_crypto_lock.c"
                      "esp_ds.c"
                      "dport_access.c")
+
+    if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
+        list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c")
+    endif()
+
 endif()
 
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

+ 215 - 0
components/esp_hw_support/port/esp32h2/esp_memprot.c

@@ -0,0 +1,215 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "sdkconfig.h"
+#include "soc/periph_defs.h"
+#include "esp_intr_alloc.h"
+#include "esp_fault.h"
+#include "esp_attr.h"
+#include "esp_memprot_err.h"
+#include "hal/memprot_types.h"
+#include "esp_private/esp_memprot_internal.h"
+#include "esp_memprot.h"
+
+esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr)
+{
+    if (line_addr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *line_addr = NULL;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr)
+{
+    if (def_split_addr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *def_split_addr = NULL;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *locked = false;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *locked = false;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags)
+{
+    if (flags == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *flags = MEMPROT_OP_NONE;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *locked = false;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled)
+{
+    if (enabled == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *enabled = false;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused)))
+{
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr)
+{
+    if (active_memp_intr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    active_memp_intr->mem_type = MEMPROT_TYPE_NONE;
+    active_memp_intr->core = -1;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *locked = false;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled)
+{
+    if (enabled == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *enabled = false;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused)))
+{
+    if (fault_addr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *fault_addr = NULL;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused)))
+{
+    if (world == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *world = MEMPROT_PMS_WORLD_NONE;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused)))
+{
+    if (oper == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *oper = MEMPROT_OP_NONE;
+
+    return ESP_OK;
+}
+
+bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type)
+{
+    return false;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused)))
+{
+    if (byte_en == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *byte_en = 0;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config)
+{
+    return ESP_OK;
+}

+ 0 - 608
components/esp_hw_support/port/esp32h2/memprot.c

@@ -1,608 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/* INTERNAL API
- * implementation of PMS memory protection features
- */
-
-#include <stdio.h>
-#include "sdkconfig.h"
-#include "soc/sensitive_reg.h"
-#include "soc/dport_access.h"
-#include "soc/periph_defs.h"
-#include "esp_intr_alloc.h"
-#include "hal/memprot_ll.h"
-#include "esp32h2/memprot.h"
-#include "riscv/interrupt.h"
-#include "esp32h2/rom/ets_sys.h"
-#include "esp_log.h"
-
-extern int _iram_text_end;
-static const char *TAG = "memprot";
-
-const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type)
-{
-    switch (mem_type) {
-    case MEMPROT_NONE:
-        return "NONE";
-    case MEMPROT_IRAM0_SRAM:
-        return "IRAM0_SRAM";
-    case MEMPROT_DRAM0_SRAM:
-        return "DRAM0_SRAM";
-    case MEMPROT_ALL:
-        return "ALL";
-    default:
-        return "UNKNOWN";
-    }
-}
-
-const char *esp_memprot_split_line_to_str(split_line_t line_type)
-{
-    switch (line_type) {
-    case MEMPROT_IRAM0_DRAM0_SPLITLINE:
-        return "MEMPROT_IRAM0_DRAM0_SPLITLINE";
-    case MEMPROT_IRAM0_LINE_0_SPLITLINE:
-        return "MEMPROT_IRAM0_LINE_0_SPLITLINE";
-    case MEMPROT_IRAM0_LINE_1_SPLITLINE:
-        return "MEMPROT_IRAM0_LINE_1_SPLITLINE";
-    case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
-        return "MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE";
-    case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
-        return "MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE";
-    default:
-        return "UNKNOWN";
-    }
-}
-
-const char *esp_memprot_pms_to_str(pms_area_t area_type)
-{
-    switch (area_type) {
-    case MEMPROT_IRAM0_PMS_AREA_0:
-        return "MEMPROT_IRAM0_PMS_AREA_0";
-    case MEMPROT_IRAM0_PMS_AREA_1:
-        return "MEMPROT_IRAM0_PMS_AREA_1";
-    case MEMPROT_IRAM0_PMS_AREA_2:
-        return "MEMPROT_IRAM0_PMS_AREA_2";
-    case MEMPROT_IRAM0_PMS_AREA_3:
-        return "MEMPROT_IRAM0_PMS_AREA_3";
-    case MEMPROT_DRAM0_PMS_AREA_0:
-        return "MEMPROT_DRAM0_PMS_AREA_0";
-    case MEMPROT_DRAM0_PMS_AREA_1:
-        return "MEMPROT_DRAM0_PMS_AREA_1";
-    case MEMPROT_DRAM0_PMS_AREA_2:
-        return "MEMPROT_DRAM0_PMS_AREA_2";
-    case MEMPROT_DRAM0_PMS_AREA_3:
-        return "MEMPROT_DRAM0_PMS_AREA_3";
-    default:
-        return "UNKNOWN";
-    }
-}
-
-
-/* split lines */
-
-void *esp_memprot_get_default_main_split_addr()
-{
-    return &_iram_text_end;
-}
-
-uint32_t *esp_memprot_get_split_addr(split_line_t line_type)
-{
-    switch ( line_type ) {
-        case MEMPROT_IRAM0_DRAM0_SPLITLINE:
-            return memprot_ll_get_iram0_split_line_main_I_D();
-        case MEMPROT_IRAM0_LINE_0_SPLITLINE:
-            return memprot_ll_get_iram0_split_line_I_0();
-        case MEMPROT_IRAM0_LINE_1_SPLITLINE:
-            return memprot_ll_get_iram0_split_line_I_1();
-        case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
-            return memprot_ll_get_dram0_split_line_D_0();
-        case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
-            return memprot_ll_get_dram0_split_line_D_1();
-        default:
-            abort();
-    }
-}
-
-void esp_memprot_set_split_line_lock()
-{
-    memprot_ll_set_iram0_dram0_split_line_lock();
-}
-
-bool esp_memprot_get_split_line_lock()
-{
-    return memprot_ll_get_iram0_dram0_split_line_lock();
-}
-
-void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr)
-{
-    ESP_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", esp_memprot_split_line_to_str(line_type), (uint32_t)line_addr);
-
-    //split-line must be divisible by 512 (PMS module restriction)
-    assert( ((uint32_t)line_addr) % 0x200 == 0 );
-
-    switch ( line_type ) {
-    case MEMPROT_IRAM0_DRAM0_SPLITLINE:
-        memprot_ll_set_iram0_split_line_main_I_D(line_addr);
-        break;
-    case MEMPROT_IRAM0_LINE_0_SPLITLINE:
-        memprot_ll_set_iram0_split_line_I_0(line_addr);
-        break;
-    case MEMPROT_IRAM0_LINE_1_SPLITLINE:
-        memprot_ll_set_iram0_split_line_I_1(line_addr);
-        break;
-    case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
-        memprot_ll_set_dram0_split_line_D_0(line_addr);
-        break;
-    case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
-        memprot_ll_set_dram0_split_line_D_1(line_addr);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", (uint32_t)line_addr);
-        abort();
-    }
-}
-
-
-/* PMS */
-
-void esp_memprot_set_pms_lock(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        memprot_ll_iram0_set_pms_lock();
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        memprot_ll_dram0_set_pms_lock();
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_pms_lock();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_pms_lock();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", esp_memprot_pms_to_str(area_type), r, w, x);
-
-    switch ( area_type ) {
-    case MEMPROT_IRAM0_PMS_AREA_0:
-        memprot_ll_iram0_set_pms_area_0(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_1:
-        memprot_ll_iram0_set_pms_area_1(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_2:
-        memprot_ll_iram0_set_pms_area_2(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_3:
-        memprot_ll_iram0_set_pms_area_3(r, w, x);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
-        abort();
-    }
-}
-
-void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_iram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
-
-    switch ( area_type ) {
-    case MEMPROT_IRAM0_PMS_AREA_0:
-        memprot_ll_iram0_get_pms_area_0(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_1:
-        memprot_ll_iram0_get_pms_area_1(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_2:
-        memprot_ll_iram0_get_pms_area_2(r, w, x);
-        break;
-    case MEMPROT_IRAM0_PMS_AREA_3:
-        memprot_ll_iram0_get_pms_area_3(r, w, x);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
-        abort();
-    }
-}
-
-void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
-
-    switch ( area_type ) {
-    case MEMPROT_DRAM0_PMS_AREA_0:
-        memprot_ll_dram0_set_pms_area_0(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_1:
-        memprot_ll_dram0_set_pms_area_1(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_2:
-        memprot_ll_dram0_set_pms_area_2(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_3:
-        memprot_ll_dram0_set_pms_area_3(r, w);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
-        abort();
-    }
-}
-
-void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_dram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
-
-    switch ( area_type ) {
-    case MEMPROT_DRAM0_PMS_AREA_0:
-        memprot_ll_dram0_get_pms_area_0(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_1:
-        memprot_ll_dram0_get_pms_area_1(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_2:
-        memprot_ll_dram0_get_pms_area_2(r, w);
-        break;
-    case MEMPROT_DRAM0_PMS_AREA_3:
-        memprot_ll_dram0_get_pms_area_3(r, w);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
-        abort();
-    }
-}
-
-
-/* monitor */
-
-void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        memprot_ll_iram0_set_monitor_lock();
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        memprot_ll_dram0_set_monitor_lock();
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_lock();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_lock();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        memprot_ll_iram0_set_monitor_en(enable);
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        memprot_ll_dram0_set_monitor_en(enable);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_en();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_en();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_is_intr_ena_any()
-{
-    return esp_memprot_get_monitor_en(MEMPROT_IRAM0_SRAM) || esp_memprot_get_monitor_en(MEMPROT_DRAM0_SRAM);
-}
-
-void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        memprot_ll_iram0_clear_monitor_intr();
-        memprot_ll_iram0_reset_clear_monitor_intr();
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        memprot_ll_dram0_clear_monitor_intr();
-        memprot_ll_dram0_reset_clear_monitor_intr();
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-mem_type_prot_t esp_memprot_get_active_intr_memtype()
-{
-    if ( memprot_ll_iram0_get_monitor_status_intr() > 0 ) {
-        return MEMPROT_IRAM0_SRAM;
-    } else if ( memprot_ll_dram0_get_monitor_status_intr() ) {
-        return MEMPROT_DRAM0_SRAM;
-    }
-
-    return MEMPROT_NONE;
-}
-
-bool esp_memprot_is_locked_any()
-{
-    return
-        esp_memprot_get_split_line_lock() ||
-        esp_memprot_get_pms_lock(MEMPROT_IRAM0_SRAM) ||
-        esp_memprot_get_pms_lock(MEMPROT_DRAM0_SRAM) ||
-        esp_memprot_get_monitor_lock(MEMPROT_IRAM0_SRAM) ||
-        esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM);
-}
-
-bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_status_intr() == 1;
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_status_intr() == 1;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_status_fault_addr();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_status_fault_addr();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
-{
-    uint32_t world = 0;
-
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        world = memprot_ll_iram0_get_monitor_status_fault_world();
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        world = memprot_ll_dram0_get_monitor_status_fault_world();
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-
-    switch ( world ) {
-        case 0x01: return MEMPROT_PMS_WORLD_0;
-        case 0x10: return MEMPROT_PMS_WORLD_1;
-        default: return MEMPROT_PMS_WORLD_INVALID;
-    }
-}
-
-pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type)
-{
-    switch ( mem_type ) {
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_status_fault_byte_en();
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-}
-
-int esp_memprot_intr_get_cpuid()
-{
-    return PRO_CPU_NUM;
-}
-
-void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", esp_memprot_mem_type_to_str(mem_type));
-
-    ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
-
-    switch (mem_type) {
-    case MEMPROT_IRAM0_SRAM:
-        intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
-        break;
-    case MEMPROT_DRAM0_SRAM:
-        intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
-        break;
-    default:
-        ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
-        abort();
-    }
-
-    /* Set the type and priority to cache error interrupts. */
-    esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL);
-    esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
-
-    ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);
-}
-
-void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask)
-{
-    esp_memprot_set_prot_int(invoke_panic_handler, lock_feature, NULL, mem_type_mask);
-}
-
-void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask)
-{
-    ESP_EARLY_LOGD(TAG, "esp_memprot_set_prot(panic_handler: %u, lock: %u, split.addr: 0x%08X, mem.types: 0x%08X", invoke_panic_handler, lock_feature, (uint32_t)split_addr, (uint32_t)mem_type_mask);
-
-    uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask;
-    bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM;
-    bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM;
-
-    if (required_mem_prot == MEMPROT_NONE) {
-        return;
-    }
-
-    //disable protection
-    if (use_iram0) {
-        esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, false);
-    }
-    if (use_dram0) {
-        esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, false);
-    }
-
-    //panic handling
-    if (invoke_panic_handler) {
-        if (use_iram0) {
-            esp_memprot_set_intr_matrix(MEMPROT_IRAM0_SRAM);
-        }
-        if (use_dram0) {
-            esp_memprot_set_intr_matrix(MEMPROT_DRAM0_SRAM);
-        }
-    }
-
-    //set split lines (must-have for all mem_types)
-    const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr;
-    esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr);
-    esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr);
-    esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr);
-    esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)));
-    esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)));
-
-    //set permissions
-    if (required_mem_prot & MEMPROT_IRAM0_SRAM) {
-        esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, true, false, true);
-        esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, true, false, true);
-        esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, true, false, true);
-        esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, true, true, false);
-    }
-    if (required_mem_prot & MEMPROT_DRAM0_SRAM) {
-        esp_memprot_dram_set_pms_area( MEMPROT_DRAM0_PMS_AREA_0, true, false );
-        esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, true, true);
-        esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, true, true);
-        esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, true, true);
-    }
-
-    //reenable protection
-    if (use_iram0) {
-        esp_memprot_monitor_clear_intr(MEMPROT_IRAM0_SRAM);
-        esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, true);
-    }
-    if (use_dram0) {
-        esp_memprot_monitor_clear_intr(MEMPROT_DRAM0_SRAM);
-        esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, true);
-    }
-
-    //lock if required
-    if (lock_feature) {
-        esp_memprot_set_split_line_lock();
-        if (use_iram0) {
-            esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM);
-            esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM);
-        }
-        if (use_dram0) {
-            esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM);
-            esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM);
-        }
-    }
-}
-
-uint32_t esp_memprot_get_dram_status_reg_1()
-{
-    return memprot_ll_dram0_get_monitor_status_register_1();
-}
-
-uint32_t esp_memprot_get_dram_status_reg_2()
-{
-    return memprot_ll_dram0_get_monitor_status_register_2();
-}
-
-uint32_t esp_memprot_get_iram_status_reg()
-{
-    return memprot_ll_iram0_get_monitor_status_register();
-}
-
-uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type)
-{
-    switch (mem_type) {
-    case MEMPROT_IRAM0_SRAM:
-        return memprot_ll_iram0_get_monitor_enable_register();
-    case MEMPROT_DRAM0_SRAM:
-        return memprot_ll_dram0_get_monitor_enable_register();
-    default:
-        abort();
-    }
-}

+ 4 - 1
components/esp_hw_support/port/esp32s3/CMakeLists.txt

@@ -18,7 +18,6 @@ if(NOT BOOTLOADER_BUILD)
         "esp_hmac.c"
         "esp_ds.c"
         "esp_crypto_lock.c"
-        "memprot.c"
         "spiram.c")
 
     if(CONFIG_SPIRAM_MODE_QUAD)
@@ -27,6 +26,10 @@ if(NOT BOOTLOADER_BUILD)
         list(APPEND srcs "opiram_psram.c")
     endif()
 
+    if(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE)
+        list(APPEND srcs "esp_memprot.c" "../esp_memprot_conv.c")
+    endif()
+
 endif()
 
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

+ 215 - 0
components/esp_hw_support/port/esp32s3/esp_memprot.c

@@ -0,0 +1,215 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "sdkconfig.h"
+#include "soc/periph_defs.h"
+#include "esp_intr_alloc.h"
+#include "esp_fault.h"
+#include "esp_attr.h"
+#include "esp_memprot_err.h"
+#include "hal/memprot_types.h"
+#include "esp_private/esp_memprot_internal.h"
+#include "esp_memprot.h"
+
+esp_err_t esp_mprot_set_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, const void *line_addr)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_split_addr(const esp_mprot_mem_t mem_type, const esp_mprot_split_addr_t line_type, void **line_addr)
+{
+    if (line_addr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *line_addr = NULL;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_default_main_split_addr(const esp_mprot_mem_t mem_type, void **def_split_addr)
+{
+    if (def_split_addr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *def_split_addr = NULL;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_split_addr_lock(const esp_mprot_mem_t mem_type)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_split_addr_lock(const esp_mprot_mem_t mem_type, bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *locked = false;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_pms_lock(const esp_mprot_mem_t mem_type)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_pms_lock(const esp_mprot_mem_t mem_type, bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *locked = false;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_pms_area(const esp_mprot_pms_area_t area_type, const uint32_t flags)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_pms_area(const esp_mprot_pms_area_t area_type, uint32_t *flags)
+{
+    if (flags == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *flags = MEMPROT_OP_NONE;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_monitor_lock(const esp_mprot_mem_t mem_type)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_monitor_lock(const esp_mprot_mem_t mem_type, bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *locked = false;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_monitor_en(const esp_mprot_mem_t mem_type, const bool enable)
+{
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_get_monitor_en(const esp_mprot_mem_t mem_type, bool *enabled)
+{
+    if (enabled == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *enabled = false;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_monitor_clear_intr(const esp_mprot_mem_t mem_type, int const *const core __attribute__((unused)))
+{
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_active_intr(esp_memp_intr_source_t *active_memp_intr)
+{
+    if (active_memp_intr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    active_memp_intr->mem_type = MEMPROT_TYPE_NONE;
+    active_memp_intr->core = -1;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_is_conf_locked_any(bool *locked)
+{
+    if (locked == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *locked = false;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_is_intr_ena_any(bool *enabled)
+{
+    if (enabled == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *enabled = false;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_addr(const esp_mprot_mem_t mem_type, void **fault_addr, int const *const core __attribute__((unused)))
+{
+    if (fault_addr == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *fault_addr = NULL;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_world(const esp_mprot_mem_t mem_type, esp_mprot_pms_world_t *world, int const *const core __attribute__((unused)))
+{
+    if (world == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *world = MEMPROT_PMS_WORLD_NONE;
+
+    return ESP_OK;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_operation(const esp_mprot_mem_t mem_type, uint32_t *oper, int const *const core __attribute__((unused)))
+{
+    if (oper == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *oper = MEMPROT_OP_NONE;
+
+    return ESP_OK;
+}
+
+bool IRAM_ATTR esp_mprot_has_byte_enables(const esp_mprot_mem_t mem_type)
+{
+    return false;
+}
+
+esp_err_t IRAM_ATTR esp_mprot_get_violate_byte_enables(const esp_mprot_mem_t mem_type, uint32_t *byte_en, int const *const core __attribute__((unused)))
+{
+    if (byte_en == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    *byte_en = 0;
+
+    return ESP_OK;
+}
+
+esp_err_t esp_mprot_set_prot(const esp_memp_config_t *memp_config)
+{
+    return ESP_OK;
+}

+ 0 - 17
components/esp_hw_support/port/esp32s3/memprot.c

@@ -1,17 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-/* INTERNAL API
- * implementation of generic interface to MMU memory protection features
- */
-
-#include <stdbool.h>
-#include "esp32s3/memprot.h"
-
-mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void)
-{
-    return MEMPROT_NONE;
-}

+ 63 - 0
components/esp_hw_support/port/esp_memprot_conv.c

@@ -0,0 +1,63 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "esp_memprot_err.h"
+#include "hal/memprot_types.h"
+#include "esp_memprot_types.h"
+
+esp_err_t esp_mprot_ll_err_to_esp_err(const memprot_ll_err_t err)
+{
+    switch (err) {
+    case MEMP_LL_OK: return ESP_OK;
+    case MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE: return ESP_ERR_MEMPROT_SPLIT_ADDR_OUT_OF_RANGE;
+    case MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED: return ESP_ERR_MEMPROT_SPLIT_ADDR_UNALIGNED;
+    case MEMP_LL_ERR_UNI_BLOCK_INVALID: return ESP_ERR_MEMPROT_UNIMGMT_BLOCK_INVALID;
+    case MEMP_LL_ERR_WORLD_INVALID: return ESP_ERR_MEMPROT_WORLD_INVALID;
+    case MEMP_LL_ERR_AREA_INVALID: return ESP_ERR_MEMPROT_AREA_INVALID;
+    default:
+        return ESP_FAIL;
+    }
+}
+
+esp_mprot_pms_world_t esp_mprot_ll_world_to_hl_world(const memprot_ll_world_t world)
+{
+    switch (world) {
+    case MEMP_LL_WORLD_NONE: return MEMPROT_PMS_WORLD_NONE;
+    case MEMP_LL_WORLD_0: return MEMPROT_PMS_WORLD_0;
+    case MEMP_LL_WORLD_1: return MEMPROT_PMS_WORLD_1;
+    default:
+        return MEMPROT_PMS_WORLD_INVALID;
+    }
+}
+
+const char *esp_mprot_oper_type_to_str(const uint32_t oper_type)
+{
+    switch (oper_type) {
+    case MEMPROT_OP_NONE: return "NONE";
+    case MEMPROT_OP_READ: return "READ";
+    case MEMPROT_OP_WRITE: return "WRITE";
+    case MEMPROT_OP_EXEC: return "EXEC";
+    default: return "INVALID";
+    }
+}
+
+const char *esp_mprot_pms_world_to_str(const esp_mprot_pms_world_t world_type)
+{
+    switch (world_type) {
+    case MEMPROT_PMS_WORLD_NONE:
+        return "PMS_WORLD_NONE";
+    case MEMPROT_PMS_WORLD_0:
+        return "PMS_WORLD_0";
+    case MEMPROT_PMS_WORLD_1:
+        return "PMS_WORLD_1";
+    case MEMPROT_PMS_WORLD_2:
+        return "PMS_WORLD_2";
+    case MEMPROT_PMS_WORLD_ALL:
+        return "PMS_WORLD_ALL";
+    default:
+        return "PMS_WORLD_INVALID";
+    }
+}

+ 13 - 6
components/esp_system/esp_system.c

@@ -14,14 +14,12 @@
 #include "soc/rtc_cntl_reg.h"
 #include "esp_private/panic_internal.h"
 #include "esp_rom_uart.h"
+#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
 #if CONFIG_IDF_TARGET_ESP32S2
 #include "esp32s2/memprot.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/memprot.h"
-#elif CONFIG_IDF_TARGET_ESP32C3
-#include "esp32c3/memprot.h"
-#elif CONFIG_IDF_TARGET_ESP32H2
-#include "esp32h2/memprot.h"
+#else
+#include "esp_memprot.h"
+#endif
 #endif
 
 #define SHUTDOWN_HANDLERS_NO 5
@@ -86,9 +84,18 @@ void IRAM_ATTR esp_restart(void)
 
     bool digital_reset_needed = false;
 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
+#if CONFIG_IDF_TARGET_ESP32S2
     if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
         digital_reset_needed = true;
     }
+#else
+    bool is_on = false;
+    if (esp_mprot_is_intr_ena_any(&is_on) != ESP_OK || is_on) {
+        digital_reset_needed = true;
+    } else if (esp_mprot_is_conf_locked_any(&is_on) != ESP_OK || is_on) {
+        digital_reset_needed = true;
+    }
+#endif
 #endif
     if (digital_reset_needed) {
         esp_restart_noos_dig();

+ 3 - 2
components/esp_system/ld/esp32c3/sections.ld.in

@@ -21,8 +21,9 @@ SECTIONS
     mapping[rtc_text]
 
     *rtc_wake_stub*.*(.literal .text .literal.* .text.*)
+    *(.rtc_text_end_test)
 
-     /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */
+    /* 16B padding for possible CPU prefetch and 4B alignment for PMS split lines */
     . += _esp_memprot_prefetch_pad_size;
     . = ALIGN(4);
 
@@ -368,7 +369,7 @@ SECTIONS
   /* Marks the end of IRAM code segment */
   .iram0.text_end (NOLOAD) :
   {
-    /* iram_end_test section exists for use by memprot unit tests only */
+    /* iram_end_test section exists for use by Memprot unit tests only */
     *(.iram_end_test)
     /* ESP32-C3 memprot requires 16B padding for possible CPU prefetch and 512B alignment for PMS split lines */
     . += _esp_memprot_prefetch_pad_size;

+ 54 - 30
components/esp_system/port/arch/riscv/panic_arch.c

@@ -15,11 +15,8 @@
 #include "cache_err_int.h"
 
 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
-#if CONFIG_IDF_TARGET_ESP32C3
-#include "esp32c3/memprot.h"
-#elif CONFIG_IDF_TARGET_ESP32H2
-#include "esp32h2/memprot.h"
-#endif
+#include "esp_private/esp_memprot_internal.h"
+#include "esp_memprot.h"
 #endif
 
 #if CONFIG_ESP_SYSTEM_USE_EH_FRAME
@@ -154,35 +151,62 @@ static inline void print_cache_err_details(const void *frame)
  * explanation of why the panic occured.
  */
 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
+
+static esp_memp_intr_source_t s_memp_intr = {MEMPROT_TYPE_INVALID, -1};
+
+#define PRINT_MEMPROT_ERROR(err) \
+        panic_print_str("N/A (error "); \
+        panic_print_str(esp_err_to_name(err)); \
+        panic_print_str(")");
+
 static inline void print_memprot_err_details(const void *frame __attribute__((unused)))
 {
+    if (s_memp_intr.mem_type == MEMPROT_TYPE_INVALID && s_memp_intr.core == -1) {
+        panic_print_str("  - no details available -\r\n");
+        return;
+    }
+
     //common memprot fault info
-    mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();
-    panic_print_str( "  memory type: ");
-    panic_print_str( esp_memprot_mem_type_to_str(mem_type) );
-    panic_print_str( "\r\n  faulting address: 0x");
-    panic_print_hex( esp_memprot_get_violate_addr(mem_type) );
-    panic_print_str( "\r\n  world:");
-    panic_print_dec( esp_memprot_get_violate_world(mem_type) );
-
-    char operation = 0;
-    // IRAM fault: check instruction-fetch flag
-    if ( mem_type == MEMPROT_IRAM0_SRAM ) {
-        if ( esp_memprot_get_violate_loadstore(mem_type) ) {
-            operation = 'X';
-        }
+    panic_print_str("  memory type: ");
+    panic_print_str(esp_mprot_mem_type_to_str(s_memp_intr.mem_type));
+
+    panic_print_str("\r\n  faulting address: ");
+    void *faulting_addr;
+    esp_err_t res = esp_mprot_get_violate_addr(s_memp_intr.mem_type, &faulting_addr, &s_memp_intr.core);
+    if (res == ESP_OK) {
+        panic_print_str("0x");
+        panic_print_hex((int)faulting_addr);
+    } else {
+        PRINT_MEMPROT_ERROR(res)
     }
-    // W/R - common
-    if ( operation == 0 ) {
-        operation = esp_memprot_get_violate_wr(mem_type) == MEMPROT_PMS_OP_WRITE ? 'W' : 'R';
+
+    panic_print_str( "\r\n  world: ");
+    esp_mprot_pms_world_t world;
+    res = esp_mprot_get_violate_world(s_memp_intr.mem_type, &world, &s_memp_intr.core);
+    if (res == ESP_OK) {
+        panic_print_str(esp_mprot_pms_world_to_str(world));
+    } else {
+        PRINT_MEMPROT_ERROR(res)
     }
+
     panic_print_str( "\r\n  operation type: ");
-    panic_print_char( operation );
+    uint32_t operation;
+    res = esp_mprot_get_violate_operation(s_memp_intr.mem_type, &operation, &s_memp_intr.core);
+    if (res == ESP_OK) {
+        panic_print_str(esp_mprot_oper_type_to_str(operation));
+    } else {
+        PRINT_MEMPROT_ERROR(res)
+    }
 
-    // DRAM/DMA fault: check byte-enables
-    if ( mem_type == MEMPROT_DRAM0_SRAM ) {
+    if (esp_mprot_has_byte_enables(s_memp_intr.mem_type)) {
         panic_print_str("\r\n  byte-enables: " );
-        panic_print_hex(esp_memprot_get_violate_byte_en(mem_type));
+        uint32_t byte_enables;
+        res = esp_mprot_get_violate_byte_enables(s_memp_intr.mem_type, &byte_enables, &s_memp_intr.core);
+        if (res == ESP_OK) {
+            panic_print_hex(byte_enables);
+        } else {
+            PRINT_MEMPROT_ERROR(res)
+        }
     }
 
     panic_print_str("\r\n");
@@ -271,11 +295,10 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
         info->reason = pseudo_reason[PANIC_RSN_INTWDT_CPU0 + core];
     }
 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
-    else if ( frame->mcause == ETS_MEMPROT_ERR_INUM ) {
-
-        info->core = esp_memprot_intr_get_cpuid();
+    else if (frame->mcause == ETS_MEMPROT_ERR_INUM) {
         info->reason = pseudo_reason[PANIC_RSN_MEMPROT];
         info->details = print_memprot_err_details;
+        info->core = esp_mprot_get_active_intr(&s_memp_intr) == ESP_OK ? s_memp_intr.core : -1;
     }
 #endif
 }
@@ -318,7 +341,8 @@ void panic_arch_fill_info(void *frame, panic_info_t *info)
     info->frame = &regs;
 }
 
-static void panic_print_basic_backtrace(const void *frame, int core) {
+static void panic_print_basic_backtrace(const void *frame, int core)
+{
     // Basic backtrace
     panic_print_str("\r\nStack memory:\r\n");
     uint32_t sp = (uint32_t)((RvExcFrame *)frame)->sp;

+ 7 - 11
components/esp_system/port/arch/xtensa/panic_arch.c

@@ -22,13 +22,11 @@
 #include "soc/extmem_reg.h"
 #include "soc/cache_memory.h"
 #include "soc/rtc_cntl_reg.h"
-#if CONFIG_IDF_TARGET_ESP32S2
-#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
+#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
+#ifdef CONFIG_IDF_TARGET_ESP32S2
 #include "esp32s2/memprot.h"
-#endif
-#elif CONFIG_IDF_TARGET_ESP32S3
-#ifdef CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
-#include "esp32s3/memprot.h"
+#else
+#include "esp_memprot.h"
 #endif
 #endif
 #endif // CONFIG_IDF_TARGET_ESP32
@@ -268,13 +266,9 @@ static inline void print_memprot_err_details(const void *f)
 
     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
     }
 
     if (op_type == MEMPROT_OP_INVALID) {
@@ -437,9 +431,11 @@ void panic_soc_fill_info(void *f, panic_info_t *info)
         info->exception = PANIC_EXCEPTION_DEBUG;
     }
 
+    //MV note: ESP32S3 PMS handling?
+
 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
     if (frame->exccause == PANIC_RSN_CACHEERR) {
-#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
+#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && CONFIG_IDF_TARGET_ESP32S2
         if ( esp_memprot_is_intr_ena_any() ) {
             info->details = print_memprot_err_details;
             info->reason = "Memory protection fault";

+ 36 - 23
components/esp_system/port/cpu_start.c

@@ -33,13 +33,11 @@
 #include "esp32s2/rom/cache.h"
 #include "esp32s2/spiram.h"
 #include "esp32s2/dport_access.h"
-#include "esp32s2/memprot.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
 #include "esp32s3/rtc.h"
 #include "esp32s3/rom/cache.h"
 #include "esp32s3/spiram.h"
 #include "esp32s3/dport_access.h"
-#include "esp32s3/memprot.h"
 #include "soc/assist_debug_reg.h"
 #include "soc/cache_memory.h"
 #include "soc/system_reg.h"
@@ -48,12 +46,18 @@
 #include "esp32c3/rtc.h"
 #include "esp32c3/rom/cache.h"
 #include "soc/cache_memory.h"
-#include "esp32c3/memprot.h"
 #elif CONFIG_IDF_TARGET_ESP32H2
 #include "esp32h2/rtc.h"
 #include "esp32h2/rom/cache.h"
 #include "soc/cache_memory.h"
-#include "esp32h2/memprot.h"
+#endif
+
+#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
+#if CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/memprot.h"
+#else
+#include "esp_memprot.h"
+#endif
 #endif
 
 #include "esp_private/spi_flash_os.h"
@@ -358,7 +362,7 @@ void IRAM_ATTR call_start_cpu0(void)
 
 #if CONFIG_IDF_TARGET_ESP32S3
     extern int _rodata_reserved_end;
-    uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1)/MMU_PAGE_SIZE)*sizeof(uint32_t);
+    uint32_t cache_mmu_drom_size = (((uint32_t)&_rodata_reserved_end - rodata_reserved_start_align + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE) * sizeof(uint32_t);
 #endif
 
     Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
@@ -475,12 +479,12 @@ void IRAM_ATTR call_start_cpu0(void)
 #endif
 
     extern void Cache_Set_IDROM_MMU_Info(uint32_t instr_page_num, uint32_t rodata_page_num, uint32_t rodata_start, uint32_t rodata_end, int i_off, int ro_off);
-    Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size/sizeof(uint32_t), \
-                            cache_mmu_drom_size/sizeof(uint32_t), \
-                            (uint32_t)&_rodata_reserved_start, \
-                            (uint32_t)&_rodata_reserved_end, \
-                            s_instr_flash2spiram_off, \
-                            s_rodata_flash2spiram_off);
+    Cache_Set_IDROM_MMU_Info(cache_mmu_irom_size / sizeof(uint32_t), \
+                             cache_mmu_drom_size / sizeof(uint32_t), \
+                             (uint32_t)&_rodata_reserved_start, \
+                             (uint32_t)&_rodata_reserved_end, \
+                             s_instr_flash2spiram_off, \
+                             s_rodata_flash2spiram_off);
 #endif
 
 #if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP || \
@@ -548,32 +552,41 @@ void IRAM_ATTR call_start_cpu0(void)
 
     esp_cache_err_int_init();
 
-#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
+#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && !CONFIG_ESP_SYSTEM_MEMPROT_TEST
     // 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 CONFIG_IDF_TARGET_ESP32S2
     if (esp_memprot_is_locked_any()) {
+#else
+    bool is_locked = false;
+    if (esp_mprot_is_conf_locked_any(&is_locked) != ESP_OK || is_locked) {
+#endif
         ESP_EARLY_LOGE(TAG, "Memprot feature locked after the system reset! Potential safety corruption, rebooting.");
         esp_restart_noos_dig();
     }
+
+    //default configuration of PMS Memprot
     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);
+#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK
+    memp_err = esp_memprot_set_prot(PANIC_HNDL_ON, MEMPROT_LOCK, NULL);
 #else
-    esp_memprot_set_prot(true, false, NULL);
+    memp_err = esp_memprot_set_prot(PANIC_HNDL_ON, MEMPROT_UNLOCK, NULL);
 #endif
+#else //CONFIG_IDF_TARGET_ESP32S2 specific end
+    esp_memp_config_t memp_cfg = ESP_MEMPROT_DEFAULT_CONFIG();
+#if !CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK
+    memp_cfg.lock_feature = false;
 #endif
+    memp_err = esp_mprot_set_prot(&memp_cfg);
+#endif //other IDF_TARGETS end
+
     if (memp_err != ESP_OK) {
-        ESP_EARLY_LOGE(TAG, "Failed to set Memprot feature (error 0x%08X), rebooting.", memp_err);
+        ESP_EARLY_LOGE(TAG, "Failed to set Memprot feature (0x%08X: %s), rebooting.", memp_err, esp_err_to_name(memp_err));
         esp_restart_noos_dig();
     }
-#endif
+#endif //CONFIG_ESP_SYSTEM_MEMPROT_FEATURE && !CONFIG_ESP_SYSTEM_MEMPROT_TEST
 
     // Read the application binary image header. This will also decrypt the header if the image is encrypted.
     __attribute__((unused)) esp_image_header_t fhdr = {0};

+ 16 - 7
components/esp_system/port/panic_handler.c

@@ -25,14 +25,14 @@
 
 #if CONFIG_IDF_TARGET_ESP32
 #include "esp32/dport_access.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
+#endif
+
+#if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
+#if CONFIG_IDF_TARGET_ESP32S2
 #include "esp32s2/memprot.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/memprot.h"
-#elif CONFIG_IDF_TARGET_ESP32C3
-#include "esp32c3/memprot.h"
-#elif CONFIG_IDF_TARGET_ESP32H2
-#include "esp32h2/memprot.h"
+#else
+#include "esp_memprot.h"
+#endif
 #endif
 
 #include "esp_private/panic_internal.h"
@@ -229,9 +229,18 @@ void __attribute__((noreturn)) panic_restart(void)
     }
 #endif
 #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE
+#if CONFIG_IDF_TARGET_ESP32S2
     if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) {
         digital_reset_needed = true;
     }
+#else
+    bool is_on = false;
+    if (esp_mprot_is_intr_ena_any(&is_on) != ESP_OK || is_on) {
+        digital_reset_needed = true;
+    } else if (esp_mprot_is_conf_locked_any(&is_on) != ESP_OK || is_on) {
+        digital_reset_needed = true;
+    }
+#endif
 #endif
     if (digital_reset_needed) {
         esp_restart_noos_dig();

+ 418 - 171
components/hal/esp32c3/include/hal/memprot_ll.h

@@ -1,59 +1,22 @@
-// 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.
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #pragma once
 
-#include "soc/sensitive_reg.h"
 #include "soc/cache_memory.h"
-#include "hal/assert.h"
+#include "soc/memprot_defs.h"
+#include "hal/memprot_types.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 /* ******************************************************************************************************
- * *** GLOBALS ***
- * NOTE: in this version, all the configurations apply only to WORLD_0
- */
-
-#define IRAM_SRAM_START             0x4037C000
-#define DRAM_SRAM_START             0x3FC7C000
-
-/* ICache size is fixed to 16KB on ESP32-C3 */
-#ifndef ICACHE_SIZE
-#define ICACHE_SIZE                 0x4000
-#endif
-
-#ifndef I_D_SRAM_SEGMENT_SIZE
-#define I_D_SRAM_SEGMENT_SIZE       0x20000
-#endif
-
-#define I_D_SPLIT_LINE_SHIFT        0x9
-#define I_D_FAULT_ADDR_SHIFT        0x2
-
-typedef union {
-    struct {
-        uint32_t cat0       : 2;
-        uint32_t cat1       : 2;
-        uint32_t cat2       : 2;
-        uint32_t res0       : 8;
-        uint32_t splitaddr  : 8;
-        uint32_t res1       : 10;
-    };
-    uint32_t val;
-} constrain_reg_fields_t;
-
+ * *** COMMON ***
+ * ******************************************************************************************************/
 static inline void memprot_ll_set_iram0_dram0_split_line_lock(void)
 {
     REG_WRITE(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG, 1);
@@ -64,7 +27,7 @@ static inline bool memprot_ll_get_iram0_dram0_split_line_lock(void)
     return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_0_REG) == 1;
 }
 
-static inline void* memprot_ll_get_split_addr_from_reg(uint32_t regval, uint32_t base)
+static inline void *memprot_ll_get_split_addr_from_reg(uint32_t regval, uint32_t base)
 {
     constrain_reg_fields_t reg_val;
     reg_val.val = regval;
@@ -85,43 +48,30 @@ static inline void* memprot_ll_get_split_addr_from_reg(uint32_t regval, uint32_t
 
 /* ******************************************************************************************************
  * *** IRAM0 ***
- */
-
-//16kB (CACHE)
-#define IRAM0_SRAM_LEVEL_0_LOW      IRAM_SRAM_START //0x40370000
-#define IRAM0_SRAM_LEVEL_0_HIGH     (IRAM0_SRAM_LEVEL_0_LOW + ICACHE_SIZE - 0x1) //0x4037FFFF
-
-//128kB (LEVEL 1)
-#define IRAM0_SRAM_LEVEL_1_LOW      (IRAM0_SRAM_LEVEL_0_HIGH + 0x1) //0x40380000
-#define IRAM0_SRAM_LEVEL_1_HIGH     (IRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x4039FFFF
-
-//128kB (LEVEL 2)
-#define IRAM0_SRAM_LEVEL_2_LOW      (IRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x403A0000
-#define IRAM0_SRAM_LEVEL_2_HIGH     (IRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403BFFFF
-
-//128kB (LEVEL 3)
-#define IRAM0_SRAM_LEVEL_3_LOW      (IRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x403C0000
-#define IRAM0_SRAM_LEVEL_3_HIGH     (IRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403DFFFF
-
-//permission bits
-#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R  0x1
-#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W  0x2
-#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F  0x4
-
+ * ******************************************************************************************************/
 static inline uint32_t memprot_ll_iram0_get_intr_source_num(void)
 {
     return ETS_CORE0_IRAM0_PMS_INTR_SOURCE;
 }
 
-
-///////////////////////////////////
-// IRAM0 - SPLIT LINES
-///////////////////////////////////
-
-static inline void memprot_ll_set_iram0_split_line(const void *line_addr, uint32_t sensitive_reg)
+/* ********************************
+ * IRAM0 - SPLIT LINES
+ *
+ * NOTES:
+ * 1. IRAM0/DRAM0 split-lines must be aligned to 512B boundaries (PMS module restriction)
+ * 2. split address must fall into appropriate IRAM0/DRAM0 region
+ */
+static inline memprot_ll_err_t memprot_ll_set_iram0_split_line(const void *line_addr, uint32_t sensitive_reg)
 {
     uint32_t addr = (uint32_t)line_addr;
-    HAL_ASSERT(addr >= IRAM0_SRAM_LEVEL_1_LOW && addr <= IRAM0_SRAM_LEVEL_3_HIGH);
+
+    if (addr < IRAM0_SRAM_LEVEL_1_LOW || addr > IRAM0_SRAM_LEVEL_3_HIGH) {
+        return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE;
+    }
+
+    if (addr % 0x200 != 0) {
+        return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED;
+    }
 
     uint32_t category[3] = {0};
     if (addr <= IRAM0_SRAM_LEVEL_1_HIGH) {
@@ -141,47 +91,61 @@ static inline void memprot_ll_set_iram0_split_line(const void *line_addr, uint32
         (category[2] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_2_S);
 
     uint32_t conf_addr = ((addr >> I_D_SPLIT_LINE_SHIFT) & SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_V) << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_S;
-
     uint32_t reg_cfg = conf_addr | category_bits;
 
     REG_WRITE(sensitive_reg, reg_cfg);
+
+    return MEMP_LL_OK;
 }
 
 /* can be both IRAM0/DRAM0 address */
-static inline void memprot_ll_set_iram0_split_line_main_I_D(const void *line_addr)
+static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_main_I_D(const void *line_addr)
 {
-    memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG);
+    return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG);
 }
 
-static inline void memprot_ll_set_iram0_split_line_I_0(const void *line_addr)
+static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_I_0(const void *line_addr)
 {
-    memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG);
+    return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG);
 }
 
-static inline void memprot_ll_set_iram0_split_line_I_1(const void *line_addr)
+static inline memprot_ll_err_t memprot_ll_set_iram0_split_line_I_1(const void *line_addr)
 {
-    memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG);
+    return memprot_ll_set_iram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG);
 }
 
-static inline void* memprot_ll_get_iram0_split_line_main_I_D(void)
+static inline uint32_t memprot_ll_get_iram0_split_line_main_I_D_cat(void)
+{
+    return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG) & 0x3F;
+}
+
+static inline uint32_t memprot_ll_get_iram0_split_line_I_0_cat(void)
+{
+    return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG) & 0x3F;
+}
+
+static inline uint32_t memprot_ll_get_iram0_split_line_I_1_cat(void)
+{
+    return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG) & 0x3F;
+}
+
+static inline void *memprot_ll_get_iram0_split_line_main_I_D(void)
 {
     return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_1_REG), SOC_DIRAM_IRAM_LOW);
 }
 
-static inline void* memprot_ll_get_iram0_split_line_I_0(void)
+static inline void *memprot_ll_get_iram0_split_line_I_0(void)
 {
     return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_2_REG), SOC_DIRAM_IRAM_LOW);
 }
 
-static inline void* memprot_ll_get_iram0_split_line_I_1(void)
+static inline void *memprot_ll_get_iram0_split_line_I_1(void)
 {
     return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_3_REG), SOC_DIRAM_IRAM_LOW);
 }
 
-
 ///////////////////////////////////
 // IRAM0 - PMS CONFIGURATION
-///////////////////////////////////
 
 // lock
 static inline void memprot_ll_iram0_set_pms_lock(void)
@@ -198,14 +162,14 @@ static inline bool memprot_ll_iram0_get_pms_lock(void)
 static inline uint32_t memprot_ll_iram0_set_permissions(bool r, bool w, bool x)
 {
     uint32_t permissions = 0;
-    if ( r ) {
-        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
+    if (r) {
+        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R;
     }
-    if ( w ) {
-        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
+    if (w) {
+        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W;
     }
-    if ( x ) {
-        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F;
+    if (x) {
+        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F;
     }
 
     return permissions;
@@ -233,39 +197,38 @@ static inline void memprot_ll_iram0_set_pms_area_3(bool r, bool w, bool x)
 
 static inline void memprot_ll_iram0_get_permissions(uint32_t perms, bool *r, bool *w, bool *x)
 {
-    *r = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
-    *w = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
-    *x = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_F;
+    *r = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R;
+    *w = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W;
+    *x = perms & SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F;
 }
 
 static inline void memprot_ll_iram0_get_pms_area_0(bool *r, bool *w, bool *x)
 {
     uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0);
-    memprot_ll_iram0_get_permissions( permissions, r, w, x);
+    memprot_ll_iram0_get_permissions(permissions, r, w, x);
 }
 
 static inline void memprot_ll_iram0_get_pms_area_1(bool *r, bool *w, bool *x)
 {
     uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1);
-    memprot_ll_iram0_get_permissions( permissions, r, w, x);
+    memprot_ll_iram0_get_permissions(permissions, r, w, x);
 }
 
 static inline void memprot_ll_iram0_get_pms_area_2(bool *r, bool *w, bool *x)
 {
     uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2);
-    memprot_ll_iram0_get_permissions( permissions, r, w, x);
+    memprot_ll_iram0_get_permissions(permissions, r, w, x);
 }
 
 static inline void memprot_ll_iram0_get_pms_area_3(bool *r, bool *w, bool *x)
 {
     uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_2_REG, SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3);
-    memprot_ll_iram0_get_permissions( permissions, r, w, x);
+    memprot_ll_iram0_get_permissions(permissions, r, w, x);
 }
 
 
 ///////////////////////////////////
 // IRAM0 - MONITOR
-///////////////////////////////////
 
 // lock
 static inline void memprot_ll_iram0_set_monitor_lock(void)
@@ -281,26 +244,31 @@ static inline bool memprot_ll_iram0_get_monitor_lock(void)
 // interrupt enable/clear
 static inline void memprot_ll_iram0_set_monitor_en(bool enable)
 {
-    if ( enable ) {
-        REG_SET_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN );
+    if (enable) {
+        REG_SET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN);
     } else {
-        REG_CLR_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN );
+        REG_CLR_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN);
     }
 }
 
+static inline bool memprot_ll_iram0_get_monitor_intrclr(void)
+{
+    return REG_GET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR) > 0;
+}
+
 static inline bool memprot_ll_iram0_get_monitor_en(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN ) == 1;
+    return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_EN) == 1;
 }
 
-static inline void memprot_ll_iram0_clear_monitor_intr(void)
+static inline void memprot_ll_iram0_set_monitor_intrclr(void)
 {
-    REG_SET_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR );
+    REG_SET_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR);
 }
 
-static inline void memprot_ll_iram0_reset_clear_monitor_intr(void)
+static inline void memprot_ll_iram0_reset_monitor_intrclr(void)
 {
-    REG_CLR_BIT( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR );
+    REG_CLR_BIT(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_CLR);
 }
 
 static inline uint32_t memprot_ll_iram0_get_monitor_enable_register(void)
@@ -308,31 +276,31 @@ static inline uint32_t memprot_ll_iram0_get_monitor_enable_register(void)
     return REG_READ(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_1_REG);
 }
 
-// // permission violation status
+// permission violation status
 static inline uint32_t memprot_ll_iram0_get_monitor_status_intr(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR );
+    return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_INTR);
 }
 
 static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_wr(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR );
+    return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WR);
 }
 
 static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_loadstore(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE );
+    return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_LOADSTORE);
 }
 
 static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_world(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD );
+    return REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD);
 }
 
-static inline uint32_t memprot_ll_iram0_get_monitor_status_fault_addr(void)
+static inline intptr_t memprot_ll_iram0_get_monitor_status_fault_addr(void)
 {
-    uint32_t addr = REG_GET_FIELD( SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR );
-    return addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + IRAM0_ADDRESS_LOW : 0;
+    uint32_t addr = REG_GET_FIELD(SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_IRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR);
+    return (intptr_t)(addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + IRAM0_ADDRESS_LOW : 0);
 }
 
 static inline uint32_t memprot_ll_iram0_get_monitor_status_register(void)
@@ -342,43 +310,309 @@ static inline uint32_t memprot_ll_iram0_get_monitor_status_register(void)
 
 
 /* ******************************************************************************************************
- * *** DRAM0 ***
+ * *** RTC_FAST ***
  */
 
-//cache not available from DRAM (!)
-#define DRAM0_SRAM_LEVEL_0_LOW      DRAM_SRAM_START //0x3FC7C000
-#define DRAM0_SRAM_LEVEL_0_HIGH     (DRAM0_SRAM_LEVEL_0_LOW + ICACHE_SIZE - 0x1) //0x3FC7FFFF
+static inline uint32_t memprot_ll_rtcfast_get_intr_source_num(void)
+{
+    return ETS_CORE0_PIF_PMS_INTR_SOURCE;
+}
+
+//shared PIF PMS lock
+//!!!: use after ALL the constraints have been set
+static inline void memprot_ll_set_pif_constraint_lock(void)
+{
+    REG_WRITE(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_0_REG, 1);
+}
+
+static inline bool memprot_ll_get_pif_constraint_lock(void)
+{
+    return REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_0_REG) == 1;
+}
+
+static inline uint32_t memprot_ll_rtcfast_get_splitaddr_register(void)
+{
+    return REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG);
+}
+
+/* ********************************
+ * IRAM0 RTCFAST - SPLIT LINES
+ *
+ * NOTES:
+ * 1. there is only 1 split line for RTCFAST/WORLD
+ * 2. RTCFAST split-line must be aligned to 4B boundaries (PMS stores 11 bits of 13-bit offset in 8kB RTCFAST region)
+ * 3. RTCFAST has weird section structure (text -> dummy (!) -> force -> data) - .dummy section seems to have wrong mapping (it doesn't fall inline with .rtctext)
+ */
+static inline memprot_ll_err_t memprot_ll_set_rtcfast_split_line(const void *line_addr, memprot_ll_world_t world)
+{
+    uint32_t addr = (uint32_t)line_addr;
+    uint32_t mask;
+
+    if (addr < SOC_RTC_IRAM_LOW || addr >= SOC_RTC_IRAM_HIGH) {
+        return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE;
+    }
+
+    if (addr % 0x4 != 0) {
+        return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED;
+    }
+
+    switch (world) {
+    case MEMP_LL_WORLD_0:
+        mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M;
+        break;
+    case MEMP_LL_WORLD_1:
+        mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M;
+        break;
+    default:
+        return MEMP_LL_ERR_WORLD_INVALID;
+    }
+
+    //offset bits to store are the same width for both worlds -> using SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_V
+    CLEAR_PERI_REG_MASK(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG, mask);
+    REG_SET_BITS(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG, mask, (addr >> 2) & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_V);
+
+    return MEMP_LL_OK;
+}
+
+static inline memprot_ll_err_t memprot_ll_get_rtcfast_split_line(memprot_ll_world_t world, void **line_addr)
+{
+    uint32_t reg_addr = REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_9_REG);
+    uint32_t mask = 0;
+    uint32_t shift = 0;
+
+    switch (world) {
+    case MEMP_LL_WORLD_0:
+        mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_M;
+        shift = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_0_S;
+        break;
+    case MEMP_LL_WORLD_1:
+        mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_M;
+        shift = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_SPLTADDR_WORLD_1_S;
+        break;
+    default:
+        return MEMP_LL_ERR_WORLD_INVALID;
+    }
+
+    *line_addr = (void *)((((reg_addr & mask) >> shift) << 2) + SOC_RTC_IRAM_LOW);
+
+    return MEMP_LL_OK;
+}
+
+///////////////////////////////////
+// RTC_FAST - PMS CONFIGURATION
+
+// permission settings
+static inline uint32_t memprot_ll_rtcfast_set_permissions(bool r, bool w, bool x)
+{
+    uint32_t permissions = 0;
+    if (r) {
+        permissions |= SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R;
+    }
+    if (w) {
+        permissions |= SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W;
+    }
+    if (x) {
+        permissions |= SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F;
+    }
+
+    return permissions;
+}
+
+static inline memprot_ll_err_t memprot_ll_rtcfast_set_pms_area(bool r, bool w, bool x, memprot_ll_world_t world, memprot_ll_area_t area)
+{
+    uint32_t bits = 0;
+    uint32_t mask = 0;
+
+    switch (world) {
+    case MEMP_LL_WORLD_0: {
+        switch (area) {
+        case MEMP_LL_AREA_LOW:
+            bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_S;
+            mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L_M;
+            break;
+        case MEMP_LL_AREA_HIGH:
+            bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H_S;
+            mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H_M;
+            break;
+        default:
+            return MEMP_LL_ERR_AREA_INVALID;
+        }
+    } break;
+    case MEMP_LL_WORLD_1: {
+        switch (area) {
+        case MEMP_LL_AREA_LOW:
+            bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_S;
+            mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L_M;
+            break;
+        case MEMP_LL_AREA_HIGH:
+            bits = memprot_ll_rtcfast_set_permissions(r, w, x) << SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_S;
+            mask = SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H_M;
+            break;
+        default:
+            return MEMP_LL_ERR_AREA_INVALID;
+        }
+    } break;
+    default:
+        return MEMP_LL_ERR_WORLD_INVALID;
+    }
+
+    CLEAR_PERI_REG_MASK(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, mask);
+    REG_SET_BITS(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, bits, mask);
+
+    return MEMP_LL_OK;
+}
+
+static inline void memprot_ll_rtcfast_get_permissions(uint32_t perms, bool *r, bool *w, bool *x)
+{
+    *r = perms & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R;
+    *w = perms & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W;
+    *x = perms & SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F;
+}
+
+static inline memprot_ll_err_t memprot_ll_rtcfast_get_pms_area(bool *r, bool *w, bool *x, memprot_ll_world_t world, memprot_ll_area_t area)
+{
+    uint32_t permissions = 0;
+
+    switch (world) {
+    case MEMP_LL_WORLD_0: {
+        switch (area) {
+        case MEMP_LL_AREA_LOW:
+            permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_L);
+            break;
+        case MEMP_LL_AREA_HIGH:
+            permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_0_H);
+            break;
+        default:
+            return MEMP_LL_ERR_AREA_INVALID;
+        }
+    } break;
+    case MEMP_LL_WORLD_1: {
+        switch (area) {
+        case MEMP_LL_AREA_LOW:
+            permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_L);
+            break;
+        case MEMP_LL_AREA_HIGH:
+            permissions = REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG, SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_1_H);
+            break;
+        default:
+            return MEMP_LL_ERR_AREA_INVALID;
+        }
+    } break;
+    default:
+        return MEMP_LL_ERR_WORLD_INVALID;
+    }
+
+    memprot_ll_rtcfast_get_permissions(permissions, r, w, x);
+
+    return MEMP_LL_OK;
+}
+
+static inline uint32_t memprot_ll_rtcfast_get_permission_register(void)
+{
+    return REG_READ(SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_10_REG);
+}
+
+///////////////////////////////////
+// RTC_FAST - MONITOR
+
+// lock
+static inline void memprot_ll_rtcfast_set_monitor_lock(void)
+{
+    REG_WRITE(SENSITIVE_CORE_0_PIF_PMS_MONITOR_0_REG, 1);
+}
+
+static inline bool memprot_ll_rtcfast_get_monitor_lock(void)
+{
+    return REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_0_REG) == 1;
+}
+
+// interrupt enable/clear
+static inline void memprot_ll_rtcfast_set_monitor_en(bool enable)
+{
+    if (enable) {
+        REG_SET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN);
+    } else {
+        REG_CLR_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN);
+    }
+}
+
+static inline bool memprot_ll_rtcfast_get_monitor_en(void)
+{
+    return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_EN) > 0;
+}
+
+static inline bool memprot_ll_rtcfast_get_monitor_intrclr(void)
+{
+    return REG_GET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR) > 0;
+}
+
+static inline void memprot_ll_rtcfast_set_monitor_intrclr(void)
+{
+    REG_SET_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR);
+}
 
-//128kB
-#define DRAM0_SRAM_LEVEL_1_LOW      (DRAM0_SRAM_LEVEL_0_HIGH + 0x1) //0x3FC80000
-#define DRAM0_SRAM_LEVEL_1_HIGH     (DRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FC9FFFF
+static inline void memprot_ll_rtcfast_reset_monitor_intrclr(void)
+{
+    REG_CLR_BIT(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_CLR);
+}
 
-//128kB
-#define DRAM0_SRAM_LEVEL_2_LOW      (DRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x3FCA0000
-#define DRAM0_SRAM_LEVEL_2_HIGH     (DRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCBFFFF
+static inline uint32_t memprot_ll_rtcfast_get_monitor_register(void)
+{
+    return REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_1_REG);
+}
+
+// permission violation status
+static inline uint32_t memprot_ll_rtcfast_get_monitor_status_intr(void)
+{
+    return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_INTR);
+}
+
+static inline intptr_t memprot_ll_rtcfast_get_monitor_status_fault_addr(void)
+{
+    //full address SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HADDR
+    return (intptr_t)REG_READ(SENSITIVE_CORE_0_PIF_PMS_MONITOR_3_REG);
+}
+
+static inline uint32_t memprot_ll_rtcfast_get_monitor_status_fault_world(void)
+{
+    return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWORLD);
+}
+
+static inline uint32_t memprot_ll_rtcfast_get_monitor_status_fault_loadstore(void)
+{
+    return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HPORT_0);
+}
 
-//128kB
-#define DRAM0_SRAM_LEVEL_3_LOW      (DRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x3FCC0000
-#define DRAM0_SRAM_LEVEL_3_HIGH     (DRAM0_SRAM_LEVEL_3_LOW  + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCDFFFF
+static inline uint32_t memprot_ll_rtcfast_get_monitor_status_fault_wr(void)
+{
+    return REG_GET_FIELD(SENSITIVE_CORE_0_PIF_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_PIF_PMS_MONITOR_VIOLATE_STATUS_HWRITE);
+}
 
-#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W  0x2
-#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R  0x1
 
+/* ******************************************************************************************************
+ * *** DRAM0 ***
+ * ******************************************************************************************************/
 
 static inline uint32_t memprot_ll_dram0_get_intr_source_num(void)
 {
     return ETS_CORE0_DRAM0_PMS_INTR_SOURCE;
 }
 
-
 ///////////////////////////////////
 // DRAM0 - SPLIT LINES
-///////////////////////////////////
 
-static inline void memprot_ll_set_dram0_split_line(const void *line_addr, uint32_t sensitive_reg)
+static inline memprot_ll_err_t memprot_ll_set_dram0_split_line(const void *line_addr, uint32_t sensitive_reg)
 {
     uint32_t addr = (uint32_t)line_addr;
-    HAL_ASSERT(addr >= DRAM0_SRAM_LEVEL_1_LOW && addr <= DRAM0_SRAM_LEVEL_3_HIGH);
+
+    //sanity check: split address required above unified mgmt region & 32bit aligned
+    if (addr < DRAM0_SRAM_LEVEL_1_LOW || addr > DRAM0_SRAM_LEVEL_3_HIGH) {
+        return MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE;
+    }
+    //split-line must be divisible by 512 (PMS module restriction)
+    if (addr % 0x200 != 0) {
+        return MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED;
+    }
 
     uint32_t category[3] = {0};
     if (addr <= DRAM0_SRAM_LEVEL_1_HIGH) {
@@ -398,36 +632,45 @@ static inline void memprot_ll_set_dram0_split_line(const void *line_addr, uint32
         (category[2] << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_CATEGORY_2_S);
 
     uint32_t conf_addr = ((addr >> I_D_SPLIT_LINE_SHIFT) & SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_V) << SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SRAM_SPLITADDR_S;
-
     uint32_t reg_cfg = conf_addr | category_bits;
 
     REG_WRITE(sensitive_reg, reg_cfg);
+
+    return MEMP_LL_OK;
 }
 
-static inline void memprot_ll_set_dram0_split_line_D_0(const void *line_addr)
+static inline memprot_ll_err_t memprot_ll_set_dram0_split_line_D_0(const void *line_addr)
 {
-    memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG);
+    return memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG);
 }
 
-static inline void memprot_ll_set_dram0_split_line_D_1(const void *line_addr)
+static inline memprot_ll_err_t memprot_ll_set_dram0_split_line_D_1(const void *line_addr)
 {
-    memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG);
+    return memprot_ll_set_dram0_split_line(line_addr, SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG);
 }
 
-static inline void* memprot_ll_get_dram0_split_line_D_0(void)
+static inline void *memprot_ll_get_dram0_split_line_D_0(void)
 {
     return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG), SOC_DIRAM_DRAM_LOW);
 }
 
-static inline void* memprot_ll_get_dram0_split_line_D_1(void)
+static inline void *memprot_ll_get_dram0_split_line_D_1(void)
 {
     return memprot_ll_get_split_addr_from_reg(REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG), SOC_DIRAM_DRAM_LOW);
 }
 
+static inline uint32_t memprot_ll_get_dram0_split_line_D_0_cat(void)
+{
+    return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_4_REG) & 0x3F;
+}
+
+static inline uint32_t memprot_ll_get_dram0_split_line_D_1_cat(void)
+{
+    return REG_READ(SENSITIVE_CORE_X_IRAM0_DRAM0_DMA_SPLIT_LINE_CONSTRAIN_5_REG) & 0x3F;
+}
 
 ///////////////////////////////////
 // DRAM0 - PMS CONFIGURATION
-///////////////////////////////////
 
 // lock
 static inline void memprot_ll_dram0_set_pms_lock(void)
@@ -444,11 +687,11 @@ static inline bool memprot_ll_dram0_get_pms_lock(void)
 static inline uint32_t memprot_ll_dram0_set_permissions(bool r, bool w)
 {
     uint32_t permissions = 0;
-    if ( r ) {
-        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
+    if (r) {
+        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R;
     }
-    if ( w ) {
-        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
+    if (w) {
+        permissions |= SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W;
     }
 
     return permissions;
@@ -476,37 +719,36 @@ static inline void memprot_ll_dram0_set_pms_area_3(bool r, bool w)
 
 static inline void memprot_ll_dram0_get_permissions(uint32_t perms, bool *r, bool *w )
 {
-    *r = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_R;
-    *w = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_W;
+    *r = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R;
+    *w = perms & SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W;
 }
 
 static inline void memprot_ll_dram0_get_pms_area_0(bool *r, bool *w)
 {
     uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_0);
-    memprot_ll_dram0_get_permissions( permissions, r, w);
+    memprot_ll_dram0_get_permissions(permissions, r, w);
 }
 
 static inline void memprot_ll_dram0_get_pms_area_1(bool *r, bool *w)
 {
     uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_1);
-    memprot_ll_dram0_get_permissions( permissions, r, w);
+    memprot_ll_dram0_get_permissions(permissions, r, w);
 }
 
 static inline void memprot_ll_dram0_get_pms_area_2(bool *r, bool *w)
 {
     uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_2);
-    memprot_ll_dram0_get_permissions( permissions, r, w);
+    memprot_ll_dram0_get_permissions(permissions, r, w);
 }
 
 static inline void memprot_ll_dram0_get_pms_area_3(bool *r, bool *w)
 {
     uint32_t permissions = REG_GET_FIELD(SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_1_REG, SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_0_PMS_3);
-    memprot_ll_dram0_get_permissions( permissions, r, w);
+    memprot_ll_dram0_get_permissions(permissions, r, w);
 }
 
 ///////////////////////////////////
 // DRAM0 - MONITOR
-///////////////////////////////////
 
 // lock
 static inline void memprot_ll_dram0_set_monitor_lock(void)
@@ -522,26 +764,31 @@ static inline bool memprot_ll_dram0_get_monitor_lock(void)
 // interrupt enable/clear
 static inline void memprot_ll_dram0_set_monitor_en(bool enable)
 {
-    if ( enable ) {
-        REG_SET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN );
+    if (enable) {
+        REG_SET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN);
     } else {
-        REG_CLR_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN );
+        REG_CLR_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN);
     }
 }
 
 static inline bool memprot_ll_dram0_get_monitor_en(void)
 {
-    return REG_GET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN ) == 1;
+    return REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_EN) > 0;
+}
+
+static inline void memprot_ll_dram0_set_monitor_intrclr(void)
+{
+    REG_SET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR);
 }
 
-static inline void memprot_ll_dram0_clear_monitor_intr(void)
+static inline void memprot_ll_dram0_reset_monitor_intrclr(void)
 {
-    REG_SET_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR );
+    REG_CLR_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR);
 }
 
-static inline void memprot_ll_dram0_reset_clear_monitor_intr(void)
+static inline bool memprot_ll_dram0_get_monitor_intrclr(void)
 {
-    REG_CLR_BIT( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR );
+    return REG_GET_BIT(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_1_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_CLR) > 0;
 }
 
 static inline uint32_t memprot_ll_dram0_get_monitor_enable_register(void)
@@ -552,33 +799,33 @@ static inline uint32_t memprot_ll_dram0_get_monitor_enable_register(void)
 // permission violation status
 static inline uint32_t memprot_ll_dram0_get_monitor_status_intr(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR );
+    return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_INTR);
 }
 
 static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_lock(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK );
+    return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_LOCK);
 }
 
 static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_world(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD );
+    return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WORLD);
 }
 
 static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_addr(void)
 {
-    uint32_t addr = REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR );
+    uint32_t addr = REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_ADDR);
     return addr > 0 ? (addr << I_D_FAULT_ADDR_SHIFT) + DRAM0_ADDRESS_LOW : 0;
 }
 
 static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_wr(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR );
+    return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_3_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_WR);
 }
 
 static inline uint32_t memprot_ll_dram0_get_monitor_status_fault_byte_en(void)
 {
-    return REG_GET_FIELD( SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN );
+    return REG_GET_FIELD(SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_2_REG, SENSITIVE_CORE_0_DRAM0_PMS_MONITOR_VIOLATE_STATUS_BYTEEN);
 }
 
 static inline uint32_t memprot_ll_dram0_get_monitor_status_register_1(void)

+ 30 - 15
components/hal/include/hal/memprot_types.h

@@ -1,16 +1,8 @@
-// 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.
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 #pragma once
 
@@ -25,11 +17,34 @@ extern "C" {
 typedef enum {
     MEMP_LL_OK = 0,
     MEMP_LL_FAIL = 1,
-    MEMP_LL_ERR_SPLIT_ADDR_INVALID = 2,
+    MEMP_LL_ERR_SPLIT_ADDR_OUT_OF_RANGE = 2,
+    MEMP_LL_ERR_SPLIT_ADDR_INVALID = 2,         /* temporary duplicate for S2 builds */
     MEMP_LL_ERR_SPLIT_ADDR_UNALIGNED = 3,
-    MEMP_LL_ERR_UNI_BLOCK_INVALID = 4
+    MEMP_LL_ERR_UNI_BLOCK_INVALID = 4,
+    MEMP_LL_ERR_AREA_INVALID = 5,
+    MEMP_LL_ERR_WORLD_INVALID = 6
 } memprot_ll_err_t;
 
+/**
+ * @brief Memprot LL PMS World IDs
+ *
+ */
+typedef enum {
+    MEMP_LL_WORLD_NONE = 0x00,
+    MEMP_LL_WORLD_0 = 0x01,
+    MEMP_LL_WORLD_1 = 0x10
+} memprot_ll_world_t;
+
+/**
+ * @brief Memprot LL PMS Area IDs
+ *
+ */
+typedef enum {
+    MEMP_LL_AREA_NONE = 0,
+    MEMP_LL_AREA_LOW = 1,
+    MEMP_LL_AREA_HIGH = 2
+} memprot_ll_area_t;
+
 #ifdef __cplusplus
 }
 #endif

+ 100 - 0
components/soc/esp32c3/include/soc/memprot_defs.h

@@ -0,0 +1,100 @@
+/*
+ * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include "soc/soc.h"
+#include "soc/sensitive_reg.h"
+#include "esp32c3/rom/cache.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef union {
+    struct {
+        uint32_t cat0       : 2;
+        uint32_t cat1       : 2;
+        uint32_t cat2       : 2;
+        uint32_t res0       : 8;
+        uint32_t splitaddr  : 8;
+        uint32_t res1       : 10;
+    };
+    uint32_t val;
+} constrain_reg_fields_t;
+
+#ifndef I_D_SRAM_SEGMENT_SIZE
+#define I_D_SRAM_SEGMENT_SIZE       0x20000
+#endif
+
+#define I_D_SPLIT_LINE_SHIFT        0x9
+#define I_D_FAULT_ADDR_SHIFT        0x2
+
+#define DRAM_SRAM_START             0x3FC7C000
+
+#ifndef MAP_DRAM_TO_IRAM
+#define MAP_DRAM_TO_IRAM(addr)       (addr - DRAM_SRAM_START + SOC_IRAM_LOW)
+#endif
+
+#ifndef MAP_IRAM_TO_DRAM
+#define MAP_IRAM_TO_DRAM(addr)       (addr - SOC_IRAM_LOW + DRAM_SRAM_START)
+#endif
+
+//IRAM0
+
+//16kB (ICACHE)
+#define IRAM0_SRAM_LEVEL_0_LOW      SOC_IRAM_LOW //0x40370000
+#define IRAM0_SRAM_LEVEL_0_HIGH     (IRAM0_SRAM_LEVEL_0_LOW + CACHE_MEMORY_IBANK_SIZE - 0x1) //0x4037FFFF
+
+//128kB (LEVEL 1)
+#define IRAM0_SRAM_LEVEL_1_LOW      (IRAM0_SRAM_LEVEL_0_HIGH + 0x1) //0x40380000
+#define IRAM0_SRAM_LEVEL_1_HIGH     (IRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x4039FFFF
+
+//128kB (LEVEL 2)
+#define IRAM0_SRAM_LEVEL_2_LOW      (IRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x403A0000
+#define IRAM0_SRAM_LEVEL_2_HIGH     (IRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403BFFFF
+
+//128kB (LEVEL 3)
+#define IRAM0_SRAM_LEVEL_3_LOW      (IRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x403C0000
+#define IRAM0_SRAM_LEVEL_3_HIGH     (IRAM0_SRAM_LEVEL_3_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x403DFFFF
+
+//permission bits
+#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R  0x1
+#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W  0x2
+#define SENSITIVE_CORE_X_IRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_F  0x4
+
+//DRAM0
+
+//16kB ICACHE not available from DRAM0
+
+//128kB (LEVEL 1)
+#define DRAM0_SRAM_LEVEL_1_LOW      SOC_DRAM_LOW //0x3FC80000
+#define DRAM0_SRAM_LEVEL_1_HIGH     (DRAM0_SRAM_LEVEL_1_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FC9FFFF
+
+//128kB (LEVEL 2)
+#define DRAM0_SRAM_LEVEL_2_LOW      (DRAM0_SRAM_LEVEL_1_HIGH + 0x1) //0x3FCA0000
+#define DRAM0_SRAM_LEVEL_2_HIGH     (DRAM0_SRAM_LEVEL_2_LOW + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCBFFFF
+
+//128kB (LEVEL 3)
+#define DRAM0_SRAM_LEVEL_3_LOW      (DRAM0_SRAM_LEVEL_2_HIGH + 0x1) //0x3FCC0000
+#define DRAM0_SRAM_LEVEL_3_HIGH     (DRAM0_SRAM_LEVEL_3_LOW  + I_D_SRAM_SEGMENT_SIZE - 0x1) //0x3FCDFFFF
+
+#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_R  0x1
+#define SENSITIVE_CORE_X_DRAM0_PMS_CONSTRAIN_SRAM_WORLD_X_W  0x2
+
+//RTC FAST
+
+//permission bits
+#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_W  0x1
+#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_R  0x2
+#define SENSITIVE_CORE_0_PIF_PMS_CONSTRAIN_RTCFAST_WORLD_X_F  0x4
+
+#define AREA_LOW                                                0
+#define AREA_HIGH                                               1
+
+#ifdef __cplusplus
+}
+#endif

+ 0 - 4
tools/ci/check_copyright_ignore.txt

@@ -457,7 +457,6 @@ components/esp_common/include/esp_assert.h
 components/esp_common/include/esp_bit_defs.h
 components/esp_common/include/esp_check.h
 components/esp_common/include/esp_compiler.h
-components/esp_common/include/esp_err.h
 components/esp_common/include/esp_types.h
 components/esp_common/src/esp_err_to_name.c
 components/esp_common/test/test_attr.c
@@ -1020,7 +1019,6 @@ components/hal/esp32c3/include/hal/hmac_hal.h
 components/hal/esp32c3/include/hal/hmac_ll.h
 components/hal/esp32c3/include/hal/i2c_ll.h
 components/hal/esp32c3/include/hal/interrupt_controller_ll.h
-components/hal/esp32c3/include/hal/memprot_ll.h
 components/hal/esp32c3/include/hal/mpu_ll.h
 components/hal/esp32c3/include/hal/rtc_cntl_ll.h
 components/hal/esp32c3/include/hal/rwdt_ll.h
@@ -1145,7 +1143,6 @@ components/hal/include/hal/interrupt_controller_types.h
 components/hal/include/hal/ledc_hal.h
 components/hal/include/hal/mcpwm_hal.h
 components/hal/include/hal/mcpwm_types.h
-components/hal/include/hal/memprot_types.h
 components/hal/include/hal/mpu_hal.h
 components/hal/include/hal/mpu_types.h
 components/hal/include/hal/pcnt_hal.h
@@ -3235,7 +3232,6 @@ tools/test_apps/system/gdb_loadable_elf/main/hello_world_main.c
 tools/test_apps/system/longjmp_test/app_test.py
 tools/test_apps/system/longjmp_test/main/hello_world_main.c
 tools/test_apps/system/memprot/app_test.py
-tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c
 tools/test_apps/system/memprot/main/esp32c3/test_panic.c
 tools/test_apps/system/memprot/main/esp32s2/test_memprot_main.c
 tools/test_apps/system/memprot/main/esp32s2/test_panic.c

+ 1 - 1
tools/test_apps/system/memprot/README.md

@@ -1,2 +1,2 @@
-| Supported Targets | ESP32-S2 | ESP32-C3 |
+| Supported Targets | ESP32-C3 | ESP32-S2 |
 | ----------------- | -------- | -------- |

+ 2 - 1
tools/test_apps/system/memprot/app_test.py

@@ -15,7 +15,8 @@ MEM_TEST_S2 = [
 
 MEM_TEST_C3 = [
     ['IRAM0_SRAM', 'WRX'],
-    ['DRAM0_SRAM', 'WR']
+    ['DRAM0_SRAM', 'WR'],
+    ['IRAM0_RTCFAST', 'WRX'],
 ]
 
 

+ 2 - 3
tools/test_apps/system/memprot/main/Kconfig.projbuild

@@ -1,4 +1,3 @@
-config ESP_SYSTEM_MEMPROT_IRAM_TESTBUF
+config ESP_SYSTEM_MEMPROT_TEST
     bool
-    default y if IDF_TARGET_ESP32C3
-    default n if !IDF_TARGET_ESP32C3
+    default y

+ 371 - 175
tools/test_apps/system/memprot/main/esp32c3/test_memprot_main.c

@@ -1,9 +1,17 @@
-/* MEMPROT (PMS) testing code */
+/*
+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #include <stdio.h>
+#include <string.h>
 #include "sdkconfig.h"
-#include "esp32c3/memprot.h"
+#include "esp_attr.h"
+#include "hal/memprot_types.h"
+#include "soc/memprot_defs.h"
+#include "esp_private/esp_memprot_internal.h"
+#include "esp_memprot.h"
 #include "esp_rom_sys.h"
-#include <string.h>
 
 /**
  * ESP32C3 MEMORY PROTECTION MODULE TEST
@@ -11,11 +19,13 @@
  *
  * In order to safely test all the memprot features, this test application uses memprot default settings
  * plus proprietary testing buffers:
- *      - iram_test_buffer (.iram_end_test, 1kB) - all low region operations
- *      - dram_test_buffer (.dram0.data, 1kB) - all high region operations
+ *      - s_iram_test_buffer (.iram_end_test, 1kB) - all IRAM/DRAM low region operations, test-only section
+ *      - s_dram_test_buffer (.dram0.data, 1kB) - all IRAM/DRAM high region operations, standard section
+ *      - s_rtc_text_test_buffer (.rtc_text_end_test, 1kB) - all RTCFAST low region operations, test-only section
+ *      - s_rtc_data_test_buffer (.rtc.data, 1kB) - all RTCFAST high region operations, standard section
  * Testing addresses are set to the middle of the testing buffers:
- *      - test_ptr_low = iram_test_buffer + 0x200
- *      - test_ptr_high = dram_test_buffer + 0x200
+ *      - test_ptr_low = (s_iram_test_buffer | s_rtc_text_test_buffer) + 0x200
+ *      - test_ptr_high = (s_dram_test_buffer | s_rtc_data_test_buffer) + 0x200
  * Each operation is tested at both low & high region addresses.
  * Each test result checked against expected status of PMS violation interrupt status and
  * against expected value stored in the memory tested (where applicable)
@@ -28,19 +38,31 @@
  *                              |                 DRam0_PMS_0                 |
  *                              |                                             |
  *                              |                                             |
- *                              | - - - - - - - iram_test_buffer - - - - - - -|   IRam0_line1_Split_addr
+ *                              | - - - - - - - s_iram_test_buffer - - - - - -|   IRam0_line1_Split_addr
  * DRam0_DMA_line0_Split_addr   |               -- test_ptr_low --            |             =
  *               =              ===============================================   IRam0_line0_Split_addr
  * DRam0_DMA_line1_Split_addr   |                                             |             =
- *                              | - - - - - - - dram_test_buffer - - - - - - -|   IRam0_DRam0_Split_addr (main I/D)
+ *                              | - - - - - - - s_dram_test_buffer - - - - - --|   IRam0_DRam0_Split_addr (main I/D)
  *                              |              -- test_ptr_high --            |
  *                              | - - - - - - - - - - - - - - - - - - - - - - |
  *                              |                                             |
  *                              |   DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3   |
  *                              |                 IRam0_PMS_3                 |
+ *                              |                                             |
+ *                              |                     ...                     |
+ *                              |                                             |
+ *                              ===============================================   SOC_RTC_IRAM_LOW (0x50000000)
+ *                              |               -- test_ptr_low --            |
+ *                              | - - - - - - s_rtc_text_test_buffer - - - - -|   RtcFast_Split_addr (_rtc_text_end)
+ *                              |               -- .rtc.dummy --              |      (UNUSED - PADDING)
+ *           8 kB               | - - - - - - - - - - - - - - - - - - - - - - |   [_rtc_dummy_end = _rtc_force_fast_start]
+ *                              |             -- .rtc.force_fast --           |      (NOT USED IN THIS TEST)
+ *                              | - - - - - - s_rtc_data_test_buffer - - - - -|   [_rtc_force_fast_end = _rtc_data_start]
+ *                              |              -- test_ptr_high --            |
+ *                              | - - - - - - - - - - - - - - - - - - - - - - |
+ *                              ===============================================   SOC_RTC_IRAM_HIGH (0x50001FFF)
+ *                              |                                             |
  *                              -----------------------------------------------
- *
- * For more details on PMS memprot settings see 'esp_memprot_set_prot_int' function in esp32c3/memprot.h
  */
 
 
@@ -48,345 +70,519 @@
     slli a0,a0,0x1
     ret
  */
-static uint8_t fnc_buff[] = { 0x06, 0x05, 0x82, 0x80 };
+static uint8_t s_fnc_buff[] = { 0x06, 0x05, 0x82, 0x80 };
 typedef int (*fnc_ptr)(int);
 
 #define SRAM_TEST_BUFFER_SIZE      0x400
 #define SRAM_TEST_OFFSET           0x200
 
-static uint8_t __attribute__((section(".iram_end_test"))) iram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
-static uint8_t dram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
+static uint8_t __attribute__((section(".iram_end_test"))) s_iram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
+static uint8_t __attribute__((section(".rtc_text_end_test"))) s_rtc_text_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
+static uint8_t RTC_DATA_ATTR s_rtc_data_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
+static uint8_t s_dram_test_buffer[SRAM_TEST_BUFFER_SIZE] = {0};
 extern volatile bool g_override_illegal_instruction;
 
-
-static void *test_memprot_addr_low(mem_type_prot_t mem_type)
+static void *test_mprot_addr_low(esp_mprot_mem_t mem_type)
 {
-    switch ( mem_type ) {
-        case MEMPROT_IRAM0_SRAM:
-            return (void*)((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET);
-        case MEMPROT_DRAM0_SRAM:
-            return (void*)MAP_IRAM_TO_DRAM((uint32_t)iram_test_buffer + SRAM_TEST_OFFSET);
-        default:
-            abort();
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        return (void *)((uint32_t)s_iram_test_buffer + SRAM_TEST_OFFSET);
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        return (void *)MAP_IRAM_TO_DRAM((uint32_t)s_iram_test_buffer + SRAM_TEST_OFFSET);
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        return (void *)((uint32_t)s_rtc_text_test_buffer + SRAM_TEST_OFFSET);
+    default:
+        abort();
     }
 }
 
-static void *test_memprot_addr_high(mem_type_prot_t mem_type)
+static void *test_mprot_addr_high(esp_mprot_mem_t mem_type)
 {
-    switch ( mem_type ) {
-        case MEMPROT_IRAM0_SRAM:
-            return (void*)MAP_DRAM_TO_IRAM((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET);
-        case MEMPROT_DRAM0_SRAM:
-            return (void*)((uint32_t)dram_test_buffer + SRAM_TEST_OFFSET);
-        default:
-            abort();
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        return (void *)MAP_DRAM_TO_IRAM((uint32_t)s_dram_test_buffer + SRAM_TEST_OFFSET);
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        return (void *)((uint32_t)s_dram_test_buffer + SRAM_TEST_OFFSET);
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        return (void *)((uint32_t)s_rtc_data_test_buffer + SRAM_TEST_OFFSET);
+    default:
+        abort();
     }
 }
 
-static void __attribute__((unused)) dump_status_register(mem_type_prot_t mem_type)
+static void __attribute__((unused)) test_mprot_dump_status_register(esp_mprot_mem_t mem_type)
 {
-    char operation = 0;
+    esp_rom_printf("FAULT [");
 
-    // IRAM fault: check instruction-fetch flag
-    if ( mem_type == MEMPROT_IRAM0_SRAM ) {
-        if ( esp_memprot_get_violate_loadstore(mem_type) ) {
-            operation = 'X';
-        }
+    void *addr;
+    esp_err_t err = esp_mprot_get_violate_addr(mem_type, &addr, NULL);
+    if (err == ESP_OK) {
+        esp_rom_printf("fault addr: 0x%08X,", (uint32_t)addr);
+    } else {
+        esp_rom_printf("fault addr: N/A (%s),", esp_err_to_name(err));
     }
 
-    // W/R - common
-    if ( operation == 0 ) {
-        operation = esp_memprot_get_violate_wr(mem_type) == MEMPROT_PMS_OP_WRITE ? 'W' : 'R';
+    esp_mprot_pms_world_t world;
+    err = esp_mprot_get_violate_world(mem_type, &world, NULL);
+    if (err == ESP_OK) {
+        esp_rom_printf(" world: %s,", esp_mprot_pms_world_to_str(world));
+    } else {
+        esp_rom_printf(" world: N/A (%s),", esp_err_to_name(err));
     }
 
-    esp_rom_printf(
-        " FAULT [ world: %u, fault addr: 0x%08X, operation: %c",
-        esp_memprot_get_violate_world(mem_type),
-        esp_memprot_get_violate_addr(mem_type),
-        operation
-    );
+    uint32_t oper;
+    err = esp_mprot_get_violate_operation(mem_type, &oper, NULL);
+    if (err == ESP_OK) {
+        esp_rom_printf(" operation: %s", esp_mprot_oper_type_to_str(oper));
+    } else {
+        esp_rom_printf(" operation: N/A (%s)", esp_err_to_name(err));
+    }
 
     // DRAM/DMA fault: check byte-enables
-    if ( mem_type == MEMPROT_DRAM0_SRAM ) {
-        esp_rom_printf( ", byte en: 0x%08X", esp_memprot_get_violate_byte_en(mem_type) );
+    if (mem_type == MEMPROT_TYPE_DRAM0_SRAM) {
+        uint32_t byteen;
+        err = esp_mprot_get_violate_byte_enables(mem_type, &byteen, NULL);
+        if (err == ESP_OK) {
+            esp_rom_printf(", byte en: 0x%08X", byteen);
+        } else {
+            esp_rom_printf(", byte en: N/A (%s)", esp_err_to_name(err));
+        }
     }
 
-    esp_rom_printf( " ]\n" );
+    esp_rom_printf( "]\n" );
 }
 
-static void check_test_result(mem_type_prot_t mem_type, bool expected_status)
+static void test_mprot_check_test_result(esp_mprot_mem_t mem_type, bool expected_status)
 {
-    bool test_result =
-            expected_status ?
-            !esp_memprot_get_violate_intr_on(mem_type) :
-            esp_memprot_get_violate_intr_on(mem_type);
+    esp_memp_intr_source_t memp_intr;
+    esp_err_t err = esp_mprot_get_active_intr(&memp_intr);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_get_active_intr() failed (%s) - test_mprot_check_test_result\n", esp_err_to_name(err));
+        return;
+    }
 
-    if ( test_result ) {
+    bool intr_on = memp_intr.mem_type == mem_type && memp_intr.core > -1;
+    bool test_result = expected_status ? !intr_on : intr_on;
+
+    if (test_result) {
         esp_rom_printf("OK\n");
     } else {
-        dump_status_register(mem_type);
+        test_mprot_dump_status_register(mem_type);
+    }
+}
+
+static void test_mprot_clear_all_interrupts(void)
+{
+    esp_err_t err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM, NULL);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_SRAM) failed (%s) - test_mprot_clear_all_interrupts\n", esp_err_to_name(err));
+    }
+    err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM, NULL);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_monitor_clear_intr(MEMPROT_TYPE_DRAM0_SRAM) failed (%s) - test_mprot_clear_all_interrupts\n", esp_err_to_name(err));
+    }
+    err = esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST, NULL);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_monitor_clear_intr(MEMPROT_TYPE_IRAM0_RTCFAST) failed (%s) - test_mprot_clear_all_interrupts\n", esp_err_to_name(err));
     }
 }
 
-static void test_memprot_get_permissions(bool low, mem_type_prot_t mem_type, bool *read, bool *write, bool *exec )
+static void test_mprot_get_permissions(bool low, esp_mprot_mem_t mem_type, bool *read, bool *write, bool *exec )
 {
-    bool _r, _w, _x;
-    pms_area_t area = MEMPROT_PMS_AREA_NONE;
+    esp_mprot_pms_area_t area;
 
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM:
-        area = low ? MEMPROT_IRAM0_PMS_AREA_2 : MEMPROT_IRAM0_PMS_AREA_3;
-        esp_memprot_iram_get_pms_area(area, &_r, &_w, &_x);
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM:
+        area = low ? MEMPROT_PMS_AREA_IRAM0_2 : MEMPROT_PMS_AREA_IRAM0_3;
+        break;
+    case MEMPROT_TYPE_DRAM0_SRAM:
+        area = low ? MEMPROT_PMS_AREA_DRAM0_0 : MEMPROT_PMS_AREA_DRAM0_1;
         break;
-    case MEMPROT_DRAM0_SRAM:
-        area = low ? MEMPROT_DRAM0_PMS_AREA_0 : MEMPROT_DRAM0_PMS_AREA_1;
-        esp_memprot_dram_get_pms_area(area, &_r, &_w);
+    case MEMPROT_TYPE_IRAM0_RTCFAST:
+        area = low ? MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO : MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI;
         break;
     default:
         abort();
     }
 
-    if ( read ) {
-        *read = _r;
+    uint32_t flags;
+    esp_err_t err = esp_mprot_get_pms_area(area, &flags);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_get_pms_area() failed (%s) - test_mprot_get_permissions\n", esp_err_to_name(err));
+        return;
+    }
+
+    if (read) {
+        *read = flags & MEMPROT_OP_READ;
     }
-    if ( write ) {
-        *write = _w;
+    if (write) {
+        *write = flags & MEMPROT_OP_WRITE;
     }
-    if ( exec ) {
-        *exec = _x;
+    if (exec) {
+        *exec = flags & MEMPROT_OP_EXEC;
     }
 }
 
-static void test_memprot_set_permissions(bool low, mem_type_prot_t mem_type, bool read, bool write, bool *exec)
+static void test_mprot_set_permissions(bool low, esp_mprot_mem_t mem_type, bool read, bool write, bool *exec)
 {
-    switch ( mem_type ) {
-    case MEMPROT_IRAM0_SRAM: {
-        bool _ex;
-        if (!exec) {
-            test_memprot_get_permissions( low, mem_type, NULL, NULL, &_ex);
-            exec = &_ex;
+    esp_err_t err;
+    uint32_t flags = 0;
+    if (read) {
+        flags |= MEMPROT_OP_READ;
+    }
+    if (write) {
+        flags |= MEMPROT_OP_WRITE;
+    }
+    if (exec && *exec) {
+        flags |= MEMPROT_OP_EXEC;
+    }
+
+    switch (mem_type) {
+    case MEMPROT_TYPE_IRAM0_SRAM: {
+        if (low) {
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_0, flags)) != ESP_OK) {
+                break;
+            }
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_1, flags)) != ESP_OK) {
+                break;
+            }
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_2, flags)) != ESP_OK) {
+                break;
+            }
+        } else {
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_3, flags)) != ESP_OK) {
+                break;
+            }
         }
+    }
+    break;
+    case MEMPROT_TYPE_DRAM0_SRAM: {
         if (low) {
-            esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, read, write, *exec);
-            esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, read, write, *exec);
-            esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, read, write, *exec);
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_0, flags)) != ESP_OK) {
+                break;
+            }
         } else {
-            esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, read, write, *exec);
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_1, flags)) != ESP_OK) {
+                break;
+            }
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_2, flags)) != ESP_OK) {
+                break;
+            }
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_DRAM0_3, flags)) != ESP_OK) {
+                break;
+            }
         }
     }
     break;
-    case MEMPROT_DRAM0_SRAM: {
+    case MEMPROT_TYPE_IRAM0_RTCFAST: {
         if (low) {
-            esp_memprot_dram_set_pms_area( MEMPROT_DRAM0_PMS_AREA_0, read, write );
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_LO, flags)) != ESP_OK) {
+                break;
+            }
         } else {
-            esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, read, write);
-            esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, read, write);
-            esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, read, write);
+            if ((err = esp_mprot_set_pms_area(MEMPROT_PMS_AREA_IRAM0_RTCFAST_HI, flags)) != ESP_OK) {
+                break;
+            }
         }
     }
     break;
     default:
         abort();
     }
+
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_pms_area() failed (%s) - test_mprot_set_permissions\n", esp_err_to_name(err));
+    }
 }
 
-static void test_memprot_read(mem_type_prot_t mem_type)
+static void test_mprot_read(esp_mprot_mem_t mem_type)
 {
-    //get current READ & WRITE permission settings
+    test_mprot_clear_all_interrupts();
+
+    //get current permission settings
     bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high;
-    test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL);
-    test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL);
+    bool is_exec_mem = mem_type & MEMPROT_TYPE_IRAM0_ANY;
+    test_mprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
+    test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
 
     //get testing pointers for low & high regions
-    volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type);
-    volatile uint32_t *ptr_high = test_memprot_addr_high(mem_type);
+    volatile uint32_t *ptr_low = test_mprot_addr_low(mem_type);
+    volatile uint32_t *ptr_high = test_mprot_addr_high(mem_type);
     const uint32_t test_val = 100;
 
     //temporarily allow WRITE for setting the test values
-    esp_memprot_set_monitor_en(mem_type, false);
-    test_memprot_set_permissions(true, mem_type, read_perm_low, true, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL);
-    test_memprot_set_permissions(false, mem_type, read_perm_high, true, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL);
+    esp_err_t err = esp_mprot_set_monitor_en(mem_type, false);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_read\n", esp_err_to_name(err));
+        return;
+    }
+
+    test_mprot_set_permissions(true, mem_type, read_perm_low, true, is_exec_mem ? &exec_perm_low : NULL);
+    test_mprot_set_permissions(false, mem_type, read_perm_high, true, is_exec_mem ? &exec_perm_high : NULL);
 
+    //save testing values
     *ptr_low = test_val;
     *ptr_high = test_val + 1;
 
-    test_memprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_low : NULL);
-    test_memprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, mem_type == MEMPROT_IRAM0_SRAM ? &exec_perm_high : NULL);
-    esp_memprot_set_monitor_en(mem_type, true);
+    //restore current PMS settings
+    test_mprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
+    test_mprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
+
+    //reenable monitoring
+    err = esp_mprot_set_monitor_en(mem_type, true);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_read\n", esp_err_to_name(err));
+        return;
+    }
 
     //perform READ test in low region
-    esp_rom_printf("%s read low: ", esp_memprot_mem_type_to_str(mem_type));
-    esp_memprot_monitor_clear_intr(mem_type);
+    esp_rom_printf("%s read low: ", esp_mprot_mem_type_to_str(mem_type));
+    err = esp_mprot_monitor_clear_intr(mem_type, NULL);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_read\n", esp_err_to_name(err));
+        return;
+    }
 
     volatile uint32_t val = *ptr_low;
 
-    if ( read_perm_low && val != test_val ) {
+    if (read_perm_low && val != test_val) {
         esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val );
-        dump_status_register(mem_type);
+        test_mprot_dump_status_register(mem_type);
     } else {
-        check_test_result(mem_type, read_perm_low);
+        test_mprot_check_test_result(mem_type, read_perm_low);
     }
 
     //perform READ in high region
-    esp_rom_printf("%s read high: ", esp_memprot_mem_type_to_str(mem_type));
-    esp_memprot_monitor_clear_intr(mem_type);
+    esp_rom_printf("%s read high: ", esp_mprot_mem_type_to_str(mem_type));
+    err = esp_mprot_monitor_clear_intr(mem_type, NULL);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_read\n", esp_err_to_name(err));
+        return;
+    }
 
     val = *ptr_high;
 
-    if ( read_perm_high && val != (test_val + 1) ) {
+    if (read_perm_high && val != (test_val + 1)) {
         esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
-        dump_status_register(mem_type);
+        test_mprot_dump_status_register(mem_type);
     } else {
-        check_test_result(mem_type, read_perm_high);
+        test_mprot_check_test_result(mem_type, read_perm_high);
     }
 }
 
-static void test_memprot_write(mem_type_prot_t mem_type)
+static void test_mprot_write(esp_mprot_mem_t mem_type)
 {
+    test_mprot_clear_all_interrupts();
+
     //get current READ & WRITE permission settings
-    bool write_perm_low, write_perm_high, read_perm_low, read_perm_high;
-    test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, NULL);
-    test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, NULL);
+    bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high;
+    bool is_exec_mem = mem_type & MEMPROT_TYPE_IRAM0_ANY;
+    test_mprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
+    test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
 
     //ensure READ enabled
-    esp_memprot_set_monitor_en(mem_type, false);
-    test_memprot_set_permissions(true, mem_type, true, write_perm_low, NULL);
-    test_memprot_set_permissions(false, mem_type, true, write_perm_high, NULL);
-    esp_memprot_set_monitor_en(mem_type, true);
+    esp_err_t err = esp_mprot_set_monitor_en(mem_type, false);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
+        return;
+    }
 
-    //get testing pointers for low & high regions
-    volatile uint32_t *ptr_low = test_memprot_addr_low(mem_type);
-    volatile uint32_t *ptr_high = test_memprot_addr_high(mem_type);
+    test_mprot_set_permissions(true, mem_type, true, write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
+    test_mprot_set_permissions(false, mem_type, true, write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
+
+    err = esp_mprot_set_monitor_en(mem_type, true);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
+        return;
+    }
+
+    volatile uint32_t *ptr_low = test_mprot_addr_low(mem_type);
+    volatile uint32_t *ptr_high = test_mprot_addr_high(mem_type);
     const uint32_t test_val = 10;
 
     //perform WRITE in low region
-    esp_rom_printf("%s write low: ", esp_memprot_mem_type_to_str(mem_type));
-    esp_memprot_monitor_clear_intr(mem_type);
+    esp_rom_printf("%s write low: ", esp_mprot_mem_type_to_str(mem_type));
+    err = esp_mprot_monitor_clear_intr(mem_type, NULL);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
+        return;
+    }
 
     volatile uint32_t val = 0;
     *ptr_low = test_val;
     val = *ptr_low;
 
-    if ( val != test_val && write_perm_low ) {
+    if (val != test_val && write_perm_low) {
         esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
-        dump_status_register(mem_type);
+        test_mprot_dump_status_register(mem_type);
     } else {
-        check_test_result(mem_type, write_perm_low);
+        test_mprot_check_test_result(mem_type, write_perm_low);
     }
 
     //perform WRITE in high region
-    esp_rom_printf("%s write high: ", esp_memprot_mem_type_to_str(mem_type));
-    esp_memprot_monitor_clear_intr(mem_type);
+    esp_rom_printf("%s write high: ", esp_mprot_mem_type_to_str(mem_type));
+    err = esp_mprot_monitor_clear_intr(mem_type, NULL);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
+        return;
+    }
 
     val = 0;
     *ptr_high = test_val + 1;
     val = *ptr_high;
 
-    if ( val != (test_val + 1) && write_perm_high ) {
+    if (val != (test_val + 1) && write_perm_high) {
         esp_rom_printf( "UNEXPECTED VALUE 0x%08X -", val);
-        dump_status_register(mem_type);
+        test_mprot_dump_status_register(mem_type);
     } else {
-        check_test_result(mem_type, write_perm_high);
+        test_mprot_check_test_result(mem_type, write_perm_high);
     }
 
     //restore original permissions
-    esp_memprot_set_monitor_en(mem_type, false);
-    test_memprot_set_permissions(true, mem_type, true, read_perm_low, NULL);
-    test_memprot_set_permissions(false, mem_type, true, read_perm_high, NULL);
-    esp_memprot_set_monitor_en(mem_type, true);
+    err = esp_mprot_set_monitor_en(mem_type, false);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
+        return;
+    }
+
+    test_mprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, is_exec_mem ? &exec_perm_low : NULL);
+    test_mprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, is_exec_mem ? &exec_perm_high : NULL);
+
+    err = esp_mprot_set_monitor_en(mem_type, true);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_write\n", esp_err_to_name(err));
+        return;
+    }
 }
 
-static void test_memprot_exec(mem_type_prot_t mem_type)
+static void test_mprot_exec(esp_mprot_mem_t mem_type)
 {
-    if ( mem_type != MEMPROT_IRAM0_SRAM ) {
+    if (!(mem_type & MEMPROT_TYPE_IRAM0_ANY)) {
         esp_rom_printf("Error: EXEC test available only for IRAM access.\n" );
         return;
     }
 
+    test_mprot_clear_all_interrupts();
+
     bool write_perm_low, write_perm_high, read_perm_low, read_perm_high, exec_perm_low, exec_perm_high;
 
     //temporarily enable READ/WRITE
-    test_memprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, &exec_perm_low);
-    test_memprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, &exec_perm_high);
-    esp_memprot_set_monitor_en(mem_type, false);
-    test_memprot_set_permissions(true, mem_type, true, true, &exec_perm_low);
-    test_memprot_set_permissions(false, mem_type, true, true, &exec_perm_high);
-    esp_memprot_set_monitor_en(mem_type, true);
+    test_mprot_get_permissions(true, mem_type, &read_perm_low, &write_perm_low, &exec_perm_low);
+    test_mprot_get_permissions(false, mem_type, &read_perm_high, &write_perm_high, &exec_perm_high);
+    esp_err_t err = esp_mprot_set_monitor_en(mem_type, false);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
+        return;
+    }
+    test_mprot_set_permissions(true, mem_type, true, true, &exec_perm_low);
+    test_mprot_set_permissions(false, mem_type, true, true, &exec_perm_high);
+    err = esp_mprot_set_monitor_en(mem_type, true);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
+        return;
+    }
 
     //get testing pointers for low & high regions, zero 8B slot
-    void *fnc_ptr_low = test_memprot_addr_low(mem_type);
-    void *fnc_ptr_high = test_memprot_addr_high(mem_type);
-    memset( fnc_ptr_low, 0, 8);
-    memset( fnc_ptr_high, 0, 8);
+    void *fnc_ptr_low = test_mprot_addr_low(mem_type);
+    void *fnc_ptr_high = test_mprot_addr_high(mem_type);
+    memset(fnc_ptr_low, 0, 8);
+    memset(fnc_ptr_high, 0, 8);
 
     //inject the code to both low & high segments
-    memcpy( (void *)fnc_ptr_low, (const void *)fnc_buff, sizeof(fnc_buff) );
-    memcpy( (void *)fnc_ptr_high, (const void *)fnc_buff, sizeof(fnc_buff) );
+    memcpy((void *)fnc_ptr_low, (const void *)s_fnc_buff, sizeof(s_fnc_buff));
+    memcpy((void *)fnc_ptr_high, (const void *)s_fnc_buff, sizeof(s_fnc_buff));
 
     uint32_t res = 0;
 
     //LOW REGION: clear the intr flag & try to execute the code injected
-    esp_rom_printf("%s exec low: ", esp_memprot_mem_type_to_str(mem_type));
-    esp_memprot_monitor_clear_intr(mem_type);
+    esp_rom_printf("%s exec low: ", esp_mprot_mem_type_to_str(mem_type));
+    err = esp_mprot_monitor_clear_intr(mem_type, NULL);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
+        return;
+    }
 
     fnc_ptr fnc = (fnc_ptr)fnc_ptr_low;
 
     g_override_illegal_instruction = true;
-    res = fnc( 5 );
+    res = fnc(5);
     g_override_illegal_instruction = false;
 
     //check results
     bool fnc_call_ok = res == 10;
-    if ( fnc_call_ok ) {
-        check_test_result(mem_type, exec_perm_low);
+    if (fnc_call_ok) {
+        test_mprot_check_test_result(mem_type, exec_perm_low);
     } else {
-        if ( !exec_perm_low ) {
-            check_test_result(mem_type, false);
+        if (!exec_perm_low) {
+            test_mprot_check_test_result(mem_type, false);
         } else {
             esp_rom_printf(" FAULT [injected code not executed]\n");
         }
     }
 
     //HIGH REGION: clear the intr-on flag & try to execute the code injected
-    esp_rom_printf("%s exec high: ", esp_memprot_mem_type_to_str(mem_type));
-    esp_memprot_monitor_clear_intr(mem_type);
+    esp_rom_printf("%s exec high: ", esp_mprot_mem_type_to_str(mem_type));
+    err = esp_mprot_monitor_clear_intr(mem_type, NULL);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_monitor_clear_intr() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
+        return;
+    }
 
     fnc = (fnc_ptr)fnc_ptr_high;
 
     g_override_illegal_instruction = true;
-    res = fnc( 6 );
+    res = fnc(6);
     g_override_illegal_instruction = false;
 
     fnc_call_ok = res == 12;
-    if ( fnc_call_ok ) {
-        check_test_result(mem_type, exec_perm_high);
+    if (fnc_call_ok) {
+        test_mprot_check_test_result(mem_type, exec_perm_high);
     } else {
-        if ( !exec_perm_high ) {
-            check_test_result(mem_type, false);
+        if (!exec_perm_high) {
+            test_mprot_check_test_result(mem_type, false);
         } else {
             esp_rom_printf(" FAULT [injected code not executed]\n");
         }
     }
 
     //restore original permissions
-    esp_memprot_set_monitor_en(mem_type, false);
-    test_memprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, &exec_perm_low);
-    test_memprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, &exec_perm_high);
-    esp_memprot_set_monitor_en(mem_type, true);
+    err = esp_mprot_set_monitor_en(mem_type, false);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
+        return;
+    }
+    test_mprot_set_permissions(true, mem_type, read_perm_low, write_perm_low, &exec_perm_low);
+    test_mprot_set_permissions(false, mem_type, read_perm_high, write_perm_high, &exec_perm_high);
+    err = esp_mprot_set_monitor_en(mem_type, true);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_monitor_en() failed (%s) - test_mprot_exec\n", esp_err_to_name(err));
+        return;
+    }
 }
 
-
 /* ********************************************************************************************
  * main test runner
  */
 void app_main(void)
 {
-    esp_memprot_set_prot_int(false, false, NULL, NULL);
+    esp_memp_config_t memp_cfg = ESP_MEMPROT_DEFAULT_CONFIG();
+    memp_cfg.invoke_panic_handler = false;
+    memp_cfg.lock_feature = false;
+
+    esp_err_t err = esp_mprot_set_prot(&memp_cfg);
+    if (err != ESP_OK) {
+        esp_rom_printf("Error: esp_mprot_set_prot() failed (%s) - app_main\n", esp_err_to_name(err));
+        return;
+    }
+
+    test_mprot_read(MEMPROT_TYPE_IRAM0_SRAM);
+    test_mprot_write(MEMPROT_TYPE_IRAM0_SRAM);
+    test_mprot_exec(MEMPROT_TYPE_IRAM0_SRAM);
 
-    test_memprot_read(MEMPROT_IRAM0_SRAM);
-    test_memprot_write(MEMPROT_IRAM0_SRAM);
-    test_memprot_exec(MEMPROT_IRAM0_SRAM);
+    test_mprot_read(MEMPROT_TYPE_DRAM0_SRAM);
+    test_mprot_write(MEMPROT_TYPE_DRAM0_SRAM);
 
-    test_memprot_read(MEMPROT_DRAM0_SRAM);
-    test_memprot_write(MEMPROT_DRAM0_SRAM);
+    test_mprot_read(MEMPROT_TYPE_IRAM0_RTCFAST);
+    test_mprot_write(MEMPROT_TYPE_IRAM0_RTCFAST);
+    test_mprot_exec(MEMPROT_TYPE_IRAM0_RTCFAST);
 }

+ 0 - 1
tools/test_apps/system/memprot/sdkconfig.ci

@@ -1 +0,0 @@
-CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n

+ 3 - 0
tools/test_apps/system/memprot/sdkconfig.defaults

@@ -0,0 +1,3 @@
+CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y
+CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=n
+CONFIG_ESP_SYSTEM_MEMPROT_TEST=y