Explorar o código

Merge branch 'feature/cpu_abstraction' into 'master'

CPU related operations abstraction

See merge request espressif/esp-idf!7301
Angus Gratton %!s(int64=5) %!d(string=hai) anos
pai
achega
04ccb84b83
Modificáronse 44 ficheiros con 1318 adicións e 314 borrados
  1. 1 0
      components/bootloader_support/CMakeLists.txt
  2. 24 0
      components/bootloader_support/include/bootloader_mem.h
  3. 48 0
      components/bootloader_support/src/bootloader_mem.c
  4. 4 4
      components/bootloader_support/src/esp32/bootloader_esp32.c
  5. 4 1
      components/bootloader_support/src/esp32s2/bootloader_esp32s2.c
  6. 5 4
      components/esp32/cpu_start.c
  7. 0 53
      components/esp32/panic.c
  8. 2 1
      components/esp32s2/cpu_start.c
  9. 0 61
      components/esp32s2/panic.c
  10. 1 0
      components/esp_gdbstub/xtensa/gdbstub_xtensa.c
  11. 4 7
      components/freertos/include/freertos/portable.h
  12. 5 1
      components/soc/CMakeLists.txt
  13. 114 0
      components/soc/include/hal/cpu_hal.h
  14. 21 0
      components/soc/include/hal/cpu_types.h
  15. 36 0
      components/soc/include/hal/mpu_hal.h
  16. 33 0
      components/soc/include/hal/mpu_types.h
  17. 75 0
      components/soc/include/hal/soc_hal.h
  18. 6 54
      components/soc/include/soc/cpu.h
  19. 2 0
      components/soc/linker.lf
  20. 20 0
      components/soc/soc/esp32/include/soc/cpu_caps.h
  21. 21 0
      components/soc/soc/esp32/include/soc/mpu_caps.h
  22. 2 0
      components/soc/soc/esp32/include/soc/soc_caps.h
  23. 20 0
      components/soc/soc/esp32s2/include/soc/cpu_caps.h
  24. 21 0
      components/soc/soc/esp32s2/include/soc/mpu_caps.h
  25. 2 0
      components/soc/soc/esp32s2/include/soc/soc_caps.h
  26. 86 0
      components/soc/src/cpu_util.c
  27. 0 1
      components/soc/src/esp32/CMakeLists.txt
  28. 0 63
      components/soc/src/esp32/cpu_util.c
  29. 171 0
      components/soc/src/esp32/include/hal/cpu_ll.h
  30. 62 0
      components/soc/src/esp32/include/hal/mpu_ll.h
  31. 53 0
      components/soc/src/esp32/include/hal/soc_ll.h
  32. 0 1
      components/soc/src/esp32s2/CMakeLists.txt
  33. 0 63
      components/soc/src/esp32s2/cpu_util.c
  34. 167 0
      components/soc/src/esp32s2/include/hal/cpu_ll.h
  35. 62 0
      components/soc/src/esp32s2/include/hal/mpu_ll.h
  36. 31 0
      components/soc/src/esp32s2/include/hal/soc_ll.h
  37. 57 0
      components/soc/src/hal/cpu_hal.c
  38. 54 0
      components/soc/src/hal/mpu_hal.c
  39. 34 0
      components/soc/src/hal/soc_hal.c
  40. 21 0
      components/xtensa/esp32/include/xtensa/config/extreg.h
  41. 2 0
      components/xtensa/esp32/include/xtensa/config/specreg.h
  42. 21 0
      components/xtensa/esp32s2/include/xtensa/config/extreg.h
  43. 2 0
      components/xtensa/esp32s2/include/xtensa/config/specreg.h
  44. 24 0
      components/xtensa/include/xt_instr_macros.h

+ 1 - 0
components/bootloader_support/CMakeLists.txt

@@ -2,6 +2,7 @@ set(srcs
     "src/bootloader_clock.c"
     "src/bootloader_common.c"
     "src/bootloader_flash.c"
+    "src/bootloader_mem.c"
     "src/bootloader_random.c"
     "src/bootloader_utility.c"
     "src/esp_image_format.c"

+ 24 - 0
components/bootloader_support/include/bootloader_mem.h

@@ -0,0 +1,24 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void bootloader_init_mem(void);
+
+#ifdef __cplusplus
+}
+#endif

+ 48 - 0
components/bootloader_support/src/bootloader_mem.c

@@ -0,0 +1,48 @@
+// 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.
+
+#include <stdbool.h>
+
+#include "xtensa/config/core.h"
+#include "hal/cpu_hal.h"
+#include "hal/mpu_hal.h"
+#include "hal/mpu_types.h"
+#include "soc/mpu_caps.h"
+#include "bootloader_mem.h"
+#include "xt_instr_macros.h"
+#include "xtensa/config/specreg.h"
+
+static inline void cpu_configure_region_protection(void)
+{
+    /* Currently, the only supported chips esp32 and esp32s2
+     * have the same configuration. Move this to the port layer once
+     * more chips with different configurations are supported.
+     * 
+     * Both chips have the address space divided into 8 regions, 512MB each.
+     */
+    const int illegal_regions[] = {0, 4, 5, 6, 7}; // 0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000
+    for (int i = 0; i < sizeof(illegal_regions) / sizeof(illegal_regions[0]); ++i) {
+        mpu_hal_set_region_access(illegal_regions[i], MPU_REGION_ILLEGAL);
+    }
+
+    mpu_hal_set_region_access(1, MPU_REGION_RW); // 0x20000000
+}
+
+void bootloader_init_mem(void)
+{
+    cpu_hal_init_hwloop();
+
+    // protect memory region
+    cpu_configure_region_protection();
+}

+ 4 - 4
components/bootloader_support/src/esp32/bootloader_esp32.c

@@ -22,6 +22,7 @@
 #include "bootloader_clock.h"
 #include "bootloader_common.h"
 #include "bootloader_flash_config.h"
+#include "bootloader_mem.h"
 
 #include "soc/cpu.h"
 #include "soc/dport_reg.h"
@@ -426,10 +427,9 @@ void abort(void)
 esp_err_t bootloader_init(void)
 {
     esp_err_t ret = ESP_OK;
-    // workaround for tensilica erratum572
-    cpu_init_memctl();
-    // protect memory region
-    cpu_configure_region_protection();
+
+    bootloader_init_mem();
+
     // check that static RAM is after the stack
 #ifndef NDEBUG
     {

+ 4 - 1
components/bootloader_support/src/esp32s2/bootloader_esp32s2.c

@@ -25,6 +25,7 @@
 #include "bootloader_init.h"
 #include "bootloader_clock.h"
 #include "bootloader_flash_config.h"
+#include "bootloader_mem.h"
 
 #include "esp32s2/rom/cache.h"
 #include "esp32s2/rom/ets_sys.h"
@@ -349,7 +350,9 @@ esp_err_t bootloader_init(void)
     esp_err_t ret = ESP_OK;
     bootloader_super_wdt_auto_feed();
     // protect memory region
-    cpu_configure_region_protection();
+
+    bootloader_init_mem();
+
     /* check that static RAM is after the stack */
 #ifndef NDEBUG
     {

+ 5 - 4
components/esp32/cpu_start.c

@@ -69,6 +69,7 @@
 #include "esp_ota_ops.h"
 #include "esp_efuse.h"
 #include "bootloader_flash_config.h"
+#include "bootloader_mem.h"
 
 #ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
 #include "esp32/rom/efuse.h"
@@ -126,8 +127,8 @@ void IRAM_ATTR call_start_cpu0(void)
 #else
     RESET_REASON rst_reas[2];
 #endif
-    cpu_configure_region_protection();
-    cpu_init_memctl();
+
+    bootloader_init_mem();
 
     //Move exception vectors to IRAM
     asm volatile (\
@@ -277,8 +278,8 @@ void IRAM_ATTR call_start_cpu1(void)
                   ::"r"(&_init_start));
 
     ets_set_appcpu_boot_addr(0);
-    cpu_configure_region_protection();
-    cpu_init_memctl();
+
+    bootloader_init_mem();
 
 #if CONFIG_ESP_CONSOLE_UART_NONE
     ets_install_putc1(NULL);

+ 0 - 53
components/esp32/panic.c

@@ -664,59 +664,6 @@ void esp_set_breakpoint_if_jtag(void *fn)
     }
 }
 
-
-esp_err_t esp_set_watchpoint(int no, void *adr, int size, int flags)
-{
-    int x;
-    if (no < 0 || no > 1) {
-        return ESP_ERR_INVALID_ARG;
-    }
-    if (flags & (~0xC0000000)) {
-        return ESP_ERR_INVALID_ARG;
-    }
-    int dbreakc = 0x3F;
-    //We support watching 2^n byte values, from 1 to 64. Calculate the mask for that.
-    for (x = 0; x < 7; x++) {
-        if (size == (1 << x)) {
-            break;
-        }
-        dbreakc <<= 1;
-    }
-    if (x == 7) {
-        return ESP_ERR_INVALID_ARG;
-    }
-    //Mask mask and add in flags.
-    dbreakc = (dbreakc & 0x3f) | flags;
-
-    if (no == 0) {
-        asm volatile(
-            "wsr.dbreaka0 %0\n" \
-            "wsr.dbreakc0 %1\n" \
-            ::"r"(adr), "r"(dbreakc));
-    } else {
-        asm volatile(
-            "wsr.dbreaka1 %0\n" \
-            "wsr.dbreakc1 %1\n" \
-            ::"r"(adr), "r"(dbreakc));
-    }
-    return ESP_OK;
-}
-
-void esp_clear_watchpoint(int no)
-{
-    //Setting a dbreakc register to 0 makes it trigger on neither load nor store, effectively disabling it.
-    int dbreakc = 0;
-    if (no == 0) {
-        asm volatile(
-            "wsr.dbreakc0 %0\n" \
-            ::"r"(dbreakc));
-    } else {
-        asm volatile(
-            "wsr.dbreakc1 %0\n" \
-            ::"r"(dbreakc));
-    }
-}
-
 static void esp_error_check_failed_print(const char *msg, esp_err_t rc, const char *file, int line, const char *function, const char *expression)
 {
     ets_printf("%s failed: esp_err_t 0x%x", msg, rc);

+ 2 - 1
components/esp32s2/cpu_start.c

@@ -69,6 +69,7 @@
 #include "esp_private/pm_impl.h"
 #include "trax.h"
 #include "esp_efuse.h"
+#include "bootloader_mem.h"
 
 #define STRINGIFY(s) STRINGIFY2(s)
 #define STRINGIFY2(s) #s
@@ -110,7 +111,7 @@ void IRAM_ATTR call_start_cpu0(void)
 {
     RESET_REASON rst_reas;
 
-    cpu_configure_region_protection();
+    bootloader_init_mem();
 
     //Move exception vectors to IRAM
     asm volatile (\

+ 0 - 61
components/esp32s2/panic.c

@@ -195,10 +195,6 @@ static inline void disableAllWdts(void);
 
 //The fact that we've panic'ed probably means the other CPU is now running wild, possibly
 //messing up the serial output, so we stall it here.
-static void haltOtherCore(void)
-{
-    esp_cpu_stall( xPortGetCoreID() == 0 ? 1 : 0 );
-}
 
 
 static void setFirstBreakpoint(uint32_t pc)
@@ -324,7 +320,6 @@ void panicHandler(XtExcFrame *frame)
         esp_reset_reason_set_hint(ESP_RST_INT_WDT);
     }
 
-    haltOtherCore();
     panicPutStr("Guru Meditation Error: Core ");
     panicPutDec(core_id);
     panicPutStr(" panic'ed (");
@@ -394,7 +389,6 @@ void panicHandler(XtExcFrame *frame)
 
 void xt_unhandled_exception(XtExcFrame *frame)
 {
-    haltOtherCore();
     if (!abort_called) {
         panicPutStr("Guru Meditation Error: Core ");
         panicPutDec(xPortGetCoreID());
@@ -477,8 +471,6 @@ static void esp_panic_dig_reset(void)
     uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
     // switch to XTAL (otherwise we will keep running from the PLL)
     rtc_clk_cpu_freq_set_xtal();
-    // reset the digital part
-    esp_cpu_unstall(PRO_CPU_NUM);
     SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
     while (true) {
         ;
@@ -672,59 +664,6 @@ void esp_set_breakpoint_if_jtag(void *fn)
     }
 }
 
-
-esp_err_t esp_set_watchpoint(int no, void *adr, int size, int flags)
-{
-    int x;
-    if (no < 0 || no > 1) {
-        return ESP_ERR_INVALID_ARG;
-    }
-    if (flags & (~0xC0000000)) {
-        return ESP_ERR_INVALID_ARG;
-    }
-    int dbreakc = 0x3F;
-    //We support watching 2^n byte values, from 1 to 64. Calculate the mask for that.
-    for (x = 0; x < 7; x++) {
-        if (size == (1 << x)) {
-            break;
-        }
-        dbreakc <<= 1;
-    }
-    if (x == 7) {
-        return ESP_ERR_INVALID_ARG;
-    }
-    //Mask mask and add in flags.
-    dbreakc = (dbreakc & 0x3f) | flags;
-
-    if (no == 0) {
-        asm volatile(
-            "wsr.dbreaka0 %0\n" \
-            "wsr.dbreakc0 %1\n" \
-            ::"r"(adr), "r"(dbreakc));
-    } else {
-        asm volatile(
-            "wsr.dbreaka1 %0\n" \
-            "wsr.dbreakc1 %1\n" \
-            ::"r"(adr), "r"(dbreakc));
-    }
-    return ESP_OK;
-}
-
-void esp_clear_watchpoint(int no)
-{
-    //Setting a dbreakc register to 0 makes it trigger on neither load nor store, effectively disabling it.
-    int dbreakc = 0;
-    if (no == 0) {
-        asm volatile(
-            "wsr.dbreakc0 %0\n" \
-            ::"r"(dbreakc));
-    } else {
-        asm volatile(
-            "wsr.dbreakc1 %0\n" \
-            ::"r"(dbreakc));
-    }
-}
-
 void _esp_error_check_failed(esp_err_t rc, const char *file, int line, const char *function, const char *expression)
 {
     ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x", rc);

+ 1 - 0
components/esp_gdbstub/xtensa/gdbstub_xtensa.c

@@ -17,6 +17,7 @@
 #include "esp_gdbstub_common.h"
 #include "soc/cpu.h"
 #include "soc/soc_memory_layout.h"
+#include "xtensa/config/specreg.h"
 #include "sdkconfig.h"
 
 #if !XCHAL_HAVE_WINDOWED

+ 4 - 7
components/freertos/include/freertos/portable.h

@@ -86,7 +86,6 @@ specific constants has been moved into the deprecated_definitions.h header
 file. */
 #include "deprecated_definitions.h"
 
-#include "soc/cpu.h"
 
 /* If portENTER_CRITICAL is not defined then including deprecated_definitions.h
 did not result in a portmacro.h header file being included - and it should be
@@ -127,6 +126,9 @@ extern "C" {
 #include "mpu_wrappers.h"
 #include "esp_system.h"
 
+#include "hal/cpu_hal.h"
+#include "xt_instr_macros.h"
+
 /*
  * Setup the stack of a new task so it is ready to be placed under the
  * scheduler control.  The registers have to be placed on the stack in
@@ -200,12 +202,7 @@ BaseType_t xPortInterruptedFromISRContext(void);
 
 /* Multi-core: get current core ID */
 static inline uint32_t IRAM_ATTR xPortGetCoreID(void) {
-    uint32_t id;
-    __asm__ __volatile__ (
-        "rsr.prid %0\n"
-        " extui %0,%0,13,1"
-        :"=r"(id));
-    return id;
+    return cpu_hal_get_core_id();
 }
 
 /* Get tick rate per second */

+ 5 - 1
components/soc/CMakeLists.txt

@@ -1,7 +1,9 @@
 idf_build_get_property(target IDF_TARGET)
 
-idf_component_register(SRCS "src/memory_layout_utils.c"
+idf_component_register(SRCS "src/cpu_util.c"
+                            "src/memory_layout_utils.c"
                             "src/lldesc.c"
+                            "src/hal/cpu_hal.c"
                             "src/hal/rmt_hal.c"
                             "src/hal/rtc_io_hal.c"
                             "src/hal/dac_hal.c"
@@ -25,6 +27,8 @@ idf_component_register(SRCS "src/memory_layout_utils.c"
                             "src/hal/uart_hal_iram.c"
                             "src/hal/spi_flash_hal.c"
                             "src/hal/spi_flash_hal_iram.c"
+                            "src/hal/mpu_hal.c"
+                            "src/hal/soc_hal.c"
                             "src/compare_set.c"
                        PRIV_REQUIRES ${target}
                        LDFRAGMENTS linker.lf)

+ 114 - 0
components/soc/include/hal/cpu_hal.h

@@ -0,0 +1,114 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "esp_err.h"
+
+#include "hal/cpu_types.h"
+#include "hal/cpu_ll.h"
+#include "soc/cpu_caps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Return the ID of the core currently executing this code.
+ *
+ * @return core id [0..SOC_CPU_CORES_NUM - 1]
+ */
+#define cpu_hal_get_core_id()           cpu_ll_get_core_id()
+
+/**
+ * Get the current value of the stack pointer.
+ *
+ * @return the current stack pointer
+ */
+#define cpu_hal_get_sp()                cpu_ll_get_sp()
+
+/**
+ * Get the current value of the internal counter that increments
+ * every processor-clock cycle.
+ *
+ * @return cycle count; returns 0 if not supported
+ */
+#define cpu_hal_get_cycle_count()       cpu_ll_get_cycle_count()
+
+/**
+ * Check if some form of debugger is attached to CPU.
+ *
+ * @return true debugger is attached
+ * @return false no debugger is attached/ no support for debuggers
+ */
+#define cpu_hal_is_debugger_attached()  cpu_ll_is_debugger_attached()
+
+/**
+ * Init HW loop status.
+ */
+#define cpu_hal_init_hwloop()           cpu_ll_init_hwloop()
+
+/**
+ * Trigger a call to debugger.
+ */
+#define cpu_hal_break()                 cpu_ll_break()
+
+#if SOC_CPU_BREAKPOINTS_NUM > 0
+
+/**
+ * Set and enable breakpoint at an instruction address.
+ *
+ * @note Overwrites previously set breakpoint with same breakpoint ID.
+ *
+ * @param id breakpoint to set [0..SOC_CPU_BREAKPOINTS_NUM - 1]
+ * @param addr address to set a breakpoint on
+ */
+void cpu_hal_set_breakpoint(int id, const void* addr);
+
+/**
+ * Clear and disable breakpoint.
+ *
+ * @param id breakpoint to clear [0..SOC_CPU_BREAKPOINTS_NUM - 1]
+ */
+void cpu_hal_clear_breakpoint(int id);
+
+#endif // SOC_CPU_BREAKPOINTS_NUM > 0
+
+#if SOC_CPU_WATCHPOINTS_NUM > 0
+
+/**
+ * Set and enable a watchpoint, specifying the memory range and trigger operation.
+ *
+ * @param id watchpoint to set [0..SOC_CPU_WATCHPOINTS_NUM - 1]
+ * @param addr starting address
+ * @param size number of bytes from starting address to watch
+ * @param trigger operation on specified memory range that triggers the watchpoint (read, write, read/write)
+ */
+void cpu_hal_set_watchpoint(int id, const void* addr, size_t size, watchpoint_trigger_t trigger);
+
+/**
+ * Clear and disable watchpoint.
+ *
+ * @param id watchpoint to clear [0..SOC_CPU_WATCHPOINTS_NUM - 1]
+ */
+void cpu_hal_clear_watchpoint(int id);
+
+#endif // SOC_CPU_WATCHPOINTS_NUM > 0
+
+#ifdef __cplusplus
+}
+#endif

+ 21 - 0
components/soc/include/hal/cpu_types.h

@@ -0,0 +1,21 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+typedef enum {
+    WATCHPOINT_TRIGGER_ON_RO,       // on read
+    WATCHPOINT_TRIGGER_ON_WO,       // on write
+    WATCHPOINT_TRIGGER_ON_RW        // on either read or write
+} watchpoint_trigger_t;

+ 36 - 0
components/soc/include/hal/mpu_hal.h

@@ -0,0 +1,36 @@
+// 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.
+
+#include <stdint.h>
+
+#include "esp_err.h"
+
+#include "hal/mpu_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Specify the type of access allowed on a memory region.
+ *  
+ * @param id index to the region table; on targets not SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED,
+ * the region divisions is predefined in hardware which is likely reflected in LL implementation.
+ * @param access type of access allowed
+ */
+void mpu_hal_set_region_access(int id, mpu_access_t access);
+
+#ifdef __cplusplus
+}
+#endif

+ 33 - 0
components/soc/include/hal/mpu_types.h

@@ -0,0 +1,33 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include <stdint.h>
+
+#if SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
+typedef void** mpu_region_table_t;
+#endif
+
+typedef enum {
+    MPU_REGION_ILLEGAL,
+#if SOC_MPU_REGION_RO_SUPPORTED
+    MPU_REGION_RO,      // read-only
+#endif
+#if SOC_MPU_REGION_WO_SUPPORTED
+    MPU_REGION_WO,      // write-only
+#endif
+    MPU_REGION_RW,      // read-write
+    MPU_REGION_X,       // executable
+    MPU_REGION_RWX      // read-write-executable
+} mpu_access_t;

+ 75 - 0
components/soc/include/hal/soc_hal.h

@@ -0,0 +1,75 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "soc/soc_caps.h"
+#include "hal/cpu_hal.h"
+#include "hal/soc_ll.h"
+
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if SOC_CPU_CORES_NUM > 1
+// Utility functions for multicore targets
+#define __SOC_HAL_PERFORM_ON_OTHER_CORES(action)    { \
+                                                        for (int i = 0, cur = cpu_hal_get_core_id(); i < SOC_CPU_CORES_NUM; i++) { \
+                                                            if (i != cur) { \
+                                                                action(i); \
+                                                            } \
+                                                        } \
+                                                    }
+
+#define SOC_HAL_STALL_OTHER_CORES()                 __SOC_HAL_PERFORM_ON_OTHER_CORES(soc_hal_stall_core);
+#define SOC_HAL_UNSTALL_OTHER_CORES()               __SOC_HAL_PERFORM_ON_OTHER_CORES(soc_hal_unstall_core);
+#define SOC_HAL_RESET_OTHER_CORES()                 __SOC_HAL_PERFORM_ON_OTHER_CORES(soc_hal_reset_core);
+
+/**
+ * Stall the specified CPU core.
+ *
+ * @note Has no effect if the core is already stalled - does not return an
+ * ESP_ERR_INVALID_STATE.
+ *
+ * @param core core to stall [0..SOC_CPU_CORES_NUM - 1]
+ */
+void soc_hal_stall_core(int core);
+
+/**
+ * Unstall the specified CPU core.
+ *
+ * @note Has no effect if the core is already unstalled - does not return an
+ * ESP_ERR_INVALID_STATE.
+ *
+ * @param core core to unstall [0..SOC_CPU_CORES_NUM - 1]
+ */
+void soc_hal_unstall_core(int core);
+
+#endif // SOC_CPU_CORES_NUM > 1
+
+/**
+ * Reset the specified core.
+ *
+ * @param core core to reset [0..SOC_CPU_CORES_NUM - 1]
+ */
+#define soc_hal_reset_core(core)         soc_ll_reset_core((core))
+
+#ifdef __cplusplus
+}
+#endif

+ 6 - 54
components/soc/soc/esp32/include/soc/cpu.h → components/soc/include/soc/cpu.h

@@ -21,69 +21,21 @@
 #include "xtensa/corebits.h"
 #include "xtensa/config/core.h"
 
+#include "xtensa/config/specreg.h"
+#include "xt_instr_macros.h"
+
+#include "hal/cpu_hal.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* C macros for xtensa special register read/write/exchange */
-
-#define RSR(reg, curval)  asm volatile ("rsr %0, " #reg : "=r" (curval));
-#define WSR(reg, newval)  asm volatile ("wsr %0, " #reg : : "r" (newval));
-#define XSR(reg, swapval) asm volatile ("xsr %0, " #reg : "+r" (swapval));
-
 /** @brief Read current stack pointer address
  *
  */
 static inline void *get_sp(void)
 {
-    void *sp;
-    asm volatile ("mov %0, sp;" : "=r" (sp));
-    return sp;
-}
-
-/* Functions to set page attributes for Region Protection option in the CPU.
- * See Xtensa ISA Reference manual for explanation of arguments (section 4.6.3.2).
- */
-
-static inline void cpu_write_dtlb(uint32_t vpn, unsigned attr)
-{
-    asm volatile ("wdtlb  %1, %0; dsync\n" :: "r" (vpn), "r" (attr));
-}
-
-
-static inline void cpu_write_itlb(unsigned vpn, unsigned attr)
-{
-    asm volatile ("witlb  %1, %0; isync\n" :: "r" (vpn), "r" (attr));
-}
-
-static inline void cpu_init_memctl(void)
-{
-#if XCHAL_ERRATUM_572
-    uint32_t memctl = XCHAL_CACHE_MEMCTL_DEFAULT;
-    WSR(MEMCTL, memctl);
-#endif // XCHAL_ERRATUM_572
-}
-
-/**
- * @brief Configure memory region protection
- *
- * Make page 0 access raise an exception.
- * Also protect some other unused pages so we can catch weirdness.
- * Useful attribute values:
- * 0 — cached, RW
- * 2 — bypass cache, RWX (default value after CPU reset)
- * 15 — no access, raise exception
- */
-
-static inline void cpu_configure_region_protection(void)
-{
-    const uint32_t pages_to_protect[] = {0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000};
-    for (int i = 0; i < sizeof(pages_to_protect)/sizeof(pages_to_protect[0]); ++i) {
-        cpu_write_dtlb(pages_to_protect[i], 0xf);
-        cpu_write_itlb(pages_to_protect[i], 0xf);
-    }
-    cpu_write_dtlb(0x20000000, 0);
-    cpu_write_itlb(0x20000000, 0);
+    return cpu_hal_get_sp();
 }
 
 /**

+ 2 - 0
components/soc/linker.lf

@@ -21,3 +21,5 @@ entries:
     i2c_hal_iram (noflash)
     spi_flash_hal_gpspi (noflash)
     lldesc (noflash_text)
+    cpu_hal (noflash)
+    soc_hal (noflash)

+ 20 - 0
components/soc/soc/esp32/include/soc/cpu_caps.h

@@ -0,0 +1,20 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#define SOC_CPU_BREAKPOINTS_NUM         2
+#define SOC_CPU_WATCHPOINTS_NUM         2
+
+#define SOC_CPU_WATCHPOINT_SIZE         64 // bytes

+ 21 - 0
components/soc/soc/esp32/include/soc/mpu_caps.h

@@ -0,0 +1,21 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#define SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED    0
+#define SOC_MPU_MIN_REGION_SIZE                   0x20000000
+#define SOC_MPU_REGIONS_MAX_NUM                   8
+#define SOC_MPU_REGION_RO_SUPPORTED               0
+#define SOC_MPU_REGION_WO_SUPPORTED               0

+ 2 - 0
components/soc/soc/esp32/include/soc/soc_caps.h

@@ -11,3 +11,5 @@
 #define SOC_SDIO_SLAVE_SUPPORTED    1
 #define SOC_CAN_SUPPORTED 1
 #define SOC_EMAC_SUPPORTED 1
+
+#define SOC_CPU_CORES_NUM 2

+ 20 - 0
components/soc/soc/esp32s2/include/soc/cpu_caps.h

@@ -0,0 +1,20 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#define SOC_CPU_BREAKPOINTS_NUM         2
+#define SOC_CPU_WATCHPOINTS_NUM         2
+
+#define SOC_CPU_WATCHPOINT_SIZE         64 // bytes

+ 21 - 0
components/soc/soc/esp32s2/include/soc/mpu_caps.h

@@ -0,0 +1,21 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#define SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED    0
+#define SOC_MPU_MIN_REGION_SIZE                   0x20000000
+#define SOC_MPU_REGIONS_MAX_NUM                   8
+#define SOC_MPU_REGION_RO_SUPPORTED               0
+#define SOC_MPU_REGION_WO_SUPPORTED               0

+ 2 - 0
components/soc/soc/esp32s2/include/soc/soc_caps.h

@@ -4,3 +4,5 @@
 // include them here.
 
 #pragma once
+
+#define SOC_CPU_CORES_NUM 1

+ 86 - 0
components/soc/src/cpu_util.c

@@ -0,0 +1,86 @@
+// 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.
+
+#include "esp_attr.h"
+#include "soc/cpu.h"
+#include "soc/soc.h"
+#include "soc/rtc_periph.h"
+#include "sdkconfig.h"
+
+#include "hal/cpu_hal.h"
+#include "esp_debug_helpers.h"
+#include "hal/cpu_types.h"
+
+#include "hal/soc_hal.h"
+#include "soc/soc_caps.h"
+
+#include "sdkconfig.h"
+
+void IRAM_ATTR esp_cpu_stall(int cpu_id)
+{
+#if SOC_CPU_CORES_NUM > 1
+    soc_hal_stall_core(cpu_id);
+#endif
+}
+
+void IRAM_ATTR esp_cpu_unstall(int cpu_id)
+{
+#if SOC_CPU_CORES_NUM > 1
+    soc_hal_unstall_core(cpu_id);
+#endif
+}
+
+void IRAM_ATTR esp_cpu_reset(int cpu_id)
+{
+    soc_hal_reset_core(cpu_id);
+}
+
+esp_err_t IRAM_ATTR esp_set_watchpoint(int no, void *adr, int size, int flags)
+{
+    watchpoint_trigger_t trigger;
+
+    switch (flags)
+    {
+    case ESP_WATCHPOINT_LOAD:
+        trigger = WATCHPOINT_TRIGGER_ON_RO;
+        break;
+    case ESP_WATCHPOINT_STORE:
+        trigger = WATCHPOINT_TRIGGER_ON_WO;
+        break;
+    case ESP_WATCHPOINT_ACCESS:
+        trigger = WATCHPOINT_TRIGGER_ON_RW;
+        break;
+    default:
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    cpu_hal_set_watchpoint(no, adr, size, trigger);
+    return ESP_OK;
+}
+
+void IRAM_ATTR esp_clear_watchpoint(int no)
+{
+    cpu_hal_clear_watchpoint(no);
+}
+
+bool IRAM_ATTR esp_cpu_in_ocd_debug_mode(void)
+{
+#if (CONFIG_ESP32_DEBUG_OCDAWARE == 1) || \
+    (CONFIG_ESP32S2_DEBUG_OCDAWARE == 1)
+    return cpu_ll_is_debugger_attached();
+#else
+    return false; // Always return false if "OCD aware" is disabled
+#endif
+}
+

+ 0 - 1
components/soc/src/esp32/CMakeLists.txt

@@ -1,5 +1,4 @@
 set(srcs "brownout_hal.c"
-    "cpu_util.c"
     "rtc_clk.c"
     "rtc_clk_init.c"
     "rtc_init.c"

+ 0 - 63
components/soc/src/esp32/cpu_util.c

@@ -1,63 +0,0 @@
-// Copyright 2013-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "esp_attr.h"
-#include "soc/cpu.h"
-#include "soc/soc.h"
-#include "soc/rtc_periph.h"
-#include "sdkconfig.h"
-
-void IRAM_ATTR esp_cpu_stall(int cpu_id)
-{
-    if (cpu_id == 1) {
-        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
-        SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
-        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
-        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
-    } else {
-        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
-        SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
-        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
-        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
-    }
-}
-
-void IRAM_ATTR esp_cpu_unstall(int cpu_id)
-{
-    if (cpu_id == 1) {
-        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
-        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
-    } else {
-        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
-        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
-    }
-}
-
-void IRAM_ATTR esp_cpu_reset(int cpu_id)
-{
-    SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
-            cpu_id == 0 ? RTC_CNTL_SW_PROCPU_RST_M : RTC_CNTL_SW_APPCPU_RST_M);
-}
-
-bool IRAM_ATTR esp_cpu_in_ocd_debug_mode(void)
-{
-#if CONFIG_ESP32_DEBUG_OCDAWARE
-    int dcr;
-    int reg=0x10200C; //DSRSET register
-    asm("rer %0,%1":"=r"(dcr):"r"(reg));
-    return (dcr&0x1);
-#else
-    return false; // Always return false if "OCD aware" is disabled
-#endif
-}

+ 171 - 0
components/soc/src/esp32/include/hal/cpu_ll.h

@@ -0,0 +1,171 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include <stdint.h>
+
+#include "soc/cpu_caps.h"
+
+#include "xt_instr_macros.h"
+#include "xtensa/config/specreg.h"
+#include "xtensa/config/extreg.h"
+#include "esp_bit_defs.h"
+#include "xtensa/config/core.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline int cpu_ll_get_core_id(void)
+{
+    uint32_t id;
+    asm volatile (
+        "rsr.prid %0\n"
+        "extui %0,%0,13,1"
+        :"=r"(id));
+    return (int) id;
+}
+
+static inline uint32_t cpu_ll_get_cycle_count(void)
+{
+    uint32_t result;
+    RSR(CCOUNT, result);
+    return result;
+}
+
+static inline void* cpu_ll_get_sp(void)
+{
+    void *sp;
+    asm volatile ("mov %0, sp;" : "=r" (sp));
+    return sp;
+}
+
+static inline void cpu_ll_init_hwloop(void)
+{
+#if XCHAL_ERRATUM_572
+    uint32_t memctl = XCHAL_CACHE_MEMCTL_DEFAULT;
+    WSR(MEMCTL, memctl);
+#endif // XCHAL_ERRATUM_572
+}
+
+static inline void cpu_ll_set_breakpoint(int id, uint32_t pc)
+{
+    uint32_t en;
+
+    // Set the break address register to the appropriate PC
+    if (id) {
+        WSR(IBREAKA_1, pc);
+    } else {
+        WSR(IBREAKA_0, pc);
+    }
+
+    // Enable the breakpoint using the break enable register
+    RSR(IBREAKENABLE, en);
+    en |= BIT(id);
+    WSR(IBREAKENABLE, en);
+}
+
+static inline void cpu_ll_clear_breakpoint(int id)
+{
+    uint32_t en = 0;
+    uint32_t pc = 0;
+
+    // Set the break address register to the appropriate PC
+    if (id) {
+        WSR(IBREAKA_1, pc);
+    } else {
+        WSR(IBREAKA_0, pc);
+    }
+
+    // Enable the breakpoint using the break enable register
+    RSR(IBREAKENABLE, en);
+    en &= ~BIT(id);
+    WSR(IBREAKENABLE, en);
+}
+
+static inline uint32_t cpu_ll_ptr_to_pc(const void* addr)
+{
+    return ((uint32_t) addr);
+}
+
+static inline void* cpu_ll_pc_to_ptr(uint32_t pc)
+{
+    return (void*) ((pc & 0x3fffffff) | 0x40000000);
+}
+
+static inline void cpu_ll_set_watchpoint(int id,
+                                        const void* addr,
+                                        size_t size,
+                                        bool on_read,
+                                        bool on_write)
+{
+    uint32_t dbreakc = 0x3F;
+
+    //We support watching 2^n byte values, from 1 to 64. Calculate the mask for that.
+    for (int x = 0; x < 7; x++) {
+        if (size == (1 << x)) {
+            break;
+        }
+        dbreakc <<= 1;
+    }
+
+    dbreakc = (dbreakc & 0x3F);
+
+    if (on_read) {
+        dbreakc |= BIT(30);
+    }
+
+    if (on_write) {
+        dbreakc |= BIT(31);
+    }
+
+    // Write the break address register and the size to control
+    // register.
+    if (id) {
+        WSR(DBREAKA_1, (uint32_t) addr);
+        WSR(DBREAKC_1, dbreakc);
+    } else {
+        WSR(DBREAKA_0, (uint32_t) addr);
+        WSR(DBREAKC_0, dbreakc);
+    }
+}
+
+static inline void cpu_ll_clear_watchpoint(int id)
+{
+    // Clear both break address register and control register
+    if (id) {
+        WSR(DBREAKA_1, 0);
+        WSR(DBREAKC_1, 0);
+    } else {
+        WSR(DBREAKA_0, 0);
+        WSR(DBREAKC_0, 0);
+    }
+}
+
+static inline bool cpu_ll_is_debugger_attached(void)
+{
+    uint32_t dcr = 0;
+    uint32_t reg = DSRSET;
+    RER(reg, dcr);
+    return (dcr&0x1);
+}
+
+static inline void cpu_ll_break(void)
+{
+    __asm__ ("break 0,0");
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 62 - 0
components/soc/src/esp32/include/hal/mpu_ll.h

@@ -0,0 +1,62 @@
+// 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.
+
+#include <stdint.h>
+
+#include "soc/mpu_caps.h"
+
+#include "xt_instr_macros.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline uint32_t cpu_ll_id_to_addr(int id)
+{
+    // vpn - id
+    // 0x00000000 = 0
+    // 0x20000000 = 1
+    // 0x40000000 = 2
+    // 0x60000000 = 3
+    // 0x80000000 = 4
+    // 0xa0000000 = 5
+    // 0xc0000000 = 6
+    // 0xe0000000 = 7
+    return id * SOC_MPU_MIN_REGION_SIZE;
+}
+
+static inline void mpu_ll_set_region_rw(uint32_t addr)
+{
+    WDTLB(0x0, addr); // cached, no allocate
+}
+
+static inline void mpu_ll_set_region_rwx(uint32_t addr)
+{
+    WDTLB(0x2, addr); // bypass cache
+}
+
+static inline void mpu_ll_set_region_x(uint32_t addr)
+{
+    WITLB(0x3, addr); // cached
+}
+
+static inline void mpu_ll_set_region_illegal(uint32_t addr)
+{
+    WITLB(0xF, addr);
+    WDTLB(0xF, addr);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 53 - 0
components/soc/src/esp32/include/hal/soc_ll.h

@@ -0,0 +1,53 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include "soc/soc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/soc_caps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline void soc_ll_stall_core(int core)
+{
+    const int rtc_cntl_c1_m[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C1_M, RTC_CNTL_SW_STALL_APPCPU_C1_M};
+    const int rtc_cntl_c1_s[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C1_S, RTC_CNTL_SW_STALL_APPCPU_C1_S};
+    const int rtc_cntl_c0_m[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C0_M, RTC_CNTL_SW_STALL_APPCPU_C0_M};
+    const int rtc_cntl_c0_s[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C0_S, RTC_CNTL_SW_STALL_APPCPU_C0_S};
+
+    CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1_m[core]);
+    SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21 << rtc_cntl_c1_s[core]);
+    CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_c0_m[core]);
+    SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2 << rtc_cntl_c0_s[core]);
+}
+
+static inline void soc_ll_unstall_core(int core)
+{
+    const int rtc_cntl_c1_m[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C1_M, RTC_CNTL_SW_STALL_APPCPU_C1_M};
+    const int rtc_cntl_c0_m[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C0_M, RTC_CNTL_SW_STALL_APPCPU_C0_M};
+    CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1_m[core]);
+    CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_c0_m[core]);
+}
+
+static inline void soc_ll_reset_core(int core)
+{
+    SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
+            core == 0 ? RTC_CNTL_SW_PROCPU_RST_M : RTC_CNTL_SW_APPCPU_RST_M);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 0 - 1
components/soc/src/esp32s2/CMakeLists.txt

@@ -1,5 +1,4 @@
 set(srcs "brownout_hal.c" 
-        "cpu_util.c"
         "rtc_clk.c"
         "rtc_clk_init.c"
         "rtc_init.c"

+ 0 - 63
components/soc/src/esp32s2/cpu_util.c

@@ -1,63 +0,0 @@
-// Copyright 2013-2016 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "esp_attr.h"
-#include "soc/cpu.h"
-#include "soc/soc.h"
-#include "soc/rtc_cntl_reg.h"
-#include "sdkconfig.h"
-
-void IRAM_ATTR esp_cpu_stall(int cpu_id)
-{
-    if (cpu_id == 1) {
-        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
-        SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
-        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
-        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
-    } else {
-        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
-        SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
-        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
-        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
-    }
-}
-
-void IRAM_ATTR esp_cpu_unstall(int cpu_id)
-{
-    if (cpu_id == 1) {
-        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
-        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
-    } else {
-        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
-        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
-    }
-}
-
-void IRAM_ATTR esp_cpu_reset(int cpu_id)
-{
-    SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
-            cpu_id == 0 ? RTC_CNTL_SW_PROCPU_RST_M : RTC_CNTL_SW_APPCPU_RST_M);
-}
-
-bool IRAM_ATTR esp_cpu_in_ocd_debug_mode(void)
-{
-#if CONFIG_ESP32S2_DEBUG_OCDAWARE
-    int dcr;
-    int reg=0x10200C; //DSRSET register
-    asm("rer %0,%1":"=r"(dcr):"r"(reg));
-    return (dcr&0x1);
-#else
-    return false; // Always return false if "OCD aware" is disabled
-#endif
-}

+ 167 - 0
components/soc/src/esp32s2/include/hal/cpu_ll.h

@@ -0,0 +1,167 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include <stdint.h>
+
+#include "soc/cpu_caps.h"
+
+#include "xt_instr_macros.h"
+#include "xtensa/config/specreg.h"
+#include "xtensa/config/extreg.h"
+#include "esp_bit_defs.h"
+#include "xtensa/config/core.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline int cpu_ll_get_core_id(void)
+{
+    return 0;
+}
+
+static inline uint32_t cpu_ll_get_cycle_count(void)
+{
+    uint32_t result;
+    RSR(CCOUNT, result);
+    return result;
+}
+
+static inline void* cpu_ll_get_sp(void)
+{
+    void *sp;
+    asm volatile ("mov %0, sp;" : "=r" (sp));
+    return sp;
+}
+
+static inline void cpu_ll_init_hwloop(void)
+{
+#if XCHAL_ERRATUM_572
+    uint32_t memctl = XCHAL_CACHE_MEMCTL_DEFAULT;
+    WSR(MEMCTL, memctl);
+#endif // XCHAL_ERRATUM_572
+}
+
+static inline void cpu_ll_set_breakpoint(int id, uint32_t pc)
+{
+    uint32_t en;
+
+    // Set the break address register to the appropriate PC
+    if (id) {
+        WSR(IBREAKA_1, pc);
+    } else {
+        WSR(IBREAKA_0, pc);
+    }
+
+    // Enable the breakpoint using the break enable register
+    RSR(IBREAKENABLE, en);
+    en |= BIT(id);
+    WSR(IBREAKENABLE, en);
+}
+
+static inline void cpu_ll_clear_breakpoint(int id)
+{
+    uint32_t en = 0;
+    uint32_t pc = 0;
+
+    // Set the break address register to the appropriate PC
+    if (id) {
+        WSR(IBREAKA_1, pc);
+    } else {
+        WSR(IBREAKA_0, pc);
+    }
+
+    // Enable the breakpoint using the break enable register
+    RSR(IBREAKENABLE, en);
+    en &= ~BIT(id);
+    WSR(IBREAKENABLE, en);
+}
+
+static inline uint32_t cpu_ll_ptr_to_pc(const void* addr)
+{
+    return ((uint32_t) addr);
+}
+
+static inline void* cpu_ll_pc_to_ptr(uint32_t pc)
+{
+    return (void*) ((pc & 0x3fffffff) | 0x40000000);
+}
+
+static inline void cpu_ll_set_watchpoint(int id,
+                                        const void* addr,
+                                        size_t size,
+                                        bool on_read,
+                                        bool on_write)
+{
+    uint32_t dbreakc = 0x3F;
+
+    //We support watching 2^n byte values, from 1 to 64. Calculate the mask for that.
+    for (int x = 0; x < 7; x++) {
+        if (size == (1 << x)) {
+            break;
+        }
+        dbreakc <<= 1;
+    }
+
+    dbreakc = (dbreakc & 0x3F);
+
+    if (on_read) {
+        dbreakc |= BIT(30);
+    }
+
+    if (on_write) {
+        dbreakc |= BIT(31);
+    }
+
+    // Write the break address register and the size to control
+    // register.
+    if (id) {
+        WSR(DBREAKA_1, (uint32_t) addr);
+        WSR(DBREAKC_1, dbreakc);
+    } else {
+        WSR(DBREAKA_0, (uint32_t) addr);
+        WSR(DBREAKC_0, dbreakc);
+    }
+}
+
+static inline void cpu_ll_clear_watchpoint(int id)
+{
+    // Clear both break address register and control register
+    if (id) {
+        WSR(DBREAKA_1, 0);
+        WSR(DBREAKC_1, 0);
+    } else {
+        WSR(DBREAKA_0, 0);
+        WSR(DBREAKC_0, 0);
+    }
+}
+
+static inline bool cpu_ll_is_debugger_attached(void)
+{
+    uint32_t dcr = 0;
+    uint32_t reg = DSRSET;
+    RER(reg, dcr);
+    return (dcr&0x1);
+}
+
+
+static inline void cpu_ll_break(void)
+{
+    __asm__ ("break 0,0");
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 62 - 0
components/soc/src/esp32s2/include/hal/mpu_ll.h

@@ -0,0 +1,62 @@
+// 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.
+
+#include <stdint.h>
+
+#include "soc/mpu_caps.h"
+
+#include "xt_instr_macros.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline uint32_t cpu_ll_id_to_addr(int id)
+{
+    // vpn - id
+    // 0x00000000 = 0
+    // 0x20000000 = 1
+    // 0x40000000 = 2
+    // 0x60000000 = 3
+    // 0x80000000 = 4
+    // 0xa0000000 = 5
+    // 0xc0000000 = 6
+    // 0xe0000000 = 7
+    return id * SOC_MPU_MIN_REGION_SIZE;
+}
+
+static inline void mpu_ll_set_region_rw(uint32_t addr)
+{
+    WDTLB(0x0, addr); // cached, no allocate
+}
+
+static inline void mpu_ll_set_region_rwx(uint32_t addr)
+{
+    WDTLB(0x2, addr); // bypass cache
+}
+
+static inline void mpu_ll_set_region_x(uint32_t addr)
+{
+    WITLB(0x3, addr); // cached
+}
+
+static inline void mpu_ll_set_region_illegal(uint32_t addr)
+{
+    WITLB(0xF, addr);
+    WDTLB(0xF, addr);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 31 - 0
components/soc/src/esp32s2/include/hal/soc_ll.h

@@ -0,0 +1,31 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+
+#include "soc/soc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/soc_caps.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline void soc_ll_reset_core(int core)
+{
+    SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 57 - 0
components/soc/src/hal/cpu_hal.c

@@ -0,0 +1,57 @@
+// 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.
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "esp_err.h"
+
+#include "hal/cpu_hal.h"
+#include "hal/cpu_types.h"
+
+#include "soc/cpu_caps.h"
+
+#if SOC_CPU_BREAKPOINTS_NUM > 0
+void cpu_hal_set_breakpoint(int id, const void* addr)
+{
+    cpu_ll_set_breakpoint(id, cpu_ll_ptr_to_pc(addr));
+}
+
+void cpu_hal_clear_breakpoint(int id)
+{
+    cpu_ll_clear_breakpoint(id);
+}
+#endif // SOC_CPU_BREAKPOINTS_NUM > 0
+
+#if SOC_CPU_WATCHPOINTS_NUM > 0
+void cpu_hal_set_watchpoint(int id, const void* addr, size_t size, watchpoint_trigger_t trigger)
+{
+    bool on_read = false, on_write = false;
+
+    if (trigger == WATCHPOINT_TRIGGER_ON_RO) {
+        on_read = true;
+    } else if (trigger == WATCHPOINT_TRIGGER_ON_WO) {
+        on_write = true;
+    } else {
+        on_read = on_write = true;
+    }
+
+    cpu_ll_set_watchpoint(id, addr, size, on_read, on_write);
+}
+
+void cpu_hal_clear_watchpoint(int id)
+{
+    cpu_ll_clear_watchpoint(id);
+}
+#endif // SOC_CPU_WATCHPOINTS_NUM > 0

+ 54 - 0
components/soc/src/hal/mpu_hal.c

@@ -0,0 +1,54 @@
+// 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.
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "esp_err.h"
+
+#include "hal/mpu_hal.h"
+#include "hal/mpu_ll.h"
+#include "hal/mpu_types.h"
+
+#include "soc/mpu_caps.h"
+
+void mpu_hal_set_region_access(int id, mpu_access_t access)
+{
+    uint32_t addr = cpu_ll_id_to_addr(id);
+
+    switch (access)
+    {
+#if SOC_MPU_REGION_RO_SUPPORTED
+        case MPU_REGION_RO:
+            mpu_ll_set_region_ro(addr);
+            break;
+#endif
+#if SOC_MPU_REGION_WO_SUPPORTED
+        case MPU_REGION_WO:
+            mpu_ll_set_region_wo(addr);
+            break;
+#endif
+        case MPU_REGION_RW:
+            mpu_ll_set_region_rw(addr);
+            break;
+        case MPU_REGION_X:
+            mpu_ll_set_region_x(addr);
+            break;
+        case MPU_REGION_RWX:
+            mpu_ll_set_region_rwx(addr);
+            break;
+        default:
+            break;
+    }
+}

+ 34 - 0
components/soc/src/hal/soc_hal.c

@@ -0,0 +1,34 @@
+// 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.
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "esp_err.h"
+
+#include "hal/soc_hal.h"
+#include "hal/soc_ll.h"
+#include "soc/soc_caps.h"
+
+#if SOC_CPU_CORES_NUM > 1
+void soc_hal_stall_core(int core)
+{
+    soc_ll_stall_core(core);
+}
+
+void soc_hal_unstall_core(int core)
+{
+    soc_ll_unstall_core(core);
+}
+#endif // SOC_CPU_CORES_NUM > 1

+ 21 - 0
components/xtensa/esp32/include/xtensa/config/extreg.h

@@ -0,0 +1,21 @@
+/*
+ * ESP32 External Register symbolic names
+ */
+
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#define DSRSET 0x10200C

+ 2 - 0
components/xtensa/esp32/include/xtensa/config/specreg.h

@@ -57,6 +57,7 @@
 #define DBREAKA_1	145
 #define DBREAKC_0	160
 #define DBREAKC_1	161
+#define CONFIGID0	176
 #define EPC_1		177
 #define EPC_2		178
 #define EPC_3		179
@@ -71,6 +72,7 @@
 #define EPS_5		197
 #define EPS_6		198
 #define EPS_7		199
+#define CONFIGID1	208
 #define EXCSAVE_1	209
 #define EXCSAVE_2	210
 #define EXCSAVE_3	211

+ 21 - 0
components/xtensa/esp32s2/include/xtensa/config/extreg.h

@@ -0,0 +1,21 @@
+/*
+ * ESP32-S2 External Register symbolic names
+ */
+
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#define DSRSET 0x10200C

+ 2 - 0
components/xtensa/esp32s2/include/xtensa/config/specreg.h

@@ -44,6 +44,7 @@
 #define DBREAKA_1	145
 #define DBREAKC_0	160
 #define DBREAKC_1	161
+#define CONFIGID0	176
 #define EPC_1		177
 #define EPC_2		178
 #define EPC_3		179
@@ -58,6 +59,7 @@
 #define EPS_5		197
 #define EPS_6		198
 #define EPS_7		199
+#define CONFIGID1	208
 #define EXCSAVE_1	209
 #define EXCSAVE_2	210
 #define EXCSAVE_3	211

+ 24 - 0
components/xtensa/include/xt_instr_macros.h

@@ -0,0 +1,24 @@
+// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#define RSR(reg, at)         asm volatile ("rsr %0, %1" : "=r" (at) : "i" (reg))
+#define WSR(reg, at)         asm volatile ("wsr %0, %1" : : "r" (at), "i" (reg))
+#define XSR(reg, at)         asm volatile ("xsr %0, %1" : "+r" (at) : "i" (reg))
+
+#define RER(reg, at)         asm volatile ("rer %0, %1" : "=r" (at) : "r" (reg))
+
+#define WITLB(at, as)        asm volatile ("witlb  %0, %1; \n isync \n " : : "r" (at), "r" (as))
+#define WDTLB(at, as)        asm volatile ("wdtlb  %0, %1; \n dsync \n " : : "r" (at), "r" (as))