diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index f48430c72..d120924ef 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/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" diff --git a/components/bootloader_support/include/bootloader_mem.h b/components/bootloader_support/include/bootloader_mem.h new file mode 100644 index 000000000..81c1b4ce7 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/components/bootloader_support/src/bootloader_mem.c b/components/bootloader_support/src/bootloader_mem.c new file mode 100644 index 000000000..e5a2218cc --- /dev/null +++ b/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 + +#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(); +} \ No newline at end of file diff --git a/components/bootloader_support/src/esp32/bootloader_esp32.c b/components/bootloader_support/src/esp32/bootloader_esp32.c index cf0572f40..6a06d8cd1 100644 --- a/components/bootloader_support/src/esp32/bootloader_esp32.c +++ b/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 { diff --git a/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c b/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c index 0c16ff129..2a2652437 100644 --- a/components/bootloader_support/src/esp32s2/bootloader_esp32s2.c +++ b/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 { diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 6ecd1eeb1..61060c5f3 100644 --- a/components/esp32/cpu_start.c +++ b/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); diff --git a/components/esp32/panic.c b/components/esp32/panic.c index a9dafe197..cbf7090a3 100644 --- a/components/esp32/panic.c +++ b/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); diff --git a/components/esp32s2/cpu_start.c b/components/esp32s2/cpu_start.c index f25cb3b07..ae18101fc 100644 --- a/components/esp32s2/cpu_start.c +++ b/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 (\ diff --git a/components/esp32s2/panic.c b/components/esp32s2/panic.c index 1209974f8..b4436397d 100644 --- a/components/esp32s2/panic.c +++ b/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); diff --git a/components/esp_gdbstub/xtensa/gdbstub_xtensa.c b/components/esp_gdbstub/xtensa/gdbstub_xtensa.c index 853b1ba08..a0da9e8cc 100644 --- a/components/esp_gdbstub/xtensa/gdbstub_xtensa.c +++ b/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 diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h index d07ac2f73..cd99a975f 100644 --- a/components/freertos/include/freertos/portable.h +++ b/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 */ diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index 7116f7261..eb67fa974 100644 --- a/components/soc/CMakeLists.txt +++ b/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) diff --git a/components/soc/include/hal/cpu_hal.h b/components/soc/include/hal/cpu_hal.h new file mode 100644 index 000000000..adda25de0 --- /dev/null +++ b/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 +#include + +#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 \ No newline at end of file diff --git a/components/soc/include/hal/cpu_types.h b/components/soc/include/hal/cpu_types.h new file mode 100644 index 000000000..aee44f6ac --- /dev/null +++ b/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; \ No newline at end of file diff --git a/components/soc/include/hal/mpu_hal.h b/components/soc/include/hal/mpu_hal.h new file mode 100644 index 000000000..0614de9eb --- /dev/null +++ b/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 + +#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 \ No newline at end of file diff --git a/components/soc/include/hal/mpu_types.h b/components/soc/include/hal/mpu_types.h new file mode 100644 index 000000000..14675a726 --- /dev/null +++ b/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 + +#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; \ No newline at end of file diff --git a/components/soc/include/hal/soc_hal.h b/components/soc/include/hal/soc_hal.h new file mode 100644 index 000000000..6a4ab30c0 --- /dev/null +++ b/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 +#include + +#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 \ No newline at end of file diff --git a/components/soc/soc/esp32/include/soc/cpu.h b/components/soc/include/soc/cpu.h similarity index 59% rename from components/soc/soc/esp32/include/soc/cpu.h rename to components/soc/include/soc/cpu.h index 82e710bfa..d01970610 100644 --- a/components/soc/soc/esp32/include/soc/cpu.h +++ b/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(); } /** diff --git a/components/soc/linker.lf b/components/soc/linker.lf index 9d05e7710..df2191e32 100644 --- a/components/soc/linker.lf +++ b/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) diff --git a/components/soc/soc/esp32/include/soc/cpu_caps.h b/components/soc/soc/esp32/include/soc/cpu_caps.h new file mode 100644 index 000000000..fbfd780bd --- /dev/null +++ b/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 \ No newline at end of file diff --git a/components/soc/soc/esp32/include/soc/mpu_caps.h b/components/soc/soc/esp32/include/soc/mpu_caps.h new file mode 100644 index 000000000..8e12a2b13 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/components/soc/soc/esp32/include/soc/soc_caps.h b/components/soc/soc/esp32/include/soc/soc_caps.h index 283c7ae0c..bb01067af 100644 --- a/components/soc/soc/esp32/include/soc/soc_caps.h +++ b/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 diff --git a/components/soc/soc/esp32s2/include/soc/cpu_caps.h b/components/soc/soc/esp32s2/include/soc/cpu_caps.h new file mode 100644 index 000000000..fbfd780bd --- /dev/null +++ b/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 \ No newline at end of file diff --git a/components/soc/soc/esp32s2/include/soc/mpu_caps.h b/components/soc/soc/esp32s2/include/soc/mpu_caps.h new file mode 100644 index 000000000..8e12a2b13 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/components/soc/soc/esp32s2/include/soc/soc_caps.h b/components/soc/soc/esp32s2/include/soc/soc_caps.h index 85a465e89..0b24ddbb1 100644 --- a/components/soc/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/soc/esp32s2/include/soc/soc_caps.h @@ -4,3 +4,5 @@ // include them here. #pragma once + +#define SOC_CPU_CORES_NUM 1 \ No newline at end of file diff --git a/components/soc/src/cpu_util.c b/components/soc/src/cpu_util.c new file mode 100644 index 000000000..eadeb2f52 --- /dev/null +++ b/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 +} + diff --git a/components/soc/src/esp32/CMakeLists.txt b/components/soc/src/esp32/CMakeLists.txt index be5ed8b4f..e4c31149f 100644 --- a/components/soc/src/esp32/CMakeLists.txt +++ b/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" diff --git a/components/soc/src/esp32/cpu_util.c b/components/soc/src/esp32/cpu_util.c deleted file mode 100644 index ed2c6361e..000000000 --- a/components/soc/src/esp32/cpu_util.c +++ /dev/null @@ -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< + +#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 diff --git a/components/soc/src/esp32/include/hal/mpu_ll.h b/components/soc/src/esp32/include/hal/mpu_ll.h new file mode 100644 index 000000000..b11e11a7d --- /dev/null +++ b/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 + +#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 \ No newline at end of file diff --git a/components/soc/src/esp32/include/hal/soc_ll.h b/components/soc/src/esp32/include/hal/soc_ll.h new file mode 100644 index 000000000..b83a0756b --- /dev/null +++ b/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 \ No newline at end of file diff --git a/components/soc/src/esp32s2/CMakeLists.txt b/components/soc/src/esp32s2/CMakeLists.txt index 4fc1eb04c..765ef7776 100644 --- a/components/soc/src/esp32s2/CMakeLists.txt +++ b/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" diff --git a/components/soc/src/esp32s2/cpu_util.c b/components/soc/src/esp32s2/cpu_util.c deleted file mode 100644 index ab45ab3b2..000000000 --- a/components/soc/src/esp32s2/cpu_util.c +++ /dev/null @@ -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< + +#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 diff --git a/components/soc/src/esp32s2/include/hal/mpu_ll.h b/components/soc/src/esp32s2/include/hal/mpu_ll.h new file mode 100644 index 000000000..b11e11a7d --- /dev/null +++ b/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 + +#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 \ No newline at end of file diff --git a/components/soc/src/esp32s2/include/hal/soc_ll.h b/components/soc/src/esp32s2/include/hal/soc_ll.h new file mode 100644 index 000000000..e61651581 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/components/soc/src/hal/cpu_hal.c b/components/soc/src/hal/cpu_hal.c new file mode 100644 index 000000000..4b2ca22c9 --- /dev/null +++ b/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 +#include + +#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 \ No newline at end of file diff --git a/components/soc/src/hal/mpu_hal.c b/components/soc/src/hal/mpu_hal.c new file mode 100644 index 000000000..b2cae6b76 --- /dev/null +++ b/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 +#include + +#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; + } +} \ No newline at end of file diff --git a/components/soc/src/hal/soc_hal.c b/components/soc/src/hal/soc_hal.c new file mode 100644 index 000000000..c01ab3e62 --- /dev/null +++ b/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 +#include + +#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 \ No newline at end of file diff --git a/components/xtensa/esp32/include/xtensa/config/extreg.h b/components/xtensa/esp32/include/xtensa/config/extreg.h new file mode 100644 index 000000000..12ab76618 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/components/xtensa/esp32/include/xtensa/config/specreg.h b/components/xtensa/esp32/include/xtensa/config/specreg.h index 0135d4c7f..d35988556 100644 --- a/components/xtensa/esp32/include/xtensa/config/specreg.h +++ b/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 diff --git a/components/xtensa/esp32s2/include/xtensa/config/extreg.h b/components/xtensa/esp32s2/include/xtensa/config/extreg.h new file mode 100644 index 000000000..95a6a69b6 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/components/xtensa/esp32s2/include/xtensa/config/specreg.h b/components/xtensa/esp32s2/include/xtensa/config/specreg.h index 30e95592a..b63d82b96 100644 --- a/components/xtensa/esp32s2/include/xtensa/config/specreg.h +++ b/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 diff --git a/components/xtensa/include/xt_instr_macros.h b/components/xtensa/include/xt_instr_macros.h new file mode 100644 index 000000000..9df78f5f2 --- /dev/null +++ b/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)) \ No newline at end of file