Skip to content

Commit dfb0662

Browse files
committed
feat(esp32p4): support eco5 on fpga
1 parent 76d24d2 commit dfb0662

36 files changed

+2011
-80
lines changed

Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ mainmenu "Espressif IoT Development Framework Configuration"
123123
bool
124124
default "y" if IDF_TARGET="esp32p4"
125125
select IDF_TARGET_ARCH_RISCV
126+
select IDF_ENV_FPGA if ESP32P4_REV_MIN_200
127+
select IDF_ENV_BRINGUP if ESP32P4_REV_MIN_200
126128

127129
config IDF_TARGET_ESP32H2
128130
bool

components/bootloader/subproject/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,13 @@ idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${common_req}")
6767
idf_build_set_property(__OUTPUT_SDKCONFIG 0)
6868
# Define a property for the default linker script
6969
set(LD_DEFAULT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/main/ld/${IDF_TARGET}")
70-
idf_build_set_property(BOOTLOADER_LINKER_SCRIPT "${LD_DEFAULT_PATH}/bootloader.ld" APPEND)
7170
idf_build_set_property(BOOTLOADER_LINKER_SCRIPT "${LD_DEFAULT_PATH}/bootloader.rom.ld" APPEND)
7271
project(bootloader)
72+
if(CONFIG_ESP32P4_REV_MIN_200)
73+
target_linker_script("__idf_main" INTERFACE "${LD_DEFAULT_PATH}/bootloader.eco5.ld")
74+
else()
75+
target_linker_script("__idf_main" INTERFACE "${LD_DEFAULT_PATH}/bootloader.ld")
76+
endif()
7377

7478
idf_build_set_property(COMPILE_DEFINITIONS "BOOTLOADER_BUILD=1" APPEND)
7579
idf_build_set_property(COMPILE_DEFINITIONS "NON_OS_BUILD=1" APPEND)
Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
/**
7+
* Simplified memory map for the bootloader.
8+
* Make sure the bootloader can load into main memory without overwriting itself.
9+
*
10+
* ESP32-P4 ROM static data usage is as follows:
11+
* - 0x4ff296b8 - 0x4ff3afc0: Shared buffers, used in UART/USB/SPI download mode only
12+
* - 0x4ff3afc0 - 0x4ff3fba4: CPU1 stack, can be reclaimed as heap after RTOS startup
13+
* - 0x4ff3fba4 - 0x4ff40000: ROM .bss and .data (not easily reclaimable)
14+
*
15+
* The 2nd stage bootloader can take space up to the end of ROM shared
16+
* buffers area (0x4087c610).
17+
*/
18+
19+
/* We consider 0x4087c610 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
20+
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
21+
*/
22+
23+
/* These lengths can be adjusted, if necessary: */
24+
bootloader_usable_dram_end = 0x4ffbcfc0;
25+
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
26+
bootloader_dram_seg_len = 0x5000;
27+
bootloader_iram_loader_seg_len = 0x7000;
28+
bootloader_iram_seg_len = 0x2D00;
29+
30+
/* Start of the lower region is determined by region size and the end of the higher region */
31+
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
32+
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
33+
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len;
34+
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
35+
36+
MEMORY
37+
{
38+
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
39+
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
40+
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
41+
}
42+
43+
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
44+
* If you have changed something above and this assert fails:
45+
* 1. Check what the new value of bootloader_iram_loader_seg start is.
46+
* 2. Update the value in this assert.
47+
* 3. Update SRAM_DRAM_END in components/esp_system/ld/esp32p4/memory.ld.in to the same value.
48+
*/
49+
ASSERT(bootloader_iram_loader_seg_start == 0x4FFAEFC0, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
50+
51+
/* Default entry point: */
52+
ENTRY(call_start_cpu0);
53+
54+
SECTIONS
55+
{
56+
57+
.iram_loader.text :
58+
{
59+
. = ALIGN (16);
60+
_loader_text_start = ABSOLUTE(.);
61+
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
62+
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
63+
*liblog.a:(.literal .text .literal.* .text.*)
64+
*libgcc.a:(.literal .text .literal.* .text.*)
65+
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
66+
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
67+
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
68+
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
69+
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
70+
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
71+
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
72+
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
73+
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
74+
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
75+
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
76+
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
77+
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
78+
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
79+
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
80+
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
81+
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
82+
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
83+
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
84+
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
85+
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
86+
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
87+
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
88+
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
89+
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
90+
*libhal.a:key_mgr_hal.*(.literal.key_mgr_hal_set_key_usage .text.key_mgr_hal_set_key_usage)
91+
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
92+
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
93+
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
94+
*libefuse.a:*.*(.literal .text .literal.* .text.*)
95+
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
96+
*(.fini.literal)
97+
*(.fini)
98+
*(.gnu.version)
99+
_loader_text_end = ABSOLUTE(.);
100+
} > iram_loader_seg
101+
102+
.iram.text :
103+
{
104+
. = ALIGN (16);
105+
*(.entry.text)
106+
*(.init.literal)
107+
*(.init)
108+
} > iram_seg
109+
110+
111+
/* Shared RAM */
112+
.dram0.bss (NOLOAD) :
113+
{
114+
. = ALIGN (8);
115+
_dram_start = ABSOLUTE(.);
116+
_bss_start = ABSOLUTE(.);
117+
*(.dynsbss)
118+
*(.sbss)
119+
*(.sbss.*)
120+
*(.gnu.linkonce.sb.*)
121+
*(.scommon)
122+
*(.sbss2)
123+
*(.sbss2.*)
124+
*(.gnu.linkonce.sb2.*)
125+
*(.dynbss)
126+
*(.bss)
127+
*(.bss.*)
128+
*(.gnu.linkonce.b.*)
129+
*(COMMON)
130+
. = ALIGN (8);
131+
_bss_end = ABSOLUTE(.);
132+
} > dram_seg
133+
134+
.dram0.bootdesc : ALIGN(0x10)
135+
{
136+
_data_start = ABSOLUTE(.);
137+
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
138+
} > dram_seg
139+
140+
.dram0.data :
141+
{
142+
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
143+
*(.data)
144+
*(.data.*)
145+
*(.gnu.linkonce.d.*)
146+
*(.data1)
147+
*(.sdata)
148+
*(.sdata.*)
149+
*(.gnu.linkonce.s.*)
150+
*(.gnu.linkonce.s2.*)
151+
*(.jcr)
152+
_data_end = ABSOLUTE(.);
153+
} > dram_seg
154+
155+
.dram0.rodata :
156+
{
157+
_rodata_start = ABSOLUTE(.);
158+
*(.rodata)
159+
*(.rodata.*)
160+
*(.gnu.linkonce.r.*)
161+
*(.rodata1)
162+
*(.sdata2 .sdata2.* .srodata .srodata.*)
163+
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
164+
*(.xt_except_table)
165+
*(.gcc_except_table)
166+
*(.gnu.linkonce.e.*)
167+
*(.gnu.version_r)
168+
*(.eh_frame_hdr)
169+
*(.eh_frame)
170+
. = (. + 3) & ~ 3;
171+
/* C++ constructor and destructor tables, properly ordered: */
172+
__init_array_start = ABSOLUTE(.);
173+
KEEP (*crtbegin.*(.ctors))
174+
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
175+
KEEP (*(SORT(.ctors.*)))
176+
KEEP (*(.ctors))
177+
__init_array_end = ABSOLUTE(.);
178+
KEEP (*crtbegin.*(.dtors))
179+
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
180+
KEEP (*(SORT(.dtors.*)))
181+
KEEP (*(.dtors))
182+
/* C++ exception handlers table: */
183+
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
184+
*(.xt_except_desc)
185+
*(.gnu.linkonce.h.*)
186+
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
187+
*(.xt_except_desc_end)
188+
*(.dynamic)
189+
*(.gnu.version_d)
190+
_rodata_end = ABSOLUTE(.);
191+
/* Literals are also RO data. */
192+
_lit4_start = ABSOLUTE(.);
193+
*(*.lit4)
194+
*(.lit4.*)
195+
*(.gnu.linkonce.lit4.*)
196+
_lit4_end = ABSOLUTE(.);
197+
. = ALIGN(4);
198+
_dram_end = ABSOLUTE(.);
199+
} > dram_seg
200+
201+
.iram.text :
202+
{
203+
_stext = .;
204+
_text_start = ABSOLUTE(.);
205+
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
206+
*(.iram .iram.*) /* catch stray IRAM_ATTR */
207+
*(.fini.literal)
208+
*(.fini)
209+
*(.gnu.version)
210+
211+
/** CPU will try to prefetch up to 16 bytes of
212+
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
213+
* safe access to up to 16 bytes after the last real instruction, add
214+
* dummy bytes to ensure this
215+
*/
216+
. += 16;
217+
218+
_text_end = ABSOLUTE(.);
219+
_etext = .;
220+
} > iram_seg
221+
222+
.riscv.attributes 0: { *(.riscv.attributes) }
223+
224+
/* DWARF 1 */
225+
.debug 0 : { *(.debug) }
226+
.line 0 : { *(.line) }
227+
/* GNU DWARF 1 extensions */
228+
.debug_srcinfo 0 : { *(.debug_srcinfo) }
229+
.debug_sfnames 0 : { *(.debug_sfnames) }
230+
/* DWARF 1.1 and DWARF 2 */
231+
.debug_aranges 0 : { *(.debug_aranges) }
232+
.debug_pubnames 0 : { *(.debug_pubnames) }
233+
/* DWARF 2 */
234+
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
235+
.debug_abbrev 0 : { *(.debug_abbrev) }
236+
.debug_line 0 : { *(.debug_line) }
237+
.debug_frame 0 : { *(.debug_frame) }
238+
.debug_str 0 : { *(.debug_str) }
239+
.debug_loc 0 : { *(.debug_loc) }
240+
.debug_macinfo 0 : { *(.debug_macinfo) }
241+
.debug_pubtypes 0 : { *(.debug_pubtypes) }
242+
/* DWARF 3 */
243+
.debug_ranges 0 : { *(.debug_ranges) }
244+
/* SGI/MIPS DWARF 2 extensions */
245+
.debug_weaknames 0 : { *(.debug_weaknames) }
246+
.debug_funcnames 0 : { *(.debug_funcnames) }
247+
.debug_typenames 0 : { *(.debug_typenames) }
248+
.debug_varnames 0 : { *(.debug_varnames) }
249+
/* GNU DWARF 2 extensions */
250+
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
251+
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
252+
/* DWARF 4 */
253+
.debug_types 0 : { *(.debug_types) }
254+
/* DWARF 5 */
255+
.debug_addr 0 : { *(.debug_addr) }
256+
.debug_line_str 0 : { *(.debug_line_str) }
257+
.debug_loclists 0 : { *(.debug_loclists) }
258+
.debug_macro 0 : { *(.debug_macro) }
259+
.debug_names 0 : { *(.debug_names) }
260+
.debug_rnglists 0 : { *(.debug_rnglists) }
261+
.debug_str_offsets 0 : { *(.debug_str_offsets) }
262+
263+
.comment 0 : { *(.comment) }
264+
.note.GNU-stack 0: { *(.note.GNU-stack) }
265+
266+
/**
267+
* Discarding .rela.* sections results in the following mapping:
268+
* .rela.text.* -> .text.*
269+
* .rela.data.* -> .data.*
270+
* And so forth...
271+
*/
272+
/DISCARD/ : { *(.rela.*) }
273+
274+
/**
275+
* This section is not included in the binary image; it is only present in the ELF file.
276+
* It is used to keep certain symbols in the ELF file.
277+
*/
278+
.noload 0 (INFO) :
279+
{
280+
_noload_keep_in_elf_start = ABSOLUTE(.);
281+
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
282+
_noload_keep_in_elf_end = ABSOLUTE(.);
283+
}
284+
}
285+
286+
287+
/**
288+
* Appendix: Memory Usage of ROM bootloader
289+
*
290+
* 0x4ff296b8 ------------------> _dram0_0_start
291+
* | |
292+
* | |
293+
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
294+
* | |
295+
* | |
296+
* 0x4ff3afc0 ------------------> __stack_sentry
297+
* | |
298+
* | | 2. Startup pro cpu stack (freed when IDF app is running)
299+
* | |
300+
* 0x4ff3cfc0 ------------------> __stack (pro cpu)
301+
* | |
302+
* | | Startup app cpu stack
303+
* | |
304+
* 0x4ff3efc0 ------------------> __stack_app (app cpu)
305+
* | |
306+
* | |
307+
* | | 3. Shared memory only used in startup code or nonos/early boot*
308+
* | | (can be freed when IDF runs)
309+
* | |
310+
* | |
311+
* 0x4ff3fba4 ------------------> _dram0_rtos_reserved_start
312+
* | |
313+
* | |
314+
* | | 4. Shared memory used in startup code and when IDF runs
315+
* | |
316+
* | |
317+
* 0x4ff3ff94 ------------------> _dram0_rtos_reserved_end
318+
* | |
319+
* 0x4ff3ffc8 ------------------> _data_start_interface
320+
* | |
321+
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
322+
* | |
323+
* 0x4ff40000 ------------------> _data_end_interface
324+
*/

components/bootloader_support/src/esp_image_format.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,11 @@ static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t
387387
}
388388

389389
#ifdef BOOTLOADER_BUILD
390+
#if CONFIG_ESP32P4_REV_MIN_200 // TODO: IDF-13410
391+
#define ROM_STACK_START (SOC_ROM_STACK_START_ECO5)
392+
#else
393+
#define ROM_STACK_START (SOC_ROM_STACK_START)
394+
#endif
390395
/* Check the region load_addr - load_end doesn't overlap any memory used by the bootloader, registers, or other invalid memory
391396
*/
392397
static bool verify_load_addresses(int segment_index, intptr_t load_addr, intptr_t load_end, bool print_error, bool no_recurse)
@@ -406,7 +411,7 @@ static bool verify_load_addresses(int segment_index, intptr_t load_addr, intptr_
406411
if (esp_ptr_in_dram(load_addr_p) && esp_ptr_in_dram(load_inclusive_end_p)) { /* Writing to DRAM */
407412
/* Check if we're clobbering the stack */
408413
intptr_t sp = (intptr_t)esp_cpu_get_sp();
409-
if (bootloader_util_regions_overlap(sp - STACK_LOAD_HEADROOM, SOC_ROM_STACK_START,
414+
if (bootloader_util_regions_overlap(sp - STACK_LOAD_HEADROOM, ROM_STACK_START,
410415
load_addr, load_end)) {
411416
reason = "overlaps bootloader stack";
412417
goto invalid;

components/esp_hw_support/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ menu "Hardware Settings"
264264
config ESP_BRINGUP_BYPASS_CPU_CLK_SETTING
265265
bool
266266
default y if !SOC_CLK_TREE_SUPPORTED
267+
default y if ESP32P4_REV_MIN_200
267268
default n
268269
help
269270
This option is only used for new chip bringup, when
@@ -273,6 +274,7 @@ menu "Hardware Settings"
273274
config ESP_BRINGUP_BYPASS_RANDOM_SETTING
274275
bool
275276
default y if !SOC_RNG_SUPPORTED
277+
default y if ESP32P4_REV_MIN_200
276278
default n
277279
help
278280
This option is only used for new chip bringup, when

0 commit comments

Comments
 (0)