diff --git a/components/esp_hw_support/cpu.c b/components/esp_hw_support/cpu.c index 6d6790b7e1..7ab72a04fa 100644 --- a/components/esp_hw_support/cpu.c +++ b/components/esp_hw_support/cpu.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -72,10 +72,10 @@ void esp_cpu_wait_for_intr(void) #if SOC_CPU_BREAKPOINTS_NUM > 0 esp_err_t esp_cpu_set_breakpoint(int bp_num, const void *bp_addr) { - /* - Todo: - - Check that bp_num is in range - */ + if (bp_num < 0 || bp_num >= SOC_CPU_BREAKPOINTS_NUM) { + return ESP_ERR_INVALID_ARG; + } + #if __XTENSA__ xt_utils_set_breakpoint(bp_num, (uint32_t)bp_addr); #else @@ -101,10 +101,10 @@ esp_err_t esp_cpu_set_breakpoint(int bp_num, const void *bp_addr) esp_err_t esp_cpu_clear_breakpoint(int bp_num) { - /* - Todo: - - Check if the bp_num is valid - */ + if (bp_num < 0 || bp_num >= SOC_CPU_BREAKPOINTS_NUM) { + return ESP_ERR_INVALID_ARG; + } + #if __XTENSA__ xt_utils_clear_breakpoint(bp_num); #else @@ -126,23 +126,20 @@ esp_err_t esp_cpu_clear_breakpoint(int bp_num) #if SOC_CPU_WATCHPOINTS_NUM > 0 esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, esp_cpu_watchpoint_trigger_t trigger) { - /* - Todo: - - Check if the wp_num is already in use - */ if (wp_num < 0 || wp_num >= SOC_CPU_WATCHPOINTS_NUM) { return ESP_ERR_INVALID_ARG; } + // Check if size is 2^n, and size is in the range of [1 ... SOC_CPU_WATCHPOINT_MAX_REGION_SIZE] + if (size < 1 || size > SOC_CPU_WATCHPOINT_MAX_REGION_SIZE || (size & (size - 1)) != 0) { + return ESP_ERR_INVALID_ARG; + } + // Check that the watched region's start address is naturally aligned to the size of the region if ((uint32_t)wp_addr % size) { return ESP_ERR_INVALID_ARG; } - // Check if size is 2^n, and size is in the range of [1 ... SOC_CPU_WATCHPOINT_MAX_REGION_SIZE] - if (size < 1 || size > SOC_CPU_WATCHPOINT_MAX_REGION_SIZE || (size & (size - 1)) != 0) { - return ESP_ERR_INVALID_ARG; - } bool on_read = (trigger == ESP_CPU_WATCHPOINT_LOAD || trigger == ESP_CPU_WATCHPOINT_ACCESS); bool on_write = (trigger == ESP_CPU_WATCHPOINT_STORE || trigger == ESP_CPU_WATCHPOINT_ACCESS); #if __XTENSA__ @@ -166,10 +163,10 @@ esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, e esp_err_t esp_cpu_clear_watchpoint(int wp_num) { - /* - Todo: - - Check if the wp_num is valid - */ + if (wp_num < 0 || wp_num >= SOC_CPU_WATCHPOINTS_NUM) { + return ESP_ERR_INVALID_ARG; + } + #if __XTENSA__ xt_utils_clear_watchpoint(wp_num); #else diff --git a/components/esp_hw_support/include/esp_cpu.h b/components/esp_hw_support/include/esp_cpu.h index c62b0c84d7..de346b589a 100644 --- a/components/esp_hw_support/include/esp_cpu.h +++ b/components/esp_hw_support/include/esp_cpu.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -110,6 +110,10 @@ void esp_cpu_reset(int core_id); * This function causes the current CPU core to execute its Wait For Interrupt * (WFI or equivalent) instruction. After executing this function, the CPU core * will stop execution until an interrupt occurs. + * + * @note On some RISC-V targets, if a debugger is attached while the hardware + * wait mode is disabled, this function may return immediately instead of + * entering WFI. This keeps debugger memory access working. */ void esp_cpu_wait_for_intr(void); @@ -150,8 +154,10 @@ FORCE_INLINE_ATTR __attribute__((always_inline)) int esp_cpu_get_curr_privilege_ #else #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 return PRV_M; -#else +#elif defined(CSR_PRV_MODE) return RV_READ_CSR(CSR_PRV_MODE); +#else + return -1; #endif #endif } @@ -441,12 +447,12 @@ FORCE_INLINE_ATTR void esp_cpu_intr_set_handler(int intr_num, esp_cpu_intr_handl } /** - * @brief Get a handler function's argument of + * @brief Get a handler function's argument * * Get the argument of a previously assigned handler function on the current CPU. * * @param intr_num Interrupt number (from 0 to 31) - * @return The the argument passed to the handler function + * @return The argument passed to the handler function */ FORCE_INLINE_ATTR void *esp_cpu_intr_get_handler_arg(int intr_num) { @@ -554,7 +560,10 @@ void esp_cpu_configure_region_protection(void); * @note Overwrites previously set breakpoint with same breakpoint number. * @param bp_num Hardware breakpoint number [0..SOC_CPU_BREAKPOINTS_NUM - 1] * @param bp_addr Address to set a breakpoint on - * @return ESP_OK if breakpoint is set. Failure otherwise + * @return + * - ESP_OK if the breakpoint is set + * - ESP_ERR_INVALID_ARG if `bp_num` is out of range + * - ESP_ERR_INVALID_RESPONSE if setting the breakpoint via semihosting fails */ esp_err_t esp_cpu_set_breakpoint(int bp_num, const void *bp_addr); @@ -563,7 +572,10 @@ esp_err_t esp_cpu_set_breakpoint(int bp_num, const void *bp_addr); * * @note Clears a breakpoint regardless of whether it was previously set * @param bp_num Hardware breakpoint number [0..SOC_CPU_BREAKPOINTS_NUM - 1] - * @return ESP_OK if breakpoint is cleared. Failure otherwise + * @return + * - ESP_OK if the breakpoint is cleared + * - ESP_ERR_INVALID_ARG if `bp_num` is out of range + * - ESP_ERR_INVALID_RESPONSE if clearing the breakpoint via semihosting fails */ esp_err_t esp_cpu_clear_breakpoint(int bp_num); @@ -587,7 +599,10 @@ esp_err_t esp_cpu_clear_breakpoint(int bp_num); * @param wp_addr Watchpoint's base address, must be naturally aligned to the size of the region * @param size Size of the region to watch. Must be one of 2^n and in the range of [1 ... SOC_CPU_WATCHPOINT_MAX_REGION_SIZE] * @param trigger Trigger type - * @return ESP_ERR_INVALID_ARG on invalid arg, ESP_OK otherwise + * @return + * - ESP_OK if the watchpoint is set + * - ESP_ERR_INVALID_ARG if `wp_num`, `wp_addr`, or `size` is invalid + * - ESP_ERR_INVALID_RESPONSE if setting the watchpoint via semihosting fails */ esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, esp_cpu_watchpoint_trigger_t trigger); @@ -596,7 +611,10 @@ esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, e * * @note Clears a watchpoint regardless of whether it was previously set * @param wp_num Hardware watchpoint number [0..SOC_CPU_WATCHPOINTS_NUM - 1] - * @return ESP_OK if watchpoint was cleared. Failure otherwise. + * @return + * - ESP_OK if the watchpoint is cleared + * - ESP_ERR_INVALID_ARG if `wp_num` is out of range + * - ESP_ERR_INVALID_RESPONSE if clearing the watchpoint via semihosting fails */ esp_err_t esp_cpu_clear_watchpoint(int wp_num);