diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index d2f97850ec..1443e619d4 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -147,3 +147,7 @@ endif() if(CONFIG_SOC_MEM_NON_CONTIGUOUS_SRAM) target_link_options(${COMPONENT_LIB} INTERFACE "-Wl,--enable-non-contiguous-regions") endif() + +if(CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS) + add_subdirectory(openocd_stub_bins) +endif() diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 10fb36e359..12d0afe461 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -530,6 +530,19 @@ menu "ESP System Settings" Debug stubs are used by OpenOCD to execute pre-compiled onboard code which does some useful debugging stuff, e.g. GCOV data dump. + config ESP_DEBUG_INCLUDE_OCD_STUB_BINS + bool "Preload OpenOCD stub binaries to speed up debugging. 8K memory will be reserved" + default y + depends on SOC_DEBUG_HAVE_OCD_STUB_BINS + help + OpenOCD uses stub code to access flash during programming or when inserting and removing + flash SW breakpoints. + To execute stub code, OpenOCD allocates memory on the target device, backs up the existing memory, + loads the stub binary, runs the binary, and then restores the original memory. + This process can be time-consuming, especially when using USB serial JTAG. + By enabling this option, 8K of memory in RAM will be preallocated with the stub code, + eliminating the need to back up and restore the memory region. + config ESP_DEBUG_OCDAWARE bool "Make exception and panic handlers JTAG/OCD aware" default y diff --git a/components/esp_system/ld/esp32c6/sections.ld.in b/components/esp_system/ld/esp32c6/sections.ld.in index c9be5aae30..8a9b7eebf2 100644 --- a/components/esp_system/ld/esp32c6/sections.ld.in +++ b/components/esp_system/ld/esp32c6/sections.ld.in @@ -156,6 +156,21 @@ SECTIONS .iram0.text : { _iram_start = ABSOLUTE(.); + +#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS + /* Do not move this block! OpenOCD expects this to be at the beginning of IRAM. */ + KEEP(*(.ocd_stub.code)); + KEEP(*(.ocd_stub.tramp)); + . = ALIGN(0x800); + KEEP(*(.ocd_stub.data)); + KEEP(*(.ocd_stub.bss)); + KEEP(*(.ocd_stub.stack)); + KEEP(*(.ocd_stub.params)); + . = ALIGN(0x1000); + KEEP(*(.ocd_stub.scratchmem)); + ASSERT(ABSOLUTE(.) == _iram_start + 0x2000, "openocd stub memory must be ended at _iram_start + 0x2000"); +#endif + /* Vectors go to start of IRAM */ ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index 57e8a7c513..26aa70b6fb 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -156,6 +156,21 @@ SECTIONS .iram0.text : { _iram_start = ABSOLUTE(.); + +#if CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS + /* Do not move this block! OpenOCD expects this to be at the beginning of IRAM. */ + KEEP(*(.ocd_stub.code)); + KEEP(*(.ocd_stub.tramp)); + . = ALIGN(0x800); + KEEP(*(.ocd_stub.data)); + KEEP(*(.ocd_stub.bss)); + KEEP(*(.ocd_stub.stack)); + KEEP(*(.ocd_stub.params)); + . = ALIGN(0x1000); + KEEP(*(.ocd_stub.scratchmem)); + ASSERT(ABSOLUTE(.) == _iram_start + 0x2000, "openocd stub memory must be ended at _iram_start + 0x2000"); +#endif + /* Vectors go to start of IRAM */ ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned"); KEEP(*(.exception_vectors_table.text)); diff --git a/components/esp_system/openocd_stub_bins/CMakeLists.txt b/components/esp_system/openocd_stub_bins/CMakeLists.txt new file mode 100644 index 0000000000..5f747289d2 --- /dev/null +++ b/components/esp_system/openocd_stub_bins/CMakeLists.txt @@ -0,0 +1,45 @@ +idf_build_get_property(target IDF_TARGET) + +# Function to add custom commands for copying files +function(add_copy_command src dest) + add_custom_command( + OUTPUT ${dest} + COMMAND ${CMAKE_COMMAND} -E copy ${src} ${dest} + DEPENDS ${src} + COMMENT "Copying ${src} to ${dest}" + VERBATIM + ) +endfunction() + +set(openocd_path $ENV{OPENOCD_SCRIPTS}) + +if(openocd_path) + set(stub_bin_path ${openocd_path}/../esp_stub_bins) + if(IS_DIRECTORY ${stub_bin_path} AND IS_DIRECTORY ${stub_bin_path}/${target}) + set(code_bin "${stub_bin_path}/${target}/stub_flash_idf_binary_code.inc") + set(data_bin "${stub_bin_path}/${target}/stub_flash_idf_binary_data.inc") + set(img_header "${stub_bin_path}/${target}/stub_flash_idf_image.h") + if(EXISTS ${code_bin} AND EXISTS ${data_bin} AND EXISTS ${img_header}) + set(dest_dir "${IDF_PATH}/components/esp_system/openocd_stub_bins/${target}") + set(output_code_bin "${dest_dir}/stub_flash_idf_binary_code.inc") + set(output_data_bin "${dest_dir}/stub_flash_idf_binary_data.inc") + set(output_img_header "${dest_dir}/stub_flash_idf_image.h") + add_copy_command(${code_bin} ${output_code_bin}) + add_copy_command(${data_bin} ${output_data_bin}) + add_copy_command(${img_header} ${output_img_header}) + add_custom_target(copy_stub_bins ALL + DEPENDS ${output_code_bin} ${output_data_bin} ${output_img_header} + COMMENT "Copying OpenOCD stub binaries and image header" + ) + endif() + endif() +endif() + +set(srcs) + +list(APPEND srcs "${target}/openocd_stub_flasher.c") + +target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) +target_include_directories(${COMPONENT_LIB} PRIVATE ${target}) + +target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_system_include_openocd_stub_binaries") diff --git a/components/esp_system/openocd_stub_bins/esp32c6/openocd_stub_flasher.c b/components/esp_system/openocd_stub_bins/esp32c6/openocd_stub_flasher.c new file mode 100644 index 0000000000..5be8def2a9 --- /dev/null +++ b/components/esp_system/openocd_stub_bins/esp32c6/openocd_stub_flasher.c @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "stub_flash_idf_image.h" + +/* Copied from openocd-esp32/contrib/loaders/flash/espressif/esp32c6/inc/stub_flash_idf_binary_code.inc */ +static const uint8_t s_flasher_stub_code[] __attribute__((used, section(".ocd_stub.code"))) = { +#include "stub_flash_idf_binary_code.inc" +}; + +/* Copied from openocd-esp32/src/target/espressif/esp_riscv_stub_tramp.inc */ +static const uint8_t s_flasher_stub_tramp[] __attribute__((used, section(".ocd_stub.tramp"))) = { +#include "../esp_riscv_stub_tramp.inc" +}; + +/* Copied from openocd-esp32/contrib/loaders/flash/espressif/esp32c6/inc/stub_flash_idf_binary_data.inc */ +static const uint8_t s_flasher_stub_data[] __attribute__((used, section(".ocd_stub.data"))) = { +#include "stub_flash_idf_binary_data.inc" +}; + +static uint8_t s_flasher_stub_bss[OPENOCD_STUB_BSS_SIZE] __attribute__((used, section(".ocd_stub.bss"))); +static uint8_t s_flasher_stub_stack[OPENOCD_STUB_STACK_SIZE] __attribute__((used, section(".ocd_stub.stack"))); +static uint8_t s_flasher_stub_params[OPENOCD_STUB_PARAM_SIZE] __attribute__((used, section(".ocd_stub.params"))); +static uint8_t s_flasher_stub_bp_sectors[OPENOCD_STUB_BP_SECTOR_SIZE] __attribute__((used, section(".ocd_stub.scratchmem"))); + +// Hook to force the linker to include this file +void esp_system_include_openocd_stub_binaries(void) +{ +} diff --git a/components/esp_system/openocd_stub_bins/esp32h2/openocd_stub_flasher.c b/components/esp_system/openocd_stub_bins/esp32h2/openocd_stub_flasher.c new file mode 100644 index 0000000000..cfc4bc4dbd --- /dev/null +++ b/components/esp_system/openocd_stub_bins/esp32h2/openocd_stub_flasher.c @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include "stub_flash_idf_image.h" + +/* Copied from openocd-esp32/contrib/loaders/flash/espressif/esp32h2/inc/stub_flash_idf_binary_code.inc */ +static const uint8_t s_flasher_stub_code[] __attribute__((used, section(".ocd_stub.code"))) = { +#include "stub_flash_idf_binary_code.inc" +}; + +/* Copied from openocd-esp32/src/target/espressif/esp_riscv_stub_tramp.inc */ +static const uint8_t s_flasher_stub_tramp[] __attribute__((used, section(".ocd_stub.tramp"))) = { +#include "../esp_riscv_stub_tramp.inc" +}; + +/* Copied from openocd-esp32/contrib/loaders/flash/espressif/esp32h2/inc/stub_flash_idf_binary_data.inc */ +static const uint8_t s_flasher_stub_data[] __attribute__((used, section(".ocd_stub.data"))) = { +#include "stub_flash_idf_binary_data.inc" +}; + +static uint8_t s_flasher_stub_bss[OPENOCD_STUB_BSS_SIZE] __attribute__((used, section(".ocd_stub.bss"))); +static uint8_t s_flasher_stub_stack[OPENOCD_STUB_STACK_SIZE] __attribute__((used, section(".ocd_stub.stack"))); +static uint8_t s_flasher_stub_params[OPENOCD_STUB_PARAM_SIZE] __attribute__((used, section(".ocd_stub.params"))); +static uint8_t s_flasher_stub_bp_sectors[OPENOCD_STUB_BP_SECTOR_SIZE] __attribute__((used, section(".ocd_stub.scratchmem"))); + +// Hook to force the linker to include this file +void esp_system_include_openocd_stub_binaries(void) +{ +} diff --git a/components/esp_system/openocd_stub_bins/esp_riscv_stub_tramp.inc b/components/esp_system/openocd_stub_bins/esp_riscv_stub_tramp.inc new file mode 100644 index 0000000000..22c0b530f6 --- /dev/null +++ b/components/esp_system/openocd_stub_bins/esp_riscv_stub_tramp.inc @@ -0,0 +1 @@ + 0x82, 0x98, 0x02, 0x90 diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 24190f9730..df11b1feee 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -1522,3 +1522,7 @@ config SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR config SOC_LP_CORE_SUPPORT_ETM bool default y + +config SOC_DEBUG_HAVE_OCD_STUB_BINS + bool + default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 0eb47fef8f..e8fe107626 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -602,3 +602,6 @@ /*------------------------------------- ULP CAPS -------------------------------------*/ #define SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR (1) /*!< LP Core interrupts all map to a single entry in vector table */ #define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */ + +/*------------------------------------- DEBUG CAPS -------------------------------------*/ +#define SOC_DEBUG_HAVE_OCD_STUB_BINS (1) diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index 28331e9ca7..c907e4193d 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1434,3 +1434,7 @@ config SOC_BLE_MULTI_CONN_OPTIMIZATION config SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED bool default y + +config SOC_DEBUG_HAVE_OCD_STUB_BINS + bool + default y diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index c929016b8c..25a97dfb38 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -562,3 +562,6 @@ #define SOC_BLE_POWER_CONTROL_SUPPORTED (1) /*!< Support Bluetooth Power Control */ #define SOC_BLE_MULTI_CONN_OPTIMIZATION (1) /*!< Support multiple connections optimization */ #define SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED (1) /*!< Support For BLE Periodic Adv Enhancements */ + +/*------------------------------------- DEBUG CAPS -------------------------------------*/ +#define SOC_DEBUG_HAVE_OCD_STUB_BINS (1) diff --git a/docs/en/api-guides/performance/ram-usage.rst b/docs/en/api-guides/performance/ram-usage.rst index c19f7386b7..a144005d08 100644 --- a/docs/en/api-guides/performance/ram-usage.rst +++ b/docs/en/api-guides/performance/ram-usage.rst @@ -192,6 +192,7 @@ The following options will reduce IRAM usage of some ESP-IDF features: - Refer to the sdkconfig menu ``Auto-detect Flash chips``, and you can disable flash drivers which you do not need to save some IRAM. :SOC_GPSPI_SUPPORTED: - Enable :ref:`CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH`. Provided that :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` is not enabled and the heap functions are not incorrectly used from ISRs, this option is safe to enable in all configurations. :esp32c2: - Enable :ref:`CONFIG_BT_RELEASE_IRAM`. Release BT text section and merge BT data, bss & text into a large free heap region when ``esp_bt_mem_release`` is called. This makes Bluetooth unavailable until the next restart, but saving ~22 KB or more of IRAM. + :SOC_DEBUG_HAVE_OCD_STUB_BINS: - Disabling :ref:`CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS` frees 8 KB IRAM but overall speed of debugging might be impacted due to the added overhead of runtime stub loading especially when using flash breakpoints. .. only:: esp32 @@ -202,7 +203,7 @@ The following options will reduce IRAM usage of some ESP-IDF features: To use this option, ESP-IDF should be able to recognize that the new SRAM1 area is also a valid load address for an image segment. If the software bootloader was compiled before this option existed, then the bootloader will not be able to load the app that has code placed in this new extended IRAM area. This would typically happen if you are doing an OTA update, where only the app would be updated. - If the IRAM section were to be placed in an invalid area, then this would be detected during the bootup process, and result in a failed boot: + If the IRAM section were to be placed in an invalid area, then this would be detected during the boot up process, and result in a failed boot: .. code-block:: text diff --git a/docs/zh_CN/api-guides/performance/ram-usage.rst b/docs/zh_CN/api-guides/performance/ram-usage.rst index 44839f698e..a6fc90a99c 100644 --- a/docs/zh_CN/api-guides/performance/ram-usage.rst +++ b/docs/zh_CN/api-guides/performance/ram-usage.rst @@ -192,6 +192,7 @@ IRAM 优化 - 要禁用不需要的 flash 驱动程序,节省 IRAM 空间,请参阅 sdkconfig 菜单中的 ``Auto-detect Flash chips`` 选项。 :SOC_GPSPI_SUPPORTED: - 启用 :ref:`CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH`。只要未启用 :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` 选项,且没有从 ISR 中错误地调用堆函数,就可以在所有配置中安全启用此选项。 :esp32c2: - 启用 :ref:`CONFIG_BT_RELEASE_IRAM`。 蓝牙所使用的 data,bss 和 text 段已经被分配在连续的RAM区间。当调用 ``esp_bt_mem_release`` 时,这些段都会被添加到 Heap 中。 这将节省约 22 KB 的 RAM。但要再次使用蓝牙功能,需要重启程序。 + :SOC_DEBUG_HAVE_OCD_STUB_BINS: - 禁用 :ref:`CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS`。 选项可以释放 8 KB 的 IRAM, 但由于运行时加载存根的额外开销,特别是在使用 flash 断点时,可能会影响调试的整体速度。 .. only:: esp32 diff --git a/tools/ci/astyle-rules.yml b/tools/ci/astyle-rules.yml index e74f913eb5..12da05ef74 100644 --- a/tools/ci/astyle-rules.yml +++ b/tools/ci/astyle-rules.yml @@ -161,6 +161,10 @@ components_not_formatted_permanent: - "/examples/peripherals/dac/dac_continuous/dac_audio/main/audio_example_file.h" # Coredump (generated) - /components/espcoredump/include_core_dump/elf.h + # OpenOCD stub binaries (generated) + - /components/esp_system/openocd_stub_bins/*.inc + - /components/esp_system/openocd_stub_bins/esp32c6/*.inc + - /components/esp_system/openocd_stub_bins/esp32h2/*.inc docs: # Docs directory contains some .inc files, which are not C include files