mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Support ELF files loadable with gdb
This commit is contained in:
parent
6a9288bc73
commit
5a916ce126
@ -66,7 +66,7 @@ variables:
|
|||||||
rm -rf "$CUSTOM_TOOLCHAIN_PATH"
|
rm -rf "$CUSTOM_TOOLCHAIN_PATH"
|
||||||
|
|
||||||
.setup_tools_unless_target_test: &setup_tools_unless_target_test |
|
.setup_tools_unless_target_test: &setup_tools_unless_target_test |
|
||||||
if [ "$CI_JOB_STAGE" != "target_test" ]; then
|
if [[ "$SETUP_TOOLS" == "1" || "$CI_JOB_STAGE" != "target_test" ]]; then
|
||||||
tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1
|
tools/idf_tools.py --non-interactive install && eval "$(tools/idf_tools.py --non-interactive export)" || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
77
Kconfig
77
Kconfig
@ -68,6 +68,83 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
|||||||
|
|
||||||
endmenu # SDK tool configuration
|
endmenu # SDK tool configuration
|
||||||
|
|
||||||
|
menu "Build type"
|
||||||
|
|
||||||
|
choice APP_BUILD_TYPE
|
||||||
|
prompt "Application build type"
|
||||||
|
default APP_BUILD_TYPE_APP_2NDBOOT
|
||||||
|
help
|
||||||
|
Select the way the application is built.
|
||||||
|
|
||||||
|
By default, the application is built as a binary file in a format compatible with
|
||||||
|
the ESP32 bootloader. In addition to this application, 2nd stage bootloader is
|
||||||
|
also built. Application and bootloader binaries can be written into flash and
|
||||||
|
loaded/executed from there.
|
||||||
|
|
||||||
|
Another option, useful for only very small and limited applications, is to only link
|
||||||
|
the .elf file of the application, such that it can be loaded directly into RAM over
|
||||||
|
JTAG. Note that since IRAM and DRAM sizes are very limited, it is not possible to
|
||||||
|
build any complex application this way. However for kinds of testing and debugging,
|
||||||
|
this option may provide faster iterations, since the application does not need to be
|
||||||
|
written into flash.
|
||||||
|
Note that at the moment, ESP-IDF does not contain all the startup code required to
|
||||||
|
initialize the CPUs and ROM memory (data/bss). Therefore it is necessary to execute
|
||||||
|
a bit of ROM code prior to executing the application. A gdbinit file may look as follows:
|
||||||
|
|
||||||
|
# Connect to a running instance of OpenOCD
|
||||||
|
target remote :3333
|
||||||
|
# Reset and halt the target
|
||||||
|
mon reset halt
|
||||||
|
# Run to a specific point in ROM code,
|
||||||
|
# where most of initialization is complete.
|
||||||
|
thb *0x40007901
|
||||||
|
c
|
||||||
|
# Load the application into RAM
|
||||||
|
load
|
||||||
|
# Run till app_main
|
||||||
|
tb app_main
|
||||||
|
c
|
||||||
|
|
||||||
|
Execute this gdbinit file as follows:
|
||||||
|
|
||||||
|
xtensa-esp32-elf-gdb build/app-name.elf -x gdbinit
|
||||||
|
|
||||||
|
Recommended sdkconfig.defaults for building loadable ELF files is as follows.
|
||||||
|
CONFIG_APP_BUILD_TYPE_ELF_RAM is required, other options help reduce application
|
||||||
|
memory footprint.
|
||||||
|
|
||||||
|
CONFIG_APP_BUILD_TYPE_ELF_RAM=y
|
||||||
|
CONFIG_VFS_SUPPORT_TERMIOS=
|
||||||
|
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||||
|
CONFIG_ESP32_PANIC_PRINT_HALT=y
|
||||||
|
CONFIG_ESP32_DEBUG_STUBS_ENABLE=
|
||||||
|
CONFIG_ESP_ERR_TO_NAME_LOOKUP=
|
||||||
|
|
||||||
|
|
||||||
|
config APP_BUILD_TYPE_APP_2NDBOOT
|
||||||
|
bool
|
||||||
|
prompt "Default (binary application + 2nd stage bootloader)"
|
||||||
|
select APP_BUILD_GENERATE_BINARIES
|
||||||
|
select APP_BUILD_BOOTLOADER
|
||||||
|
select APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
config APP_BUILD_TYPE_ELF_RAM
|
||||||
|
bool
|
||||||
|
prompt "ELF file, loadable into RAM (EXPERIMENTAL))"
|
||||||
|
endchoice # APP_BUILD_TYPE
|
||||||
|
|
||||||
|
# Hidden options, set according to the choice above
|
||||||
|
config APP_BUILD_GENERATE_BINARIES
|
||||||
|
bool # Whether to generate .bin files or not
|
||||||
|
|
||||||
|
config APP_BUILD_BOOTLOADER
|
||||||
|
bool # Whether to build the bootloader
|
||||||
|
|
||||||
|
config APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
bool # Whether to place code/data into memory-mapped flash sections
|
||||||
|
|
||||||
|
endmenu # Build type
|
||||||
|
|
||||||
source "$COMPONENT_KCONFIGS_PROJBUILD"
|
source "$COMPONENT_KCONFIGS_PROJBUILD"
|
||||||
|
|
||||||
menu "Compiler options"
|
menu "Compiler options"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
idf_component_register(PRIV_REQUIRES partition_table)
|
idf_component_register(PRIV_REQUIRES partition_table)
|
||||||
|
|
||||||
# Do not generate flash file when building bootloader or is in early expansion of the build
|
# Do not generate flash file when building bootloader or is in early expansion of the build
|
||||||
if(BOOTLOADER_BUILD)
|
if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
set(BOOTLOADER_OFFSET 0x1000)
|
set(BOOTLOADER_OFFSET 0x1000)
|
||||||
|
|
||||||
# Do not generate flash file when building bootloader
|
# Do not generate flash file when building bootloader
|
||||||
if(BOOTLOADER_BUILD)
|
if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
|
||||||
return()
|
return()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -738,6 +738,11 @@ menu "ESP32-specific"
|
|||||||
|
|
||||||
Enabling this setting adds approximately 1KB to the app's IRAM usage.
|
Enabling this setting adds approximately 1KB to the app's IRAM usage.
|
||||||
|
|
||||||
|
config ESP32_APP_INIT_CLK
|
||||||
|
bool
|
||||||
|
default y if ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS
|
||||||
|
default y if APP_BUILD_TYPE_ELF_RAM
|
||||||
|
|
||||||
config ESP32_RTCDATA_IN_FAST_MEM
|
config ESP32_RTCDATA_IN_FAST_MEM
|
||||||
bool "Place RTC_DATA_ATTR and RTC_RODATA_ATTR variables into RTC fast memory segment"
|
bool "Place RTC_DATA_ATTR and RTC_RODATA_ATTR variables into RTC fast memory segment"
|
||||||
default n
|
default n
|
||||||
|
@ -75,7 +75,7 @@ void esp_clk_init(void)
|
|||||||
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
||||||
rtc_init(cfg);
|
rtc_init(cfg);
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS
|
#if (CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS || CONFIG_ESP32_APP_INIT_CLK)
|
||||||
/* Check the bootloader set the XTAL frequency.
|
/* Check the bootloader set the XTAL frequency.
|
||||||
|
|
||||||
Bootloaders pre-v2.1 don't do this.
|
Bootloaders pre-v2.1 don't do this.
|
||||||
@ -293,6 +293,8 @@ void esp_perip_clk_init(void)
|
|||||||
DPORT_I2S1_CLK_EN |
|
DPORT_I2S1_CLK_EN |
|
||||||
DPORT_SPI_DMA_CLK_EN;
|
DPORT_SPI_DMA_CLK_EN;
|
||||||
|
|
||||||
|
common_perip_clk &= ~DPORT_SPI01_CLK_EN;
|
||||||
|
|
||||||
#if CONFIG_SPIRAM_SPEED_80M
|
#if CONFIG_SPIRAM_SPEED_80M
|
||||||
//80MHz SPIRAM uses SPI2/SPI3 as well; it's initialized before this is called. Because it is used in
|
//80MHz SPIRAM uses SPI2/SPI3 as well; it's initialized before this is called. Because it is used in
|
||||||
//a weird mode where clock to the peripheral is disabled but reset is also disabled, it 'hangs'
|
//a weird mode where clock to the peripheral is disabled but reset is also disabled, it 'hangs'
|
||||||
|
@ -72,6 +72,11 @@
|
|||||||
#include "esp_efuse.h"
|
#include "esp_efuse.h"
|
||||||
#include "bootloader_flash_config.h"
|
#include "bootloader_flash_config.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||||
|
#include "esp32/rom/efuse.h"
|
||||||
|
#include "esp32/rom/spi_flash.h"
|
||||||
|
#endif // CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||||
|
|
||||||
#define STRINGIFY(s) STRINGIFY2(s)
|
#define STRINGIFY(s) STRINGIFY2(s)
|
||||||
#define STRINGIFY2(s) #s
|
#define STRINGIFY2(s) #s
|
||||||
|
|
||||||
@ -391,6 +396,32 @@ void start_cpu0_default(void)
|
|||||||
#ifndef CONFIG_FREERTOS_UNICORE
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
esp_dport_access_int_init();
|
esp_dport_access_int_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bootloader_flash_update_id();
|
||||||
|
#if !CONFIG_SPIRAM_BOOT_INIT
|
||||||
|
// Read the application binary image header. This will also decrypt the header if the image is encrypted.
|
||||||
|
esp_image_header_t fhdr = {0};
|
||||||
|
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||||
|
fhdr.spi_mode = ESP_IMAGE_SPI_MODE_DIO;
|
||||||
|
fhdr.spi_speed = ESP_IMAGE_SPI_SPEED_40M;
|
||||||
|
fhdr.spi_size = ESP_IMAGE_FLASH_SIZE_4MB;
|
||||||
|
|
||||||
|
extern void esp_rom_spiflash_attach(uint32_t, bool);
|
||||||
|
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), false);
|
||||||
|
esp_rom_spiflash_unlock();
|
||||||
|
#else
|
||||||
|
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
||||||
|
// the binary header through cache by accessing SOC_DROM_LOW address.
|
||||||
|
memcpy(&fhdr, (void*) SOC_DROM_LOW, sizeof(fhdr));
|
||||||
|
#endif // CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||||
|
|
||||||
|
// If psram is uninitialized, we need to improve some flash configuration.
|
||||||
|
bootloader_flash_clock_config(&fhdr);
|
||||||
|
bootloader_flash_gpio_config(&fhdr);
|
||||||
|
bootloader_flash_dummy_config(&fhdr);
|
||||||
|
bootloader_flash_cs_timing_config();
|
||||||
|
#endif //!CONFIG_SPIRAM_BOOT_INIT
|
||||||
|
|
||||||
spi_flash_init();
|
spi_flash_init();
|
||||||
/* init default OS-aware flash access critical section */
|
/* init default OS-aware flash access critical section */
|
||||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||||
@ -424,20 +455,6 @@ void start_cpu0_default(void)
|
|||||||
esp_coex_adapter_register(&g_coex_adapter_funcs);
|
esp_coex_adapter_register(&g_coex_adapter_funcs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bootloader_flash_update_id();
|
|
||||||
#if !CONFIG_SPIRAM_BOOT_INIT
|
|
||||||
// Read the application binary image header. This will also decrypt the header if the image is encrypted.
|
|
||||||
esp_image_header_t fhdr = {0};
|
|
||||||
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
|
||||||
// the binary header through cache by accessing SOC_DROM_LOW address.
|
|
||||||
memcpy(&fhdr, (void*) SOC_DROM_LOW, sizeof(fhdr));
|
|
||||||
// If psram is uninitialized, we need to improve some flash configuration.
|
|
||||||
bootloader_flash_clock_config(&fhdr);
|
|
||||||
bootloader_flash_gpio_config(&fhdr);
|
|
||||||
bootloader_flash_dummy_config(&fhdr);
|
|
||||||
bootloader_flash_cs_timing_config();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
|
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
|
||||||
ESP_TASK_MAIN_STACK, NULL,
|
ESP_TASK_MAIN_STACK, NULL,
|
||||||
ESP_TASK_MAIN_PRIO, NULL, 0);
|
ESP_TASK_MAIN_PRIO, NULL, 0);
|
||||||
|
@ -49,6 +49,7 @@ MEMORY
|
|||||||
/* IRAM for PRO cpu. Not sure if happy with this, this is MMU area... */
|
/* IRAM for PRO cpu. Not sure if happy with this, this is MMU area... */
|
||||||
iram0_0_seg (RX) : org = 0x40080000, len = 0x20000
|
iram0_0_seg (RX) : org = 0x40080000, len = 0x20000
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
/* Even though the segment name is iram, it is actually mapped to flash
|
/* Even though the segment name is iram, it is actually mapped to flash
|
||||||
*/
|
*/
|
||||||
iram0_2_seg (RX) : org = 0x400D0018, len = 0x330000-0x18
|
iram0_2_seg (RX) : org = 0x400D0018, len = 0x330000-0x18
|
||||||
@ -58,6 +59,7 @@ MEMORY
|
|||||||
which is flashed to the chip has a 0x18 byte file header. Setting this offset makes it simple to meet the flash
|
which is flashed to the chip has a 0x18 byte file header. Setting this offset makes it simple to meet the flash
|
||||||
cache MMU's constraint that (paddr % 64KB == vaddr % 64KB).)
|
cache MMU's constraint that (paddr % 64KB == vaddr % 64KB).)
|
||||||
*/
|
*/
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
|
||||||
/* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
|
/* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
|
||||||
@ -72,10 +74,12 @@ MEMORY
|
|||||||
dram0_0_seg (RW) : org = 0x3FFB0000 + CONFIG_BT_RESERVE_DRAM,
|
dram0_0_seg (RW) : org = 0x3FFB0000 + CONFIG_BT_RESERVE_DRAM,
|
||||||
len = DRAM0_0_SEG_LEN - CONFIG_BT_RESERVE_DRAM
|
len = DRAM0_0_SEG_LEN - CONFIG_BT_RESERVE_DRAM
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
/* Flash mapped constant data */
|
/* Flash mapped constant data */
|
||||||
drom0_0_seg (R) : org = 0x3F400018, len = 0x400000-0x18
|
drom0_0_seg (R) : org = 0x3F400018, len = 0x400000-0x18
|
||||||
|
|
||||||
/* (See iram0_2_seg for meaning of 0x18 offset in the above.) */
|
/* (See iram0_2_seg for meaning of 0x18 offset in the above.) */
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
/* RTC fast memory (executable). Persists over deep sleep.
|
/* RTC fast memory (executable). Persists over deep sleep.
|
||||||
*/
|
*/
|
||||||
@ -116,3 +120,15 @@ REGION_ALIAS("rtc_data_location", rtc_slow_seg );
|
|||||||
#else
|
#else
|
||||||
REGION_ALIAS("rtc_data_location", rtc_data_seg );
|
REGION_ALIAS("rtc_data_location", rtc_data_seg );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
REGION_ALIAS("default_code_seg", iram0_2_seg);
|
||||||
|
#else
|
||||||
|
REGION_ALIAS("default_code_seg", iram0_0_seg);
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
REGION_ALIAS("default_rodata_seg", drom0_0_seg);
|
||||||
|
#else
|
||||||
|
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
@ -161,12 +161,8 @@ SECTIONS
|
|||||||
mapping[iram0_text]
|
mapping[iram0_text]
|
||||||
|
|
||||||
_iram_text_end = ABSOLUTE(.);
|
_iram_text_end = ABSOLUTE(.);
|
||||||
_iram_end = ABSOLUTE(.);
|
|
||||||
} > iram0_0_seg
|
} > iram0_0_seg
|
||||||
|
|
||||||
ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
|
||||||
"IRAM0 segment data does not fit.")
|
|
||||||
|
|
||||||
.dram0.data :
|
.dram0.data :
|
||||||
{
|
{
|
||||||
_data_start = ABSOLUTE(.);
|
_data_start = ABSOLUTE(.);
|
||||||
@ -312,7 +308,7 @@ SECTIONS
|
|||||||
*(.tbss.*)
|
*(.tbss.*)
|
||||||
_thread_local_end = ABSOLUTE(.);
|
_thread_local_end = ABSOLUTE(.);
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >drom0_0_seg
|
} >default_rodata_seg
|
||||||
|
|
||||||
.flash.text :
|
.flash.text :
|
||||||
{
|
{
|
||||||
@ -334,5 +330,25 @@ SECTIONS
|
|||||||
the flash.text segment.
|
the flash.text segment.
|
||||||
*/
|
*/
|
||||||
_flash_cache_start = ABSOLUTE(0);
|
_flash_cache_start = ABSOLUTE(0);
|
||||||
} >iram0_2_seg
|
} >default_code_seg
|
||||||
|
|
||||||
|
/* Marks the end of IRAM code segment */
|
||||||
|
.iram0.text_end (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN (4);
|
||||||
|
_iram_end = ABSOLUTE(.);
|
||||||
|
} > iram0_0_seg
|
||||||
|
|
||||||
|
/* Marks the end of data, bss and possibly rodata */
|
||||||
|
.dram0.heap_start (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN (8);
|
||||||
|
_heap_start = ABSOLUTE(.);
|
||||||
|
} > dram0_0_seg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT(((_iram_text_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||||
|
"IRAM0 segment data does not fit.")
|
||||||
|
|
||||||
|
ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
|
||||||
|
"DRAM segment data does not fit.")
|
||||||
|
@ -50,8 +50,12 @@ entries:
|
|||||||
|
|
||||||
[scheme:default]
|
[scheme:default]
|
||||||
entries:
|
entries:
|
||||||
|
if APP_BUILD_USE_FLASH_SECTIONS = y:
|
||||||
text -> flash_text
|
text -> flash_text
|
||||||
rodata -> flash_rodata
|
rodata -> flash_rodata
|
||||||
|
else:
|
||||||
|
text -> iram0_text
|
||||||
|
rodata -> dram0_data
|
||||||
data -> dram0_data
|
data -> dram0_data
|
||||||
bss -> dram0_bss
|
bss -> dram0_bss
|
||||||
common -> dram0_bss
|
common -> dram0_bss
|
||||||
|
@ -450,7 +450,7 @@ static void esp_panic_dig_reset(void)
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // CONFIG_ESP32_PANIC_PRINT_REBOOT || CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||||
|
|
||||||
static void putEntry(uint32_t pc, uint32_t sp)
|
static void putEntry(uint32_t pc, uint32_t sp)
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@ PROVIDE ( esp_rom_spiflash_erase_area = 0x400631ac );
|
|||||||
PROVIDE ( esp_rom_spiflash_erase_block = 0x40062c4c );
|
PROVIDE ( esp_rom_spiflash_erase_block = 0x40062c4c );
|
||||||
PROVIDE ( esp_rom_spiflash_erase_chip = 0x40062c14 );
|
PROVIDE ( esp_rom_spiflash_erase_chip = 0x40062c14 );
|
||||||
PROVIDE ( esp_rom_spiflash_erase_sector = 0x40062ccc );
|
PROVIDE ( esp_rom_spiflash_erase_sector = 0x40062ccc );
|
||||||
|
PROVIDE ( esp_rom_spiflash_attach = 0x40062a6c );
|
||||||
PROVIDE ( esp_rom_spiflash_lock = 0x400628f0 );
|
PROVIDE ( esp_rom_spiflash_lock = 0x400628f0 );
|
||||||
PROVIDE ( esp_rom_spiflash_read = 0x40062ed8 );
|
PROVIDE ( esp_rom_spiflash_read = 0x40062ed8 );
|
||||||
PROVIDE ( esp_rom_spiflash_config_readmode = 0x40062b64 ); /* SPIMasterReadModeCnfig */
|
PROVIDE ( esp_rom_spiflash_config_readmode = 0x40062b64 ); /* SPIMasterReadModeCnfig */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
idf_component_register(REQUIRES bootloader)
|
idf_component_register(REQUIRES bootloader)
|
||||||
|
|
||||||
if(NOT BOOTLOADER_BUILD)
|
if(NOT BOOTLOADER_BUILD AND CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||||
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_FLASH_OPTIONS}")
|
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_FLASH_OPTIONS}")
|
||||||
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
|
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
|
||||||
"${ESPTOOLPY_FLASH_PROJECT_OPTIONS}"
|
"${ESPTOOLPY_FLASH_PROJECT_OPTIONS}"
|
||||||
|
@ -68,7 +68,11 @@ endif
|
|||||||
APP_BIN_UNSIGNED ?= $(APP_BIN)
|
APP_BIN_UNSIGNED ?= $(APP_BIN)
|
||||||
|
|
||||||
$(APP_BIN_UNSIGNED): $(APP_ELF) $(ESPTOOLPY_SRC) | check_python_dependencies
|
$(APP_BIN_UNSIGNED): $(APP_ELF) $(ESPTOOLPY_SRC) | check_python_dependencies
|
||||||
|
ifeq ("$(CONFIG_APP_BUILD_GENERATE_BINARIES)","y")
|
||||||
$(ESPTOOLPY) elf2image $(ESPTOOL_FLASH_OPTIONS) $(ESPTOOL_ELF2IMAGE_OPTIONS) -o $@ $<
|
$(ESPTOOLPY) elf2image $(ESPTOOL_FLASH_OPTIONS) $(ESPTOOL_ELF2IMAGE_OPTIONS) -o $@ $<
|
||||||
|
else
|
||||||
|
@echo "Skipping the BIN generation"
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||||
encrypted-flash: all_binaries $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) partition_table_get_info | check_python_dependencies
|
encrypted-flash: all_binaries $(ESPTOOLPY_SRC) $(call prereq_if_explicit,erase_flash) partition_table_get_info | check_python_dependencies
|
||||||
|
@ -78,6 +78,7 @@ set(PROJECT_BIN "${elf_name}.bin")
|
|||||||
#
|
#
|
||||||
# Add 'app.bin' target - generates with elf2image
|
# Add 'app.bin' target - generates with elf2image
|
||||||
#
|
#
|
||||||
|
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||||
add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
||||||
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
|
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
|
||||||
-o "${build_dir}/${unsigned_project_binary}" "${elf}"
|
-o "${build_dir}/${unsigned_project_binary}" "${elf}"
|
||||||
@ -89,13 +90,16 @@ add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
|||||||
COMMENT "Generating binary image from built executable"
|
COMMENT "Generating binary image from built executable"
|
||||||
)
|
)
|
||||||
add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp")
|
add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp")
|
||||||
|
endif()
|
||||||
|
|
||||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||||
"${build_dir}/${unsigned_project_binary}"
|
"${build_dir}/${unsigned_project_binary}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||||
add_custom_target(app ALL DEPENDS gen_project_binary)
|
add_custom_target(app ALL DEPENDS gen_project_binary)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS)
|
if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS)
|
||||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||||
|
@ -29,7 +29,7 @@ extern soc_reserved_region_t soc_reserved_memory_region_end;
|
|||||||
These variables have the start and end of the data and static IRAM
|
These variables have the start and end of the data and static IRAM
|
||||||
area used by the program. Defined in the linker script.
|
area used by the program. Defined in the linker script.
|
||||||
*/
|
*/
|
||||||
extern int _data_start, _static_data_end, _iram_start, _iram_end;
|
extern int _data_start, _heap_start, _iram_start, _iram_end;
|
||||||
|
|
||||||
/* static DRAM & IRAM chunks */
|
/* static DRAM & IRAM chunks */
|
||||||
static const size_t EXTRA_RESERVED_REGIONS = 2;
|
static const size_t EXTRA_RESERVED_REGIONS = 2;
|
||||||
@ -67,8 +67,8 @@ static void s_prepare_reserved_regions(soc_reserved_region_t *reserved, size_t c
|
|||||||
(count - EXTRA_RESERVED_REGIONS) * sizeof(soc_reserved_region_t));
|
(count - EXTRA_RESERVED_REGIONS) * sizeof(soc_reserved_region_t));
|
||||||
|
|
||||||
/* Add the EXTRA_RESERVED_REGIONS at the beginning */
|
/* Add the EXTRA_RESERVED_REGIONS at the beginning */
|
||||||
reserved[0].start = (intptr_t)&_data_start; /* DRAM used by data+bss */
|
reserved[0].start = (intptr_t)&_data_start; /* DRAM used by data+bss and possibly rodata */
|
||||||
reserved[0].end = (intptr_t)&_static_data_end;
|
reserved[0].end = (intptr_t)&_heap_start;
|
||||||
reserved[1].start = (intptr_t)&_iram_start; /* IRAM used by code */
|
reserved[1].start = (intptr_t)&_iram_start; /* IRAM used by code */
|
||||||
reserved[1].end = (intptr_t)&_iram_end;
|
reserved[1].end = (intptr_t)&_iram_end;
|
||||||
|
|
||||||
|
13
examples/get-started/hello_world/.gdbinit.ci
Normal file
13
examples/get-started/hello_world/.gdbinit.ci
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Connect to a running instance of OpenOCD
|
||||||
|
target remote 127.0.0.1:3333
|
||||||
|
# Reset and halt the target
|
||||||
|
mon reset halt
|
||||||
|
# Run to a specific point in ROM code,
|
||||||
|
# where most of initialization is complete.
|
||||||
|
thb *0x40007901
|
||||||
|
c
|
||||||
|
# Load the application into RAM
|
||||||
|
load
|
||||||
|
# Run till app_main
|
||||||
|
tb app_main
|
||||||
|
c
|
129
examples/get-started/hello_world/loadable_elf_example_test.py
Normal file
129
examples/get-started/hello_world/loadable_elf_example_test.py
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import os
|
||||||
|
import pexpect
|
||||||
|
import serial
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
try:
|
||||||
|
import IDF
|
||||||
|
except ImportError:
|
||||||
|
test_fw_path = os.getenv('TEST_FW_PATH')
|
||||||
|
if test_fw_path and test_fw_path not in sys.path:
|
||||||
|
sys.path.insert(0, test_fw_path)
|
||||||
|
import IDF
|
||||||
|
|
||||||
|
import Utility
|
||||||
|
|
||||||
|
|
||||||
|
class CustomProcess(object):
|
||||||
|
def __init__(self, cmd, logfile):
|
||||||
|
self.f = open(logfile, 'wb')
|
||||||
|
self.p = pexpect.spawn(cmd, timeout=60, logfile=self.f)
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.p.terminate(force=True)
|
||||||
|
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
self.close()
|
||||||
|
self.f.close()
|
||||||
|
|
||||||
|
|
||||||
|
class OCDProcess(CustomProcess):
|
||||||
|
def __init__(self, proj_path):
|
||||||
|
cmd = 'openocd -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg'
|
||||||
|
log_file = os.path.join(proj_path, 'openocd.log')
|
||||||
|
super(OCDProcess, self).__init__(cmd, log_file)
|
||||||
|
i = self.p.expect_exact(['Info : Listening on port 3333 for gdb connections', 'Error:'])
|
||||||
|
if i == 0:
|
||||||
|
Utility.console_log('openocd is listening for gdb connections')
|
||||||
|
else:
|
||||||
|
raise RuntimeError('openocd initialization has failed')
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
try:
|
||||||
|
self.p.sendcontrol('c')
|
||||||
|
self.p.expect_exact('shutdown command invoked')
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('openocd needs to be killed', 'O')
|
||||||
|
super(OCDProcess, self).close()
|
||||||
|
|
||||||
|
|
||||||
|
class GDBProcess(CustomProcess):
|
||||||
|
def __init__(self, proj_path, elf_path):
|
||||||
|
cmd = 'xtensa-esp32-elf-gdb -x {} --directory={} {}'.format(os.path.join(proj_path, '.gdbinit.ci'),
|
||||||
|
os.path.join(proj_path, 'main'),
|
||||||
|
elf_path)
|
||||||
|
log_file = os.path.join(proj_path, 'gdb.log')
|
||||||
|
super(GDBProcess, self).__init__(cmd, log_file)
|
||||||
|
self.p.sendline('') # it is for "---Type <return> to continue, or q <return> to quit---"
|
||||||
|
i = self.p.expect_exact(['Thread 1 hit Temporary breakpoint 2, app_main ()',
|
||||||
|
'Load failed'])
|
||||||
|
if i == 0:
|
||||||
|
Utility.console_log('gdb is at breakpoint')
|
||||||
|
else:
|
||||||
|
raise RuntimeError('Load failed: probably the ELF file was not built for loading with gdb')
|
||||||
|
self.p.expect_exact('(gdb)')
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
try:
|
||||||
|
self.p.sendline('q')
|
||||||
|
self.p.expect_exact('Quit anyway? (y or n)')
|
||||||
|
self.p.sendline('y')
|
||||||
|
self.p.expect_exact('Ending remote debugging.')
|
||||||
|
except Exception:
|
||||||
|
Utility.console_log('gdb needs to be killed', 'O')
|
||||||
|
super(GDBProcess, self).close()
|
||||||
|
|
||||||
|
def break_till_end(self):
|
||||||
|
self.p.sendline('b esp_restart')
|
||||||
|
self.p.sendline('c')
|
||||||
|
self.p.expect_exact('Thread 1 hit Breakpoint 3, esp_restart ()')
|
||||||
|
|
||||||
|
|
||||||
|
class SerialThread(object):
|
||||||
|
def run(self, log_path, exit_event):
|
||||||
|
with serial.Serial('/dev/ttyUSB1', 115200) as ser, open(log_path, 'wb') as f:
|
||||||
|
while True:
|
||||||
|
f.write(ser.read(ser.in_waiting))
|
||||||
|
if exit_event.is_set():
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
def __init__(self, log_path):
|
||||||
|
self.exit_event = threading.Event()
|
||||||
|
self.t = threading.Thread(target=self.run, args=(log_path, self.exit_event,))
|
||||||
|
self.t.start()
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
self.exit_event.set()
|
||||||
|
self.t.join(60)
|
||||||
|
if self.t.is_alive():
|
||||||
|
Utility.console_log('The pyserial thread is still alive', 'O')
|
||||||
|
|
||||||
|
|
||||||
|
@IDF.idf_example_test(env_tag="test_jtag_arm")
|
||||||
|
def test_examples_loadable_elf(env, extra_data):
|
||||||
|
|
||||||
|
idf_path = os.environ['IDF_PATH']
|
||||||
|
rel_project_path = os.path.join('examples', 'get-started', 'hello_world')
|
||||||
|
proj_path = os.path.join(idf_path, rel_project_path)
|
||||||
|
elf_path = os.path.join(IDF.Example(rel_project_path).get_binary_path(rel_project_path), 'hello-world.elf')
|
||||||
|
esp_log_path = os.path.join(proj_path, 'esp.log')
|
||||||
|
|
||||||
|
with SerialThread(esp_log_path):
|
||||||
|
with OCDProcess(proj_path), GDBProcess(proj_path, elf_path) as gdb:
|
||||||
|
gdb.break_till_end()
|
||||||
|
|
||||||
|
if pexpect.run('grep "Restarting now." {}'.format(esp_log_path), withexitstatus=True)[1]:
|
||||||
|
raise RuntimeError('Expected output from ESP was not received')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
test_examples_loadable_elf()
|
6
examples/get-started/hello_world/sdkconfig.ci
Normal file
6
examples/get-started/hello_world/sdkconfig.ci
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
CONFIG_APP_BUILD_TYPE_ELF_RAM=y
|
||||||
|
CONFIG_VFS_SUPPORT_TERMIOS=
|
||||||
|
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||||
|
CONFIG_ESP32_PANIC_PRINT_HALT=y
|
||||||
|
CONFIG_ESP32_DEBUG_STUBS_ENABLE=
|
||||||
|
CONFIG_ESP_ERR_TO_NAME_LOOKUP=
|
@ -320,9 +320,15 @@ ifndef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
|||||||
endif
|
endif
|
||||||
@echo "To flash app & partition table, run 'make flash' or:"
|
@echo "To flash app & partition table, run 'make flash' or:"
|
||||||
else
|
else
|
||||||
|
ifdef CONFIG_APP_BUILD_GENERATE_BINARIES
|
||||||
@echo "To flash all build output, run 'make flash' or:"
|
@echo "To flash all build output, run 'make flash' or:"
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
ifdef CONFIG_APP_BUILD_GENERATE_BINARIES
|
||||||
@echo $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS)
|
@echo $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS)
|
||||||
|
else
|
||||||
|
@echo "Binary is not available for flashing"
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
# If we have `version.txt` then prefer that for extracting IDF version
|
# If we have `version.txt` then prefer that for extracting IDF version
|
||||||
@ -533,6 +539,7 @@ $(APP_ELF): $(foreach libcomp,$(COMPONENT_LIBRARIES),$(BUILD_DIR_BASE)/$(libcomp
|
|||||||
$(CC) $(LDFLAGS) -o $@ -Wl,-Map=$(APP_MAP)
|
$(CC) $(LDFLAGS) -o $@ -Wl,-Map=$(APP_MAP)
|
||||||
|
|
||||||
app: $(APP_BIN) partition_table_get_info
|
app: $(APP_BIN) partition_table_get_info
|
||||||
|
ifeq ("$(CONFIG_APP_BUILD_GENERATE_BINARIES)","y")
|
||||||
ifeq ("$(CONFIG_SECURE_BOOT_ENABLED)$(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)","y") # secure boot enabled, but remote sign app image
|
ifeq ("$(CONFIG_SECURE_BOOT_ENABLED)$(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)","y") # secure boot enabled, but remote sign app image
|
||||||
@echo "App built but not signed. Signing step via espsecure.py:"
|
@echo "App built but not signed. Signing step via espsecure.py:"
|
||||||
@echo "espsecure.py sign_data --keyfile KEYFILE $(APP_BIN)"
|
@echo "espsecure.py sign_data --keyfile KEYFILE $(APP_BIN)"
|
||||||
@ -542,6 +549,9 @@ else
|
|||||||
@echo "App built. Default flash app command is:"
|
@echo "App built. Default flash app command is:"
|
||||||
@echo $(ESPTOOLPY_WRITE_FLASH) $(APP_OFFSET) $(APP_BIN)
|
@echo $(ESPTOOLPY_WRITE_FLASH) $(APP_OFFSET) $(APP_BIN)
|
||||||
endif
|
endif
|
||||||
|
else
|
||||||
|
@echo "Application in not built and cannot be flashed."
|
||||||
|
endif
|
||||||
|
|
||||||
all_binaries: $(APP_BIN)
|
all_binaries: $(APP_BIN)
|
||||||
|
|
||||||
|
@ -202,6 +202,19 @@ example_test_008:
|
|||||||
- ESP32
|
- ESP32
|
||||||
- Example_Flash_Encryption
|
- Example_Flash_Encryption
|
||||||
|
|
||||||
|
example_test_009:
|
||||||
|
extends: .example_test_template
|
||||||
|
tags:
|
||||||
|
- ESP32
|
||||||
|
- test_jtag_arm
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- $CI_PROJECT_DIR/examples/get-started/hello_world/*.log
|
||||||
|
expire_in: 1 week
|
||||||
|
variables:
|
||||||
|
SETUP_TOOLS: "1"
|
||||||
|
|
||||||
UT_001:
|
UT_001:
|
||||||
extends: .unit_test_template
|
extends: .unit_test_template
|
||||||
parallel: 50
|
parallel: 50
|
||||||
|
@ -924,6 +924,10 @@ def init_cli(verbose_output=None):
|
|||||||
print("Done")
|
print("Done")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not os.path.exists(os.path.join(args.build_dir, "flasher_args.json")):
|
||||||
|
print("Done")
|
||||||
|
return
|
||||||
|
|
||||||
# Otherwise, if we built any binaries print a message about
|
# Otherwise, if we built any binaries print a message about
|
||||||
# how to flash them
|
# how to flash them
|
||||||
def print_flashing_message(title, key):
|
def print_flashing_message(title, key):
|
||||||
|
@ -35,6 +35,9 @@ class IDFApp(App.BaseApp):
|
|||||||
self.binary_path = self.get_binary_path(app_path)
|
self.binary_path = self.get_binary_path(app_path)
|
||||||
self.elf_file = self._get_elf_file_path(self.binary_path)
|
self.elf_file = self._get_elf_file_path(self.binary_path)
|
||||||
assert os.path.exists(self.binary_path)
|
assert os.path.exists(self.binary_path)
|
||||||
|
sdkconfig_dict = self.get_sdkconfig()
|
||||||
|
if "CONFIG_APP_BUILD_GENERATE_BINARIES" in sdkconfig_dict:
|
||||||
|
# There are no flashing targets available when no binaries where generated.
|
||||||
if self.IDF_DOWNLOAD_CONFIG_FILE not in os.listdir(self.binary_path):
|
if self.IDF_DOWNLOAD_CONFIG_FILE not in os.listdir(self.binary_path):
|
||||||
if self.IDF_FLASH_ARGS_FILE not in os.listdir(self.binary_path):
|
if self.IDF_FLASH_ARGS_FILE not in os.listdir(self.binary_path):
|
||||||
msg = ("Neither {} nor {} exists. "
|
msg = ("Neither {} nor {} exists. "
|
||||||
|
@ -70,7 +70,15 @@ void setUp(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
printf("%s", ""); /* sneakily lazy-allocate the reent structure for this test task */
|
printf("%s", ""); /* sneakily lazy-allocate the reent structure for this test task */
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
/* TODO: add sufficient startup code in case of building an ELF file, so that
|
||||||
|
* flash cache is initialized and can work in such mode.
|
||||||
|
* For now this is disabled to allow running unit tests which don't require
|
||||||
|
* flash cache related operations.
|
||||||
|
*/
|
||||||
get_test_data_partition(); /* allocate persistent partition table structures */
|
get_test_data_partition(); /* allocate persistent partition table structures */
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
unity_reset_leak_checks();
|
unity_reset_leak_checks();
|
||||||
test_utils_set_leak_level(CONFIG_UNITY_CRITICAL_LEAK_LEVEL_GENERAL, TYPE_LEAK_CRITICAL, COMP_LEAK_GENERAL);
|
test_utils_set_leak_level(CONFIG_UNITY_CRITICAL_LEAK_LEVEL_GENERAL, TYPE_LEAK_CRITICAL, COMP_LEAK_GENERAL);
|
||||||
|
Loading…
Reference in New Issue
Block a user