feat(esp32h4): finnal introduce hello world

This commit is contained in:
Chen Jichang
2025-03-06 16:43:12 +08:00
parent 9fd0f634d2
commit 45ba78940f
45 changed files with 6088 additions and 92 deletions

View File

@ -13,6 +13,7 @@ extra_default_build_targets:
bypass_check_test_targets: bypass_check_test_targets:
- esp32h21 - esp32h21
- esp32h4
# #
# These lines would # These lines would

View File

@ -147,6 +147,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
config IDF_TARGET_ESP32H4 config IDF_TARGET_ESP32H4
bool bool
default "y" if IDF_TARGET="esp32h4" default "y" if IDF_TARGET="esp32h4"
select FREERTOS_UNICORE # TODO: [ESP32H4] IDF-12319, need remove
select IDF_TARGET_ARCH_RISCV select IDF_TARGET_ARCH_RISCV
select IDF_ENV_FPGA select IDF_ENV_FPGA
select IDF_ENV_BRINGUP select IDF_ENV_BRINGUP

View File

@ -8,7 +8,7 @@ menu "Bootloader config"
hex hex
default 0x1000 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 default 0x1000 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2
# the first 2 sectors are reserved for the key manager with AES-XTS (flash encryption) purpose # the first 2 sectors are reserved for the key manager with AES-XTS (flash encryption) purpose
default 0x2000 if IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C5 default 0x2000 if IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32H4
default 0x0 default 0x0
help help
Offset address that 2nd bootloader will be flashed to. Offset address that 2nd bootloader will be flashed to.

View File

@ -0,0 +1,304 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
*
* ESP32-H4 ROM static data usage is as follows:
* - 0x4084d350 - 0x4085b350: Shared buffers, used in UART/USB/SPI download mode only
* - 0x4085b350 - 0x4085d350: PRO CPU stack, can be reclaimed as heap after RTOS startup
* - 0x4085d350 - 0x40860000: ROM .bss and .data (not easily reclaimable)
*
* The 2nd stage bootloader can take space up to the end of ROM shared
* buffers area (0x4085b350).
*/
/* We consider 0x4085b350 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
*/
/* These lengths can be adjusted, if necessary: */
bootloader_usable_dram_end = 0x4085d350;
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
bootloader_dram_seg_len = 0x5000;
bootloader_iram_loader_seg_len = 0x7000;
bootloader_iram_seg_len = 0x2200;
/* Start of the lower region is determined by region size and the end of the higher region */
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len;
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
MEMORY
{
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
}
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
* If you have changed something above and this assert fails:
* 1. Check what the new value of bootloader_iram_loader_seg start is.
* 2. Update the value in this assert.
* 3. Update SRAM_SEG_END in components/esp_system/ld/esp32h4/memory.ld.in to the same value.
*/
ASSERT(bootloader_iram_loader_seg_start == 0x4084f350, "bootloader_iram_loader_seg_start inconsistent with SRAM_SEG_END");
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} > dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .srodata .srodata.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} > dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
}
/**
* Appendix: Memory Usage of ROM bootloader
*
* 0x4084d350 ------------------> _dram0_0_start
* | |
* | |
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
* | |
* | |
* 0x4085b350 ------------------> __stack_sentry
* | |
* | | 2. Startup pro cpu stack (freed when IDF app is running)
* | |
* 0x4085d350 ------------------> __stack (pro cpu)
* | |
* | |
* | | 3. Shared memory only used in startup code or nonos/early boot*
* | | (can be freed when IDF runs)
* | |
* | |
* 0x4085fea8 ------------------> _dram0_rtos_reserved_start
* | |
* | |
* | | 4. Shared memory used in startup code and when IDF runs
* | |
* | |
* 0x4085ffb4 ------------------> _dram0_rtos_reserved_end
* | |
* 0x4085ffc4 ------------------> _data_start_interface
* | |
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
* | |
* 0x40860000 ------------------> _data_end_interface
*/

View File

@ -0,0 +1,6 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* No definition for ESP32-H4 target */

View File

@ -0,0 +1,277 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <assert.h>
#include "string.h"
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_rom_gpio.h"
#include "esp_rom_efuse.h"
#include "rom/spi_flash.h"
#include "rom/efuse.h"
#include "soc/efuse_reg.h"
#include "soc/spi_mem_reg.h"
#include "soc/soc_caps.h"
#include "flash_qio_mode.h"
#include "bootloader_flash_config.h"
#include "bootloader_common.h"
#include "bootloader_flash_priv.h"
#include "bootloader_init.h"
#include "hal/mmu_hal.h"
#include "hal/mmu_ll.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
static const char *TAG = "boot.esp32h4";
void bootloader_flash_update_id()
{
esp_rom_spiflash_chip_t *chip = &rom_spiflash_legacy_data->chip;
chip->device_id = bootloader_read_flash_id();
}
void IRAM_ATTR bootloader_flash_cs_timing_config()
{
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
}
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
{
uint32_t spi_clk_div = 0;
switch (pfhdr->spi_speed) {
case ESP_IMAGE_SPI_SPEED_DIV_1:
spi_clk_div = 1;
break;
case ESP_IMAGE_SPI_SPEED_DIV_2:
spi_clk_div = 2;
break;
case ESP_IMAGE_SPI_SPEED_DIV_3:
spi_clk_div = 3;
break;
case ESP_IMAGE_SPI_SPEED_DIV_4:
spi_clk_div = 4;
break;
default:
break;
}
esp_rom_spiflash_config_clk(spi_clk_div, 0);
}
void IRAM_ATTR bootloader_configure_spi_pins(int drv)
{
uint8_t clk_gpio_num = MSPI_IOMUX_PIN_NUM_CLK;
uint8_t q_gpio_num = MSPI_IOMUX_PIN_NUM_MISO;
uint8_t d_gpio_num = MSPI_IOMUX_PIN_NUM_MOSI;
uint8_t cs0_gpio_num = MSPI_IOMUX_PIN_NUM_CS0;
uint8_t hd_gpio_num = MSPI_IOMUX_PIN_NUM_HD;
uint8_t wp_gpio_num = MSPI_IOMUX_PIN_NUM_WP;
esp_rom_gpio_pad_set_drv(clk_gpio_num, drv);
esp_rom_gpio_pad_set_drv(q_gpio_num, drv);
esp_rom_gpio_pad_set_drv(d_gpio_num, drv);
esp_rom_gpio_pad_set_drv(cs0_gpio_num, drv);
esp_rom_gpio_pad_set_drv(hd_gpio_num, drv);
esp_rom_gpio_pad_set_drv(wp_gpio_num, drv);
}
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
{
uint32_t size;
switch (bootloader_hdr->spi_size) {
case ESP_IMAGE_FLASH_SIZE_1MB:
size = 1;
break;
case ESP_IMAGE_FLASH_SIZE_2MB:
size = 2;
break;
case ESP_IMAGE_FLASH_SIZE_4MB:
size = 4;
break;
case ESP_IMAGE_FLASH_SIZE_8MB:
size = 8;
break;
case ESP_IMAGE_FLASH_SIZE_16MB:
size = 16;
break;
default:
size = 2;
}
// Set flash chip size
esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: [ESP32H4] IDF-12290 set mode
}
static void print_flash_info(const esp_image_header_t *bootloader_hdr)
{
ESP_EARLY_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
ESP_EARLY_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
ESP_EARLY_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
ESP_EARLY_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
ESP_EARLY_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
const char *str;
switch (bootloader_hdr->spi_speed) {
case ESP_IMAGE_SPI_SPEED_DIV_2:
str = "32MHz";
break;
case ESP_IMAGE_SPI_SPEED_DIV_4:
str = "16MHz";
break;
case ESP_IMAGE_SPI_SPEED_DIV_1:
str = "64MHz";
break;
default:
str = "16MHz";
break;
}
ESP_EARLY_LOGI(TAG, "SPI Speed : %s", str);
/* SPI mode could have been set to QIO during boot already,
so test the SPI registers not the flash header */
esp_rom_spiflash_read_mode_t spi_mode = bootloader_flash_get_spi_mode();
switch (spi_mode) {
case ESP_ROM_SPIFLASH_QIO_MODE:
str = "QIO";
break;
case ESP_ROM_SPIFLASH_QOUT_MODE:
str = "QOUT";
break;
case ESP_ROM_SPIFLASH_DIO_MODE:
str = "DIO";
break;
case ESP_ROM_SPIFLASH_DOUT_MODE:
str = "DOUT";
break;
case ESP_ROM_SPIFLASH_FASTRD_MODE:
str = "FAST READ";
break;
default:
str = "SLOW READ";
break;
}
ESP_EARLY_LOGI(TAG, "SPI Mode : %s", str);
switch (bootloader_hdr->spi_size) {
case ESP_IMAGE_FLASH_SIZE_1MB:
str = "1MB";
break;
case ESP_IMAGE_FLASH_SIZE_2MB:
str = "2MB";
break;
case ESP_IMAGE_FLASH_SIZE_4MB:
str = "4MB";
break;
case ESP_IMAGE_FLASH_SIZE_8MB:
str = "8MB";
break;
case ESP_IMAGE_FLASH_SIZE_16MB:
str = "16MB";
break;
default:
str = "2MB";
break;
}
ESP_EARLY_LOGI(TAG, "SPI Flash Size : %s", str);
}
static void IRAM_ATTR bootloader_init_flash_configure(void)
{
bootloader_configure_spi_pins(1);
bootloader_flash_cs_timing_config();
}
static void bootloader_spi_flash_resume(void)
{
bootloader_execute_flash_command(CMD_RESUME, 0, 0, 0);
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
}
esp_err_t bootloader_init_spi_flash(void)
{
bootloader_init_flash_configure();
bootloader_spi_flash_resume();
bootloader_flash_unlock();
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
bootloader_enable_qio_mode();
#endif
print_flash_info(&bootloader_image_hdr);
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
update_flash_config(&bootloader_image_hdr);
cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
//ensure the flash is write-protected
bootloader_enable_wp();
return ESP_OK;
}
#if CONFIG_APP_BUILD_TYPE_RAM && !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
static void bootloader_flash_set_spi_mode(const esp_image_header_t* pfhdr)
{
esp_rom_spiflash_read_mode_t mode;
switch(pfhdr->spi_mode) {
case ESP_IMAGE_SPI_MODE_QIO:
mode = ESP_ROM_SPIFLASH_QIO_MODE;
break;
case ESP_IMAGE_SPI_MODE_QOUT:
mode = ESP_ROM_SPIFLASH_QOUT_MODE;
break;
case ESP_IMAGE_SPI_MODE_DIO:
mode = ESP_ROM_SPIFLASH_DIO_MODE;
break;
case ESP_IMAGE_SPI_MODE_FAST_READ:
mode = ESP_ROM_SPIFLASH_FASTRD_MODE;
break;
case ESP_IMAGE_SPI_MODE_SLOW_READ:
mode = ESP_ROM_SPIFLASH_SLOWRD_MODE;
break;
default:
mode = ESP_ROM_SPIFLASH_DIO_MODE;
}
esp_rom_spiflash_config_readmode(mode);
}
void bootloader_flash_hardware_init(void)
{
esp_rom_spiflash_attach(0, false);
//init cache hal
cache_hal_init();
//init mmu
mmu_hal_init();
// update flash ID
bootloader_flash_update_id();
// Check and run XMC startup flow
esp_err_t ret = bootloader_flash_xmc_startup();
assert(ret == ESP_OK);
/* Alternative of bootloader_init_spi_flash */
// RAM app doesn't have headers in the flash. Make a default one for it.
esp_image_header_t WORD_ALIGNED_ATTR hdr = {
.spi_mode = ESP_IMAGE_SPI_MODE_DIO,
.spi_speed = ESP_IMAGE_SPI_SPEED_DIV_2,
.spi_size = ESP_IMAGE_FLASH_SIZE_2MB,
};
bootloader_configure_spi_pins(1);
bootloader_flash_set_spi_mode(&hdr);
bootloader_flash_clock_config(&hdr);
bootloader_flash_cs_timing_config();
bootloader_spi_flash_resume();
bootloader_flash_unlock();
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
update_flash_config(&hdr);
cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
//ensure the flash is write-protected
bootloader_enable_wp();
}
#endif //CONFIG_APP_BUILD_TYPE_RAM && !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP

View File

@ -9,7 +9,7 @@
#include "soc/chip_revision.h" #include "soc/chip_revision.h"
#include "hal/efuse_hal.h" #include "hal/efuse_hal.h"
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 &&! CONFIG_IDF_TARGET_ESP32C61 &&! CONFIG_IDF_TARGET_ESP32H21 // TODO: IDF-5645 #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 // TODO: IDF-5645
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#else #else
#include "soc/lp_wdt_reg.h" #include "soc/lp_wdt_reg.h"
@ -136,6 +136,21 @@ __attribute__((weak)) void bootloader_clock_configure(void)
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */ SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */
SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */ SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */
SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_SLEEP_REJECT_INT_CLR); SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_SLEEP_REJECT_INT_CLR);
#elif CONFIG_IDF_TARGET_ESP32H4
// CLR ENA
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */
// TODO [ESP32H4] IDF-12295
// CLEAR_PERI_REG_MASK(LP_ANA_LP_INT_ENA_REG, LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */
CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */
// SET CLR
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */
// TODO [ESP32H4] IDF-12295
// SET_PERI_REG_MASK(LP_ANA_LP_INT_CLR_REG, LP_ANA_BOD_MODE0_LP_INT_CLR); /* BROWN_OUT */
SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */
SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */
SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_SLEEP_REJECT_INT_CLR);
#elif CONFIG_IDF_TARGET_ESP32P4 #elif CONFIG_IDF_TARGET_ESP32P4
// CLR ENA // CLR ENA
CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */ CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_SUPER_WDT_INT_ENA); /* SWD */

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -45,6 +45,10 @@ int bootloader_clock_get_rated_freq_mhz(void)
//TODO: [ESP32H21] IDF-11556, please check //TODO: [ESP32H21] IDF-11556, please check
return 96; return 96;
#elif CONFIG_IDF_TARGET_ESP32H4
//TODO: [ESP32H4] IDF-12322 inherited from verification branch, need check
return 96;
#elif CONFIG_IDF_TARGET_ESP32P4 #elif CONFIG_IDF_TARGET_ESP32P4
return 400; return 400;

View File

@ -0,0 +1,212 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_image_format.h"
#include "flash_qio_mode.h"
#include "esp_rom_gpio.h"
#include "esp_rom_efuse.h"
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"
#include "esp_rom_spiflash.h"
#include "soc/gpio_sig_map.h"
#include "esp_cpu.h"
#include "soc/rtc.h"
#include "soc/spi_periph.h"
#include "soc/cache_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/pcr_reg.h"
#include "soc/bus_monitor_reg.h"
#include "bootloader_common.h"
#include "bootloader_init.h"
#include "bootloader_clock.h"
#include "bootloader_flash_config.h"
#include "bootloader_mem.h"
#include "esp_private/regi2c_ctrl.h"
#include "soc/regi2c_lp_bias.h"
#include "soc/regi2c_bias.h"
#include "soc/hp_system_reg.h"
#include "bootloader_console.h"
#include "bootloader_flash_priv.h"
#include "bootloader_soc.h"
#include "esp_private/bootloader_flash_internal.h"
#include "esp_efuse.h"
#include "hal/mmu_hal.h"
#include "hal/cache_hal.h"
#include "hal/clk_tree_ll.h"
#include "soc/lp_wdt_reg.h"
#include "hal/efuse_hal.h"
#include "hal/lpwdt_ll.h"
static const char *TAG = "boot.esp32h4";
// TODO: [ESP32H4] support core1 bus monitor IDF-12592
static void wdt_reset_cpu0_info_enable(void)
{
REG_SET_BIT(PCR_ASSIST_CONF_REG, PCR_ASSIST_CLK_EN);
REG_CLR_BIT(PCR_ASSIST_CONF_REG, PCR_ASSIST_RST_EN);
REG_WRITE(BUS_MONITOR_CORE_0_RCD_EN_REG, BUS_MONITOR_CORE_0_RCD_PDEBUGEN | BUS_MONITOR_CORE_0_RCD_RECORDEN);
}
static void wdt_reset_info_dump(int cpu)
{
(void) cpu;
// saved PC was already printed by the ROM bootloader.
// nothing to do here.
}
static void bootloader_check_wdt_reset(void)
{
int wdt_rst = 0;
soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
if (rst_reason == RESET_REASON_CORE_RTC_WDT || rst_reason == RESET_REASON_CORE_MWDT0 || rst_reason == RESET_REASON_CORE_MWDT1 ||
rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_MWDT1 || rst_reason == RESET_REASON_CPU0_RTC_WDT) {
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
wdt_rst = 1;
}
if (wdt_rst) {
// if reset by WDT dump info from trace port
wdt_reset_info_dump(0);
}
wdt_reset_cpu0_info_enable();
}
static void bootloader_super_wdt_auto_feed(void)
{
REG_WRITE(LP_WDT_SWD_WPROTECT_REG, LP_WDT_SWD_WKEY_VALUE);
REG_SET_BIT(LP_WDT_SWD_CONFIG_REG, LP_WDT_SWD_AUTO_FEED_EN);
REG_WRITE(LP_WDT_SWD_WPROTECT_REG, 0);
}
void spi_flash_din_num_set(uint8_t spi_num, uint8_t din_num)
{
uint32_t reg_val = (REG_READ(SPI_MEM_DIN_NUM_REG(spi_num)) & (~(SPI_MEM_DIN0_NUM_M | SPI_MEM_DIN1_NUM_M | SPI_MEM_DIN2_NUM_M | SPI_MEM_DIN3_NUM_M | SPI_MEM_DIN4_NUM_M | SPI_MEM_DIN5_NUM_M | SPI_MEM_DIN6_NUM_M | SPI_MEM_DIN7_NUM_M | SPI_MEM_DINS_NUM_M)))
| (din_num << SPI_MEM_DIN0_NUM_S) | (din_num << SPI_MEM_DIN1_NUM_S) | (din_num << SPI_MEM_DIN2_NUM_S) | (din_num << SPI_MEM_DIN3_NUM_S)
| (din_num << SPI_MEM_DIN4_NUM_S) | (din_num << SPI_MEM_DIN5_NUM_S) | (din_num << SPI_MEM_DIN6_NUM_S) | (din_num << SPI_MEM_DIN7_NUM_S) | (din_num << SPI_MEM_DINS_NUM_S);
REG_WRITE(SPI_MEM_DIN_NUM_REG(spi_num), reg_val);
REG_SET_BIT(SPI_MEM_TIMING_CALI_REG(spi_num), SPI_MEM_TIMING_CALI_UPDATE);
}
void spi_flash_extra_dummy_set(uint8_t spi_num, uint8_t extra_dummy)
{
rom_spiflash_legacy_data->dummy_len_plus[spi_num] = extra_dummy;
}
/*
* din mode din_num dummy
1 0 1
0 0 0
1 0 2
0 0 1
1 0 3
0 0 2
1 0 4
0 0 3
*/
static inline void bootloader_hardware_init(void)
{
// TODO: [ESP32H4] IDF-12315
ESP_EARLY_LOGE(TAG, "Analog i2c mst clk enable skipped!\n");
/* Enable analog i2c master clock */
// SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN);
// SET_PERI_REG_MASK(MODEM_LPCON_I2C_MST_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_SEL_160M);
}
static inline void bootloader_ana_reset_config(void)
{
//Enable super WDT reset.
bootloader_ana_super_wdt_reset_config(true);
//Enable BOD reset
//TODO: [ESP32H4] IDF-12300 need check
}
static inline void bootloader_config_dcache(void)
{
REG_SET_BIT(LP_AON_SRAM_USAGE_CONF_REG, LP_AON_DCACHE_USAGE);
}
static inline void bootloader_config_icache1(void)
{
// TODO: [ESP32H4] IDF-12289
#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
REG_CLR_BIT(LP_AON_SRAM_USAGE_CONF_REG, LP_AON_ICACHE1_USAGE);
#else
REG_SET_BIT(LP_AON_SRAM_USAGE_CONF_REG, LP_AON_ICACHE1_USAGE);
#endif
}
esp_err_t bootloader_init(void)
{
esp_err_t ret = ESP_OK;
bootloader_hardware_init();
bootloader_ana_reset_config();
bootloader_super_wdt_auto_feed();
// In RAM_APP, memory will be initialized in `call_start_cpu0`
#if !CONFIG_APP_BUILD_TYPE_RAM
// protect memory region
bootloader_init_mem();
/* check that static RAM is after the stack */
assert(&_bss_start <= &_bss_end);
assert(&_data_start <= &_data_end);
// clear bss section
bootloader_clear_bss_section();
#endif // !CONFIG_APP_BUILD_TYPE_RAM
// init eFuse virtual mode (read eFuses to RAM)
#ifdef CONFIG_EFUSE_VIRTUAL
ESP_EARLY_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
esp_efuse_init_virtual_mode_in_ram();
#endif
#endif
// config clock
bootloader_clock_configure();
// initialize console, from now on, we can use esp_log
bootloader_console_init();
/* print 2nd bootloader banner */
bootloader_print_banner();
#if !CONFIG_APP_BUILD_TYPE_RAM
//init cache hal
cache_hal_init();
//init mmu
mmu_hal_init();
// update flash ID
bootloader_flash_update_id();
// Check and run XMC startup flow
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
return ret;
}
// read bootloader header
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
return ret;
}
// read chip revision and check if it's compatible to bootloader
if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
return ret;
}
// initialize spi flash
if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
return ret;
}
#endif // !CONFIG_APP_BUILD_TYPE_RAM
bootloader_config_dcache();
bootloader_config_icache1();
// check whether a WDT reset happened
bootloader_check_wdt_reset();
// config WDT
bootloader_config_wdt();
// enable RNG early entropy source
bootloader_enable_random();
return ret;
}

View File

@ -0,0 +1,44 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "bootloader_sha.h"
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <sys/param.h>
#include "rom/sha.h"
static SHA_CTX ctx;
bootloader_sha256_handle_t bootloader_sha256_start()
{
// Enable SHA hardware
ets_sha_enable();
ets_sha_init(&ctx, SHA2_256);
return &ctx; // Meaningless non-NULL value
}
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
{
assert(handle != NULL);
/* H4 secure boot key field consists of 1 byte of curve identifier and 64 bytes of ECDSA public key.
* While verifying the signature block, we need to calculate the SHA of this key field which is of 65 bytes.
* ets_sha_update handles it cleanly so we can safely remove the check:
* assert(data_len % 4) == 0
*/
ets_sha_update(&ctx, data, data_len, false);
}
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
{
assert(handle != NULL);
if (digest == NULL) {
bzero(&ctx, sizeof(ctx));
return;
}
ets_sha_finish(&ctx, digest);
}

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <assert.h>
#include "soc/soc.h"
#include "soc/lp_analog_peri_reg.h"
//TODO: [ESP32H4] IDF-12300 inherited from verification branch, need check
void bootloader_ana_super_wdt_reset_config(bool enable)
{
//H4 doesn't support bypass super WDT reset
// assert(enable);
// REG_CLR_BIT(LP_ANA_FIB_ENABLE_REG, LP_ANALOG_PERI_LP_ANA_FIB_SUPER_WDT_RST);
}
//Not supported but common bootloader calls the function. Do nothing
void bootloader_ana_clock_glitch_reset_config(bool enable)
{
(void)enable;
}

View File

@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <strings.h>
#include "esp_flash_encrypt.h"
#include "esp_secure_boot.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_log.h"
#include "sdkconfig.h"
//TODO: [ESP32H4] IDF-12261
static __attribute__((unused)) const char *TAG = "flash_encrypt";
esp_err_t esp_flash_encryption_enable_secure_features(void)
{
abort();
return ESP_OK;
}

View File

@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <strings.h>
#include "esp_flash_encrypt.h"
#include "esp_secure_boot.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_log.h"
#include "sdkconfig.h"
//TODO: [ESP32H4] IDF-12262
static __attribute__((unused)) const char *TAG = "secure_boot";
esp_err_t esp_secure_boot_enable_secure_features(void)
{
abort();
return ESP_OK;
}

View File

@ -173,6 +173,13 @@ set(public_include_dirs "include" "include/soc" "include/soc/${target}"
"dma/include" "ldo/include" "debug_probe/include" "dma/include" "ldo/include" "debug_probe/include"
"mspi_timing_tuning/include" "power_supply/include") "mspi_timing_tuning/include" "power_supply/include")
if(CONFIG_IDF_TARGET_ESP32H4)
list(REMOVE_ITEM srcs
"sleep_modes.c"
"sleep_gpio.c" # TODO: [ESP32H4] IDF-12279, IDF-12281
)
endif()
idf_component_register(SRCS ${srcs} idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${public_include_dirs} INCLUDE_DIRS ${public_include_dirs}
PRIV_INCLUDE_DIRS port/include include/esp_private PRIV_INCLUDE_DIRS port/include include/esp_private

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -29,7 +29,7 @@
void esp_cpu_stall(int core_id) void esp_cpu_stall(int core_id)
{ {
#if SOC_CPU_CORES_NUM > 1 // We don't allow stalling of the current core #if SOC_CPU_CORES_NUM > 1 // We don't allow stalling of the current core
assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM); assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
cpu_utility_ll_stall_cpu(core_id); cpu_utility_ll_stall_cpu(core_id);
#endif // SOC_CPU_CORES_NUM > 1 #endif // SOC_CPU_CORES_NUM > 1

View File

@ -0,0 +1,58 @@
choice ESP32H4_REV_MIN
prompt "Minimum Supported ESP32-H4 Revision"
default ESP32H4_REV_MIN_0
help
Required minimum chip revision. ESP-IDF will check for it and
reject to boot if the chip revision fails the check.
This ensures the chip used will have some modifications (features, or bugfixes).
The complied binary will only support chips above this revision,
this will also help to reduce binary size.
config ESP32H4_REV_MIN_0
bool "Rev v0.0"
endchoice
config ESP32H4_REV_MIN_FULL
int
default 0 if ESP32H4_REV_MIN_0
config ESP_REV_MIN_FULL
int
default ESP32H4_REV_MIN_FULL
#
# MAX Revision
#
comment "Maximum Supported ESP32-H4 Revision (Rev v0.99)"
# Maximum revision that IDF supports.
# It can not be changed by user.
# Only Espressif can change it when a new version will be supported in IDF.
# Supports all chips starting from ESP32H4_REV_MIN_FULL to ESP32H4_REV_MAX_FULL
config ESP32H4_REV_MAX_FULL
int
default 99
# keep in sync the "Maximum Supported Revision" description with this value
config ESP_REV_MAX_FULL
int
default ESP32H4_REV_MAX_FULL
config ESP_EFUSE_BLOCK_REV_MIN_FULL
int "Minimum Supported ESP32-H4 eFuse Block Revision"
default 0
help
Required minimum eFuse Block revision. ESP-IDF will check it at the 2nd bootloader stage
whether the current image can work correctly for this eFuse Block revision.
So that to avoid running an incompatible image on a SoC that contains breaking change in the eFuse Block.
If you want to update this value to run the image that not compatible with the current eFuse Block revision,
please contact to Espressif's business team for details:
https://www.espressif.com.cn/en/contact-us/sales-questions
config ESP_EFUSE_BLOCK_REV_MAX_FULL
int
default 99
comment "Maximum Supported ESP32-H4 eFuse Block Revision (eFuse Block Rev v0.99)"
# The revision in the comment must correspond to the default value of ESP_EFUSE_BLOCK_REV_MAX_FULL

View File

@ -0,0 +1,39 @@
choice RTC_CLK_SRC
prompt "RTC clock source"
default RTC_CLK_SRC_INT_RC
help
Choose which clock is used as RTC clock source.
config RTC_CLK_SRC_INT_RC
bool "Internal 136kHz RC oscillator"
config RTC_CLK_SRC_EXT_CRYS
bool "External 32kHz crystal"
select ESP_SYSTEM_RTC_EXT_XTAL
config RTC_CLK_SRC_EXT_OSC
bool "External 32kHz oscillator at 32K_XP pin"
select ESP_SYSTEM_RTC_EXT_OSC
config RTC_CLK_SRC_INT_RC32K
bool "Internal 32kHz RC oscillator"
endchoice
config RTC_CLK_CAL_CYCLES
int "Number of cycles for RTC_SLOW_CLK calibration"
default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_RC32K
default 1024 if RTC_CLK_SRC_INT_RC
range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_RC32K
range 0 32766 if RTC_CLK_SRC_INT_RC
help
When the startup code initializes RTC_SLOW_CLK, it can perform
calibration by comparing the RTC_SLOW_CLK frequency with main XTAL
frequency. This option sets the number of RTC_SLOW_CLK cycles measured
by the calibration routine. Higher numbers increase calibration
precision, which may be important for applications which spend a lot of
time in deep sleep. Lower numbers reduce startup time.
When this option is set to 0, clock calibration will not be performed at
startup, and approximate clock frequencies will be assumed:
- 136000 Hz if internal RC oscillator is used as clock source. For this use value 1024.
- 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more.
In case more value will help improve the definition of the launch of the crystal.
If the crystal could not start, it will be switched to internal RC.

View File

@ -0,0 +1,176 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "sdkconfig.h"
#include "soc/soc.h"
#include "esp_cpu.h"
#include "esp_fault.h"
#ifdef BOOTLOADER_BUILD
// Without L bit set
#define CONDITIONAL_NONE 0x0
#define CONDITIONAL_RX PMP_R | PMP_X
#define CONDITIONAL_RW PMP_R | PMP_W
#define CONDITIONAL_RWX PMP_R | PMP_W | PMP_X
#else
// With L bit set
#define CONDITIONAL_NONE NONE
#define CONDITIONAL_RX RX
#define CONDITIONAL_RW RW
#define CONDITIONAL_RWX RWX
#endif
//TODO: [ESP32H4] IDF-12588
static void esp_cpu_configure_invalid_regions(void)
{
abort();
}
void esp_cpu_configure_region_protection(void)
{
// ROM has configured the MSPI region with RX permission, we should add W attribute for psram
PMA_ENTRY_SET_NAPOT(0, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X);
return;
/* Notes on implementation:
*
* 1) Note: ESP32-H4 CPU doesn't support overlapping PMP regions
*
* 2) ESP32-H4 supports 16 PMA regions so we use this feature to block all the invalid address ranges
*
* 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range)
* entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries
* which can be used to provide more granular access
*
* 4) Entries are grouped in order with some static asserts to try and verify everything is
* correct.
*/
/* There are 4 configuration scenarios for SRAM
*
* 1. Bootloader build:
* - We cannot set the lock bit as we need to reconfigure it again for the application.
* We configure PMP to cover entire valid IRAM and DRAM range.
*
* 2. Application build with CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT enabled
* - We split the SRAM into IRAM and DRAM such that IRAM region cannot be written to
* and DRAM region cannot be executed. We use _iram_end and _data_start markers to set the boundaries.
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
*
* 3. Application build with CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT disabled
* - The IRAM-DRAM split is not enabled so we just need to ensure that access to only valid address ranges are successful
* so for that we set PMP to cover entire valid IRAM and DRAM region.
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
*
* 4. CPU is in OCD debug mode
* - The IRAM-DRAM split is not enabled so that OpenOCD can write and execute from IRAM.
* We set PMP to cover entire valid IRAM and DRAM region.
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
*/
const unsigned NONE = PMP_L;
const unsigned R = PMP_L | PMP_R;
const unsigned RW = PMP_L | PMP_R | PMP_W;
const unsigned RX = PMP_L | PMP_R | PMP_X;
const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X;
//
// Configure all the invalid address regions using PMA
//
esp_cpu_configure_invalid_regions();
//
// Configure all the valid address regions using PMP
//
// 1. Debug region
const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_DEBUG_LOW, SOC_DEBUG_HIGH);
PMP_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RWX);
_Static_assert(SOC_DEBUG_LOW < SOC_DEBUG_HIGH, "Invalid CPU debug region");
// 2.1 I-ROM
PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE);
PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX);
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I-ROM region");
// 2.2 D-ROM
PMP_ENTRY_SET(3, SOC_DROM_MASK_LOW, NONE);
PMP_ENTRY_SET(4, SOC_DROM_MASK_HIGH, PMP_TOR | R);
_Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid D-ROM region");
if (esp_cpu_dbgr_is_attached()) {
// Anti-FI check that cpu is really in ocd mode
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
// 5. IRAM and DRAM
// const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH);
// PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | RWX);
// _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX);
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
} else {
#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD
extern int _iram_end;
// 5. IRAM and DRAM
/* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits
* Bootloader might have given extra permissions and those won't be cleared
*/
PMP_ENTRY_CFG_RESET(5);
PMP_ENTRY_CFG_RESET(6);
PMP_ENTRY_CFG_RESET(7);
PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
PMP_ENTRY_SET(6, (int)&_iram_end, PMP_TOR | RX);
PMP_ENTRY_SET(7, SOC_DRAM_HIGH, PMP_TOR | RW);
#else
// 5. IRAM and DRAM
// const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH);
// PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | CONDITIONAL_RWX);
// _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX);
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
#endif
}
// 4. I_Cache (flash)
const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
PMP_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | RX);
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I_Cache region");
// 5. D_Cache (flash)
const uint32_t pmpaddr9 = PMPADDR_NAPOT(SOC_DROM_LOW, SOC_DROM_HIGH);
PMP_ENTRY_SET(9, pmpaddr9, PMP_NAPOT | R);
_Static_assert(SOC_DROM_LOW < SOC_DROM_HIGH, "Invalid D_Cache region");
// 6. LP memory
#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD
extern int _rtc_text_end;
/* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits
* Bootloader might have given extra permissions and those won't be cleared
*/
PMP_ENTRY_CFG_RESET(10);
PMP_ENTRY_CFG_RESET(11);
PMP_ENTRY_CFG_RESET(12);
PMP_ENTRY_CFG_RESET(13);
PMP_ENTRY_SET(10, SOC_RTC_IRAM_LOW, NONE);
// Repeat same previous entry, to ensure next entry has correct base address (TOR)
PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE);
PMP_ENTRY_SET(12, (int)&_rtc_text_end, PMP_TOR | RX);
PMP_ENTRY_SET(13, SOC_RTC_IRAM_HIGH, PMP_TOR | RW);
#else
const uint32_t pmpaddr10 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH);
PMP_ENTRY_SET(10, pmpaddr10, PMP_NAPOT | CONDITIONAL_RWX);
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
#endif
// 7. Peripheral addresses
const uint32_t pmpaddr14 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
PMP_ENTRY_SET(14, pmpaddr14, PMP_NAPOT | RW);
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
}

View File

@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "esp_clk_tree.h"
#include "esp_err.h"
#include "esp_check.h"
#include "soc/rtc.h"
#include "hal/clk_tree_hal.h"
#include "hal/clk_tree_ll.h"
#include "esp_private/esp_clk_tree_common.h"
//TODO: [ESP32H4] IDF-12285
static const char *TAG = "esp_clk_tree";
esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision,
uint32_t *freq_value)
{
ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src");
ESP_RETURN_ON_FALSE(precision < ESP_CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision");
ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer");
uint32_t clk_src_freq = 0;
switch (clk_src) {
case SOC_MOD_CLK_XTAL:
clk_src_freq = 32 * MHZ;
break;
case SOC_MOD_CLK_PLL_F80M:
clk_src_freq = CLK_LL_PLL_80M_FREQ_MHZ * MHZ;
break;
case SOC_MOD_CLK_PLL_F160M:
clk_src_freq = CLK_LL_PLL_160M_FREQ_MHZ * MHZ;
break;
case SOC_MOD_CLK_PLL_F240M:
clk_src_freq = CLK_LL_PLL_240M_FREQ_MHZ * MHZ;
break;
default:
break;
}
ESP_RETURN_ON_FALSE(clk_src_freq, ESP_FAIL, TAG,
"freq shouldn't be 0, calibration failed");
*freq_value = clk_src_freq;
return ESP_OK;
}

View File

@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_cpu.h"
#include "esp_riscv_intr.h"
void esp_cpu_intr_get_desc(int core_id, int intr_num, esp_cpu_intr_desc_t *intr_desc_ret)
{
/* On targets that uses CLIC as the interrupt controller, the first 16 lines (0..15) are reserved for software
* interrupts, all the other lines starting from 16 and above can be used by external peripheral.
*
* Only interrupt line 6 is reserved at the moment since it is used for disabling interrupts in the
* interrupt allocator (INT_MUX_DISABLED_INTNO) */
const uint32_t rsvd_mask = BIT(6);
intr_desc_ret->priority = 1;
intr_desc_ret->type = ESP_CPU_INTR_TYPE_NA;
intr_desc_ret->flags = esp_riscv_intr_num_flags(intr_num, rsvd_mask);
}

View File

@ -0,0 +1,84 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "rom/ets_sys.h"
#include "rom/rtc.h"
#include "rom/uart.h"
#include "soc/rtc.h"
#include "esp_cpu.h"
#include "regi2c_ctrl.h"
#include "soc/lp_clkrst_reg.h"
#include "soc/regi2c_dig_reg.h"
#include "esp_hw_log.h"
#include "sdkconfig.h"
#include "esp_rom_uart.h"
#include "esp_private/esp_pmu.h"
#include "hal/clk_tree_ll.h"
#include "hal/pmu_ll.h"
#include "soc/pmu_reg.h"
#include "pmu_param.h"
static const char *TAG = "rtc_clk_init";
void rtc_clk_init(rtc_clk_config_t cfg)
{
rtc_cpu_freq_config_t old_config, new_config;
/* Set tuning parameters for RC_FAST, RC_SLOW, and RC32K clocks.
* Note: this doesn't attempt to set the clocks to precise frequencies.
* Instead, we calibrate these clocks against XTAL frequency later, when necessary.
* - SCK_DCAP value controls tuning of RC_SLOW clock.
* The higher the value of DCAP is, the lower is the frequency.
* - CK8M_DFREQ value controls tuning of RC_FAST clock.
* CLK_8M_DFREQ constant gives the best temperature characteristics.
* - RC32K_DFREQ value controls tuning of RC32K clock.
*/
REG_SET_FIELD(LP_CLKRST_FOSC_CNTL_REG, LP_CLKRST_FOSC_DFREQ, cfg.clk_8m_dfreq);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_SCK_DCAP, cfg.slow_clk_dcap);
REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1);
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, HP_CALI_DBIAS);
REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS);
clk_ll_rc_fast_tick_conf();
rtc_xtal_freq_t xtal_freq = cfg.xtal_freq;
esp_rom_output_tx_wait_idle(0);
rtc_clk_xtal_freq_update(xtal_freq);
/* Set CPU frequency */
rtc_clk_cpu_freq_get_config(&old_config);
uint32_t freq_before = old_config.freq_mhz;
bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config);
if (!res) {
ESP_HW_LOGE(TAG, "invalid CPU frequency value");
abort();
}
rtc_clk_cpu_freq_set_config(&new_config);
/* Re-calculate the ccount to make time calculation correct. */
esp_cpu_set_cycle_count( (uint64_t)esp_cpu_get_cycle_count() * cfg.cpu_freq_mhz / freq_before );
/* Slow & fast clocks setup */
// We will not power off RC_FAST in bootloader stage even if it is not being used as any
// cpu / rtc_fast / rtc_slow clock sources, this is because RNG always needs it in the bootloader stage.
bool need_rc_fast_en = true;
if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
rtc_clk_32k_enable(true);
} else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
rtc_clk_32k_enable_external();
} else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
rtc_clk_rc32k_enable(true);
}
rtc_clk_8m_enable(need_rc_fast_en);
rtc_clk_fast_src_set(cfg.fast_clk_src);
rtc_clk_slow_src_set(cfg.slow_clk_src);
}

View File

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <stdint.h>
#include "sdkconfig.h"
#include "soc/ext_mem_defs.h"
#include "../ext_mem_layout.h"
#include "hal/mmu_types.h"
/**
* The start addresses in this list should always be sorted from low to high, as MMU driver will need to
* coalesce adjacent regions
*/
const mmu_mem_region_t g_mmu_mem_regions[SOC_MMU_LINEAR_ADDRESS_REGION_NUM] = {
[0] = {
.start = SOC_MMU_IRAM0_LINEAR_ADDRESS_LOW,
.end = SOC_MMU_IRAM0_LINEAR_ADDRESS_HIGH,
.size = SOC_BUS_SIZE(SOC_MMU_IRAM0_LINEAR),
.bus_id = CACHE_BUS_IBUS0 | CACHE_BUS_DBUS0,
.targets = MMU_TARGET_FLASH0 | MMU_TARGET_PSRAM0,
.caps = MMU_MEM_CAP_EXEC | MMU_MEM_CAP_READ | MMU_MEM_CAP_WRITE | MMU_MEM_CAP_32BIT | MMU_MEM_CAP_8BIT,
},
};

View File

@ -105,6 +105,8 @@
#define REF_CLK_DIV_MIN 2 #define REF_CLK_DIV_MIN 2
#elif CONFIG_IDF_TARGET_ESP32P4 #elif CONFIG_IDF_TARGET_ESP32P4
#define REF_CLK_DIV_MIN 2 #define REF_CLK_DIV_MIN 2
#elif CONFIG_IDF_TARGET_ESP32H4
#define REF_CLK_DIV_MIN 2
#endif #endif
#ifdef CONFIG_PM_PROFILING #ifdef CONFIG_PM_PROFILING

View File

@ -59,6 +59,10 @@ config ESP_ROM_HAS_NEWLIB_NANO_FORMAT
bool bool
default y default y
config ESP_ROM_USB_OTG_NUM
int
default -1
config ESP_ROM_WDT_INIT_PATCH config ESP_ROM_WDT_INIT_PATCH
bool bool
default y default y

View File

@ -20,5 +20,6 @@
#define ESP_ROM_WITHOUT_REGI2C (1) // ROM has the regi2c bug or rom does not support regi2c function #define ESP_ROM_WITHOUT_REGI2C (1) // ROM has the regi2c bug or rom does not support regi2c function
#define ESP_ROM_HAS_NEWLIB (1) // ROM has newlib (at least parts of it) functions included #define ESP_ROM_HAS_NEWLIB (1) // ROM has newlib (at least parts of it) functions included
#define ESP_ROM_HAS_NEWLIB_NANO_FORMAT (1) // ROM has the newlib nano versions of formatting functions #define ESP_ROM_HAS_NEWLIB_NANO_FORMAT (1) // ROM has the newlib nano versions of formatting functions
#define ESP_ROM_USB_OTG_NUM (-1) // No USB_OTG CDC in the ROM, set -1 for Kconfig usage.
#define ESP_ROM_WDT_INIT_PATCH (1) // ROM version does not configure the clock #define ESP_ROM_WDT_INIT_PATCH (1) // ROM version does not configure the clock
#define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init #define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init

View File

@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/soc.h"
#include "soc/pcr_reg.h"
#pragma once
static inline void esp_crypto_clk_init(void)
{
// Set crypto clock (`clk_sec`) to use 96M PLL clock
REG_SET_FIELD(PCR_SEC_CONF_REG, PCR_SEC_CLK_SEL, 0x3);
}

View File

@ -71,8 +71,8 @@ uint32_t clk_hal_xtal_get_freq_mhz(void)
{ {
uint32_t freq = clk_ll_xtal_load_freq_mhz(); uint32_t freq = clk_ll_xtal_load_freq_mhz();
if (freq == 0) { if (freq == 0) {
HAL_LOGW(CLK_HAL_TAG, "invalid RTC_XTAL_FREQ_REG value, assume 32MHz"); HAL_LOGW(CLK_HAL_TAG, "invalid SOC_XTAL_FREQ_32M value, assume 32MHz");
return (uint32_t)RTC_XTAL_FREQ_32M; return (uint32_t)SOC_XTAL_FREQ_32M;
} }
return freq; return freq;
} }

View File

@ -26,6 +26,38 @@ FORCE_INLINE_ATTR void cpu_utility_ll_reset_cpu(uint32_t cpu_no)
} }
} }
#if SOC_CPU_CORES_NUM > 1 // We only allow stalling/unstalling of other cores
FORCE_INLINE_ATTR void cpu_utility_ll_stall_cpu(uint32_t cpu_no)
{
(void)cpu_no;
abort();
}
FORCE_INLINE_ATTR void cpu_utility_ll_unstall_cpu(uint32_t cpu_no)
{
(void)cpu_no;
abort();
}
FORCE_INLINE_ATTR void cpu_utility_ll_enable_debug(uint32_t cpu_no)
{
(void)cpu_no;
abort();
}
FORCE_INLINE_ATTR void cpu_utility_ll_enable_record(uint32_t cpu_no)
{
(void)cpu_no;
abort();
}
FORCE_INLINE_ATTR void cpu_utility_ll_enable_clock_and_reset_app_cpu(void)
{
abort();
}
#endif // SOC_CPU_CORES_NUM > 1
FORCE_INLINE_ATTR uint32_t cpu_utility_ll_wait_mode(void) FORCE_INLINE_ATTR uint32_t cpu_utility_ll_wait_mode(void)
{ {
return REG_GET_BIT(PCR_CPU_WAITI_CONF_REG, PCR_CPU0_WAIT_MODE_FORCE_ON); return REG_GET_BIT(PCR_CPU_WAITI_CONF_REG, PCR_CPU0_WAIT_MODE_FORCE_ON);

View File

@ -57,6 +57,9 @@ extern "C" {
#define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \ #define UART_LL_PCR_REG_GET(hw, reg_suffix, field_suffix) \
(((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix) (((hw) == &UART0) ? PCR.uart0_##reg_suffix.uart0_##field_suffix : PCR.uart1_##reg_suffix.uart1_##field_suffix)
#define UART_LL_WAKEUP_EDGE_THRED_MAX(hw) UART_ACTIVE_THRESHOLD_V
#define UART_LL_WAKEUP_FIFO_THRED_MAX(hw) UART_RX_WAKE_UP_THRHD_V
// Define UART interrupts // Define UART interrupts
typedef enum { typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0), UART_INTR_RXFIFO_FULL = (0x1 << 0),
@ -254,28 +257,29 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source
* @param baud The baud rate to be set. * @param baud The baud rate to be set.
* @param sclk_freq Frequency of the clock source of UART, in Hz. * @param sclk_freq Frequency of the clock source of UART, in Hz.
* *
* @return None * @return True if baud-rate set successfully; False if baud-rate requested cannot be achieved
*/ */
FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t sclk_freq) FORCE_INLINE_ATTR bool uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t sclk_freq)
{ {
// #define DIV_UP(a, b) (((a) + (b) - 1) / (b)) #define DIV_UP(a, b) (((a) + (b) - 1) / (b))
// const uint32_t max_div = BIT(12) - 1; // UART divider integer part only has 12 bits if (baud == 0) {
// uint32_t sclk_div = DIV_UP(sclk_freq, (uint64_t)max_div * baud); return false;
}
const uint32_t max_div = UART_CLKDIV_V; // UART divider integer part only has 12 bits
uint32_t sclk_div = DIV_UP(sclk_freq, (uint64_t)max_div * baud);
#undef DIV_UP
// if (sclk_div == 0) abort(); if (sclk_div == 0 || sclk_div > (PCR_UART0_SCLK_DIV_NUM_V + 1)) {
return false; // unachievable baud-rate
}
// uint32_t clk_div = ((sclk_freq) << 4) / (baud * sclk_div); uint32_t clk_div = ((sclk_freq) << 4) / (baud * sclk_div);
// // The baud rate configuration register is divided into // The baud rate configuration register is divided into an integer part and a fractional part.
// // an integer part and a fractional part. hw->clkdiv_sync.clkdiv = clk_div >> 4;
// hw->clkdiv_sync.clkdiv = clk_div >> 4; hw->clkdiv_sync.clkdiv_frag = clk_div & 0xf;
// hw->clkdiv_sync.clkdiv_frag = clk_div & 0xf; UART_LL_PCR_REG_U32_SET(hw, sclk_conf, sclk_div_num, sclk_div - 1);
// if ((hw) == &LP_UART) { uart_ll_update(hw);
// abort(); return true;
// } else {
// UART_LL_PCR_REG_U32_SET(hw, sclk_conf, sclk_div_num, sclk_div - 1);
// }
// #undef DIV_UP
// uart_ll_update(hw);
} }
/** /**
@ -288,16 +292,11 @@ FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint3
*/ */
FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_freq) FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_freq)
{ {
// typeof(hw->clkdiv_sync) div_reg; typeof(hw->clkdiv_sync) div_reg;
// div_reg.val = hw->clkdiv_sync.val; div_reg.val = hw->clkdiv_sync.val;
// int sclk_div; int sclk_div;
// if ((hw) == &LP_UART) { sclk_div = UART_LL_PCR_REG_U32_GET(hw, sclk_conf, sclk_div_num) + 1;
// sclk_div = HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1; return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * sclk_div);
// } else {
// sclk_div = UART_LL_PCR_REG_U32_GET(hw, sclk_conf, sclk_div_num) + 1;
// }
// return ((sclk_freq << 4)) / (((div_reg.clkdiv_int << 4) | div_reg.clkdiv_frag) * sclk_div);
return 0;
} }
/** /**
@ -748,6 +747,51 @@ FORCE_INLINE_ATTR void uart_ll_set_wakeup_edge_thrd(uart_dev_t *hw, uint32_t wak
hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN; hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_WAKEUP_EDGE_THRED_MIN;
} }
/**
* @brief Set the number of received data bytes for the RX FIFO threshold wake-up mode.
*
* @param hw Beginning address of the peripheral registers.
* @param wakeup_thrd The wakeup threshold value in bytes to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_fifo_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
{
// System would wakeup when reach the number of the received data number threshold.
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->sleep_conf2, rx_wake_up_thrhd, wakeup_thrd);
}
/**
* @brief Set the UART wakeup mode.
*
* @param hw Beginning address of the peripheral registers.
* @param mode UART wakeup mode to be set.
*
* @return None.
*/
FORCE_INLINE_ATTR void uart_ll_set_wakeup_mode(uart_dev_t *hw, uart_wakeup_mode_t mode)
{
switch(mode){
case UART_WK_MODE_ACTIVE_THRESH:
hw->sleep_conf2.wk_mode_sel = 0;
break;
default:
abort();
break;
}
}
/**
* @brief Enable/disable the UART pad clock in sleep_state
*
* @param hw Beginning address of the peripheral registers.
* @param enable enable or disable
*/
FORCE_INLINE_ATTR void uart_ll_enable_pad_sleep_clock(uart_dev_t *hw, bool enable)
{
(void)hw; (void)enable;
}
/** /**
* @brief Configure the UART work in normal mode. * @brief Configure the UART work in normal mode.
* *

View File

@ -0,0 +1,91 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdlib.h>
#include "esp_attr.h"
#include "sdkconfig.h"
#include "soc/soc.h"
#include "heap_memory_layout.h"
#include "esp_heap_caps.h"
/* Memory layout for ESP32H4 SoC
* Note that the external memory is not represented in this file since
* it is handled by the esp_psram component
*/
/**
* @brief Memory type descriptors. These describe the capabilities of a type of memory in the SoC.
* Each type of memory map consists of one or more regions in the address space.
* Each type contains an array of prioritized capabilities.
* Types with later entries are only taken if earlier ones can't fulfill the memory request.
*
* - For a normal malloc (MALLOC_CAP_DEFAULT), give away the DRAM-only memory first, then pass off any dual-use IRAM regions, finally eat into the application memory.
* - For a malloc where 32-bit-aligned-only access is okay, first allocate IRAM, then DRAM, finally application IRAM.
* - Application mallocs (PIDx) will allocate IRAM first, if possible, then DRAM.
* - Most other malloc caps only fit in one region anyway.
*
*/
/* Index of memory in `soc_memory_types[]` */
enum {
SOC_MEMORY_TYPE_RAM = 0,
};
/* COMMON_CAPS is the set of attributes common to all types of memory on this chip */
#ifdef CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT
#define ESP32H4_MEM_COMMON_CAPS (MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT | MALLOC_CAP_8BIT)
#else
#define ESP32H4_MEM_COMMON_CAPS (MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT | MALLOC_CAP_8BIT | MALLOC_CAP_EXEC)
#endif
/**
* Defined the attributes and allocation priority of each memory on the chip,
* The heap allocator will traverse all types of memory types in column High Priority Matching and match the specified caps at first,
* if no memory caps matched or the allocation is failed, it will go to columns Medium Priority Matching and Low Priority Matching
* in turn to continue matching.
*/
const soc_memory_type_desc_t soc_memory_types[] = {
/* Mem Type Name High Priority Matching Medium Priority Matching Low Priority Matching */
[SOC_MEMORY_TYPE_RAM] = { "RAM", { ESP32H4_MEM_COMMON_CAPS | MALLOC_CAP_DMA, 0, 0 }},
};
const size_t soc_memory_type_count = sizeof(soc_memory_types) / sizeof(soc_memory_type_desc_t);
/**
* @brief Region descriptors. These describe all regions of memory available, and map them to a type in the above type.
*
* @note Because of requirements in the coalescing code which merges adjacent regions,
* this list should always be sorted from low to high by start address.
*
*/
/**
* Register the shared buffer area of the last memory block into the heap during heap initialization
*/
#define APP_USABLE_DIRAM_END (SOC_ROM_STACK_START - SOC_ROM_STACK_SIZE)
const soc_memory_region_t soc_memory_regions[] = {
{ SOC_DIRAM_DRAM_LOW, (APP_USABLE_DIRAM_END - SOC_DIRAM_DRAM_LOW), SOC_MEMORY_TYPE_RAM, SOC_DIRAM_IRAM_LOW, false}, //D/IRAM, can be used as trace memory
{ APP_USABLE_DIRAM_END, (SOC_DIRAM_DRAM_HIGH - APP_USABLE_DIRAM_END), SOC_MEMORY_TYPE_RAM, APP_USABLE_DIRAM_END, true}, //D/IRAM, can be used as trace memory (ROM reserved area)
};
const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_memory_region_t);
extern int _data_start, _heap_start, _iram_start, _iram_end;
/**
* Reserved memory regions.
* These are removed from the soc_memory_regions array when heaps are created.
*
*/
// Static data region. DRAM used by data+bss and possibly rodata
SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_data);
// Target has a shared D/IRAM virtual address, no need to calculate I_D_OFFSET like previous chips
SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code);

View File

@ -357,16 +357,12 @@ config SOC_FLASH_ENCRYPTION_XTS_AES_128
config SOC_UART_NUM config SOC_UART_NUM
int int
default 3 default 2
config SOC_UART_HP_NUM config SOC_UART_HP_NUM
int int
default 2 default 2
config SOC_UART_LP_NUM
int
default 1
config SOC_UART_FIFO_LEN config SOC_UART_FIFO_LEN
int int
default 128 default 128

View File

@ -469,10 +469,9 @@
// #define SOC_CRYPTO_DPA_PROTECTION_SUPPORTED 1 // #define SOC_CRYPTO_DPA_PROTECTION_SUPPORTED 1
/*-------------------------- UART CAPS ---------------------------------------*/ /*-------------------------- UART CAPS ---------------------------------------*/
// ESP32-H4 has 3 UARTs (2 HP UART, and 1 LP UART) TODO: IDF-12445 [ESP32H4] inherit from verify code, need remove LP*/ // ESP32-H4 has 2 HP UARTs
#define SOC_UART_NUM (3) #define SOC_UART_NUM (2)
#define SOC_UART_HP_NUM (2) #define SOC_UART_HP_NUM (2)
#define SOC_UART_LP_NUM (1U)
#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */
#define SOC_LP_UART_FIFO_LEN (16) /*!< The LP UART hardware FIFO length */ #define SOC_LP_UART_FIFO_LEN (16) /*!< The LP UART hardware FIFO length */
#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ #define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -11,10 +11,12 @@
extern "C" { extern "C" {
#endif #endif
#define DR_REG_SPI_BASE(i) (((i)>=2) ? (DR_REG_SPI2_BASE + (i-2) * 0x1000) : (0)) // GPSPI2 and GPSPI3
/** SPI_CMD_REG register /** SPI_CMD_REG register
* Command control register * Command control register
*/ */
#define SPI_CMD_REG (DR_REG_SPI_BASE + 0x0) #define SPI_CMD_REG(i) (DR_REG_SPI_BASE(i) + 0x0)
/** SPI_CONF_BITLEN : R/W; bitpos: [17:0]; default: 0; /** SPI_CONF_BITLEN : R/W; bitpos: [17:0]; default: 0;
* Configures the SPI_CLK cycles of SPI CONF state. * Configures the SPI_CLK cycles of SPI CONF state.
* Measurement unit: SPI_CLK clock cycle. * Measurement unit: SPI_CLK clock cycle.
@ -50,7 +52,7 @@ extern "C" {
/** SPI_ADDR_REG register /** SPI_ADDR_REG register
* Address value register * Address value register
*/ */
#define SPI_ADDR_REG (DR_REG_SPI_BASE + 0x4) #define SPI_ADDR_REG(i) (DR_REG_SPI_BASE(i) + 0x4)
/** SPI_USR_ADDR_VALUE : R/W; bitpos: [31:0]; default: 0; /** SPI_USR_ADDR_VALUE : R/W; bitpos: [31:0]; default: 0;
* Configures the address to slave. * Configures the address to slave.
* Can be configured in CONF state. * Can be configured in CONF state.
@ -63,7 +65,7 @@ extern "C" {
/** SPI_CTRL_REG register /** SPI_CTRL_REG register
* SPI control register * SPI control register
*/ */
#define SPI_CTRL_REG (DR_REG_SPI_BASE + 0x8) #define SPI_CTRL_REG(i) (DR_REG_SPI_BASE(i) + 0x8)
/** SPI_DUMMY_OUT : R/W; bitpos: [3]; default: 0; /** SPI_DUMMY_OUT : R/W; bitpos: [3]; default: 0;
* Configures whether or not to output the FSPI bus signals in DUMMY state. * Configures whether or not to output the FSPI bus signals in DUMMY state.
* 0: Not output * 0: Not output
@ -232,7 +234,7 @@ extern "C" {
/** SPI_CLOCK_REG register /** SPI_CLOCK_REG register
* SPI clock control register * SPI clock control register
*/ */
#define SPI_CLOCK_REG (DR_REG_SPI_BASE + 0xc) #define SPI_CLOCK_REG(i) (DR_REG_SPI_BASE(i) + 0xc)
/** SPI_CLKCNT_L : R/W; bitpos: [5:0]; default: 3; /** SPI_CLKCNT_L : R/W; bitpos: [5:0]; default: 3;
* In master transfer, this field must be equal to SPI_CLKCNT_N. In slave mode, it * In master transfer, this field must be equal to SPI_CLKCNT_N. In slave mode, it
* must be 0. Can be configured in CONF state. * must be 0. Can be configured in CONF state.
@ -295,7 +297,7 @@ extern "C" {
/** SPI_USER_REG register /** SPI_USER_REG register
* SPI USER control register * SPI USER control register
*/ */
#define SPI_USER_REG (DR_REG_SPI_BASE + 0x10) #define SPI_USER_REG(i) (DR_REG_SPI_BASE(i) + 0x10)
/** SPI_DOUTDIN : R/W; bitpos: [0]; default: 0; /** SPI_DOUTDIN : R/W; bitpos: [0]; default: 0;
* Configures whether or not to enable full-duplex communication. * Configures whether or not to enable full-duplex communication.
* 0: Disable * 0: Disable
@ -511,7 +513,7 @@ extern "C" {
/** SPI_USER1_REG register /** SPI_USER1_REG register
* SPI USER control register 1 * SPI USER control register 1
*/ */
#define SPI_USER1_REG (DR_REG_SPI_BASE + 0x14) #define SPI_USER1_REG(i) (DR_REG_SPI_BASE(i) + 0x14)
/** SPI_USR_DUMMY_CYCLELEN : R/W; bitpos: [7:0]; default: 7; /** SPI_USR_DUMMY_CYCLELEN : R/W; bitpos: [7:0]; default: 7;
* Configures the length of DUMMY state. * Configures the length of DUMMY state.
* Measurement unit: SPI_CLK clock cycles. * Measurement unit: SPI_CLK clock cycles.
@ -562,7 +564,7 @@ extern "C" {
/** SPI_USER2_REG register /** SPI_USER2_REG register
* SPI USER control register 2 * SPI USER control register 2
*/ */
#define SPI_USER2_REG (DR_REG_SPI_BASE + 0x18) #define SPI_USER2_REG(i) (DR_REG_SPI_BASE(i) + 0x18)
/** SPI_USR_COMMAND_VALUE : R/W; bitpos: [15:0]; default: 0; /** SPI_USR_COMMAND_VALUE : R/W; bitpos: [15:0]; default: 0;
* Configures the command value. * Configures the command value.
* Can be configured in CONF state. * Can be configured in CONF state.
@ -593,7 +595,7 @@ extern "C" {
/** SPI_MS_DLEN_REG register /** SPI_MS_DLEN_REG register
* SPI data bit length control register * SPI data bit length control register
*/ */
#define SPI_MS_DLEN_REG (DR_REG_SPI_BASE + 0x1c) #define SPI_MS_DLEN_REG(i) (DR_REG_SPI_BASE(i) + 0x1c)
/** SPI_MS_DATA_BITLEN : R/W; bitpos: [17:0]; default: 0; /** SPI_MS_DATA_BITLEN : R/W; bitpos: [17:0]; default: 0;
* Configures the data bit length of SPI transfer in DMA-controlled master transfer or * Configures the data bit length of SPI transfer in DMA-controlled master transfer or
* in CPU-controlled master transfer. Or configures the bit length of SPI RX transfer * in CPU-controlled master transfer. Or configures the bit length of SPI RX transfer
@ -608,7 +610,7 @@ extern "C" {
/** SPI_MISC_REG register /** SPI_MISC_REG register
* SPI misc register * SPI misc register
*/ */
#define SPI_MISC_REG (DR_REG_SPI_BASE + 0x20) #define SPI_MISC_REG(i) (DR_REG_SPI_BASE(i) + 0x20)
/** SPI_CS0_DIS : R/W; bitpos: [0]; default: 0; /** SPI_CS0_DIS : R/W; bitpos: [0]; default: 0;
* Configures whether or not to disable SPI_CS$n pin. * Configures whether or not to disable SPI_CS$n pin.
* 0: SPI_CS$n signal is from/to SPI_CS$n pin. * 0: SPI_CS$n signal is from/to SPI_CS$n pin.
@ -773,7 +775,7 @@ extern "C" {
/** SPI_DIN_MODE_REG register /** SPI_DIN_MODE_REG register
* SPI input delay mode configuration * SPI input delay mode configuration
*/ */
#define SPI_DIN_MODE_REG (DR_REG_SPI_BASE + 0x24) #define SPI_DIN_MODE_REG(i) (DR_REG_SPI_BASE(i) + 0x24)
/** SPI_DIN0_MODE : R/W; bitpos: [1:0]; default: 0; /** SPI_DIN0_MODE : R/W; bitpos: [1:0]; default: 0;
* Configures the input mode for FSPID signal. * Configures the input mode for FSPID signal.
* 0: Input without delay * 0: Input without delay
@ -882,7 +884,7 @@ extern "C" {
/** SPI_DIN_NUM_REG register /** SPI_DIN_NUM_REG register
* SPI input delay number configuration * SPI input delay number configuration
*/ */
#define SPI_DIN_NUM_REG (DR_REG_SPI_BASE + 0x28) #define SPI_DIN_NUM_REG(i) (DR_REG_SPI_BASE(i) + 0x28)
/** SPI_DIN0_NUM : R/W; bitpos: [1:0]; default: 0; /** SPI_DIN0_NUM : R/W; bitpos: [1:0]; default: 0;
* Configures the delays to input signal FSPID based on the setting of SPI_DIN0_MODE. * Configures the delays to input signal FSPID based on the setting of SPI_DIN0_MODE.
* 0: Delayed by 1 clock cycle * 0: Delayed by 1 clock cycle
@ -967,7 +969,7 @@ extern "C" {
/** SPI_DOUT_MODE_REG register /** SPI_DOUT_MODE_REG register
* SPI output delay mode configuration * SPI output delay mode configuration
*/ */
#define SPI_DOUT_MODE_REG (DR_REG_SPI_BASE + 0x2c) #define SPI_DOUT_MODE_REG(i) (DR_REG_SPI_BASE(i) + 0x2c)
/** SPI_DOUT0_MODE : R/W; bitpos: [0]; default: 0; /** SPI_DOUT0_MODE : R/W; bitpos: [0]; default: 0;
* Configures the output mode for FSPID signal. * Configures the output mode for FSPID signal.
* 0: Output without delay * 0: Output without delay
@ -1057,7 +1059,7 @@ extern "C" {
/** SPI_DMA_CONF_REG register /** SPI_DMA_CONF_REG register
* SPI DMA control register * SPI DMA control register
*/ */
#define SPI_DMA_CONF_REG (DR_REG_SPI_BASE + 0x30) #define SPI_DMA_CONF_REG(i) (DR_REG_SPI_BASE(i) + 0x30)
/** SPI_DMA_OUTFIFO_EMPTY : RO; bitpos: [0]; default: 1; /** SPI_DMA_OUTFIFO_EMPTY : RO; bitpos: [0]; default: 1;
* Represents whether or not the DMA TX FIFO is ready for sending data. * Represents whether or not the DMA TX FIFO is ready for sending data.
* 0: Ready * 0: Ready
@ -1178,7 +1180,7 @@ extern "C" {
/** SPI_DMA_INT_ENA_REG register /** SPI_DMA_INT_ENA_REG register
* SPI interrupt enable register * SPI interrupt enable register
*/ */
#define SPI_DMA_INT_ENA_REG (DR_REG_SPI_BASE + 0x34) #define SPI_DMA_INT_ENA_REG(i) (DR_REG_SPI_BASE(i) + 0x34)
/** SPI_DMA_INFIFO_FULL_ERR_INT_ENA : R/W; bitpos: [0]; default: 0; /** SPI_DMA_INFIFO_FULL_ERR_INT_ENA : R/W; bitpos: [0]; default: 0;
* Write 1 to enable SPI_DMA_INFIFO_FULL_ERR_INT interrupt. * Write 1 to enable SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
*/ */
@ -1330,7 +1332,7 @@ extern "C" {
/** SPI_DMA_INT_CLR_REG register /** SPI_DMA_INT_CLR_REG register
* SPI interrupt clear register * SPI interrupt clear register
*/ */
#define SPI_DMA_INT_CLR_REG (DR_REG_SPI_BASE + 0x38) #define SPI_DMA_INT_CLR_REG(i) (DR_REG_SPI_BASE(i) + 0x38)
/** SPI_DMA_INFIFO_FULL_ERR_INT_CLR : WT; bitpos: [0]; default: 0; /** SPI_DMA_INFIFO_FULL_ERR_INT_CLR : WT; bitpos: [0]; default: 0;
* Write 1 to clear SPI_DMA_INFIFO_FULL_ERR_INT interrupt. * Write 1 to clear SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
*/ */
@ -1482,7 +1484,7 @@ extern "C" {
/** SPI_DMA_INT_RAW_REG register /** SPI_DMA_INT_RAW_REG register
* SPI interrupt raw register * SPI interrupt raw register
*/ */
#define SPI_DMA_INT_RAW_REG (DR_REG_SPI_BASE + 0x3c) #define SPI_DMA_INT_RAW_REG(i) (DR_REG_SPI_BASE(i) + 0x3c)
/** SPI_DMA_INFIFO_FULL_ERR_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0; /** SPI_DMA_INFIFO_FULL_ERR_INT_RAW : R/WTC/SS; bitpos: [0]; default: 0;
* The raw interrupt status of SPI_DMA_INFIFO_FULL_ERR_INT interrupt. * The raw interrupt status of SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
*/ */
@ -1638,7 +1640,7 @@ extern "C" {
/** SPI_DMA_INT_ST_REG register /** SPI_DMA_INT_ST_REG register
* SPI interrupt status register * SPI interrupt status register
*/ */
#define SPI_DMA_INT_ST_REG (DR_REG_SPI_BASE + 0x40) #define SPI_DMA_INT_ST_REG(i) (DR_REG_SPI_BASE(i) + 0x40)
/** SPI_DMA_INFIFO_FULL_ERR_INT_ST : RO; bitpos: [0]; default: 0; /** SPI_DMA_INFIFO_FULL_ERR_INT_ST : RO; bitpos: [0]; default: 0;
* The interrupt status of SPI_DMA_INFIFO_FULL_ERR_INT interrupt. * The interrupt status of SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
*/ */
@ -1790,7 +1792,7 @@ extern "C" {
/** SPI_DMA_INT_SET_REG register /** SPI_DMA_INT_SET_REG register
* SPI interrupt software set register * SPI interrupt software set register
*/ */
#define SPI_DMA_INT_SET_REG (DR_REG_SPI_BASE + 0x44) #define SPI_DMA_INT_SET_REG(i) (DR_REG_SPI_BASE(i) + 0x44)
/** SPI_DMA_INFIFO_FULL_ERR_INT_SET : WT; bitpos: [0]; default: 0; /** SPI_DMA_INFIFO_FULL_ERR_INT_SET : WT; bitpos: [0]; default: 0;
* Write 1 to set SPI_DMA_INFIFO_FULL_ERR_INT interrupt. * Write 1 to set SPI_DMA_INFIFO_FULL_ERR_INT interrupt.
*/ */
@ -1942,7 +1944,7 @@ extern "C" {
/** SPI_W0_REG register /** SPI_W0_REG register
* SPI CPU-controlled buffer0 * SPI CPU-controlled buffer0
*/ */
#define SPI_W0_REG (DR_REG_SPI_BASE + 0x98) #define SPI_W0_REG(i) (DR_REG_SPI_BASE(i) + 0x98)
/** SPI_BUF0 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF0 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -1954,7 +1956,7 @@ extern "C" {
/** SPI_W1_REG register /** SPI_W1_REG register
* SPI CPU-controlled buffer1 * SPI CPU-controlled buffer1
*/ */
#define SPI_W1_REG (DR_REG_SPI_BASE + 0x9c) #define SPI_W1_REG(i) (DR_REG_SPI_BASE(i) + 0x9c)
/** SPI_BUF1 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF1 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -1966,7 +1968,7 @@ extern "C" {
/** SPI_W2_REG register /** SPI_W2_REG register
* SPI CPU-controlled buffer2 * SPI CPU-controlled buffer2
*/ */
#define SPI_W2_REG (DR_REG_SPI_BASE + 0xa0) #define SPI_W2_REG(i) (DR_REG_SPI_BASE(i) + 0xa0)
/** SPI_BUF2 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF2 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -1978,7 +1980,7 @@ extern "C" {
/** SPI_W3_REG register /** SPI_W3_REG register
* SPI CPU-controlled buffer3 * SPI CPU-controlled buffer3
*/ */
#define SPI_W3_REG (DR_REG_SPI_BASE + 0xa4) #define SPI_W3_REG(i) (DR_REG_SPI_BASE(i) + 0xa4)
/** SPI_BUF3 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF3 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -1990,7 +1992,7 @@ extern "C" {
/** SPI_W4_REG register /** SPI_W4_REG register
* SPI CPU-controlled buffer4 * SPI CPU-controlled buffer4
*/ */
#define SPI_W4_REG (DR_REG_SPI_BASE + 0xa8) #define SPI_W4_REG(i) (DR_REG_SPI_BASE(i) + 0xa8)
/** SPI_BUF4 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF4 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2002,7 +2004,7 @@ extern "C" {
/** SPI_W5_REG register /** SPI_W5_REG register
* SPI CPU-controlled buffer5 * SPI CPU-controlled buffer5
*/ */
#define SPI_W5_REG (DR_REG_SPI_BASE + 0xac) #define SPI_W5_REG(i) (DR_REG_SPI_BASE(i) + 0xac)
/** SPI_BUF5 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF5 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2014,7 +2016,7 @@ extern "C" {
/** SPI_W6_REG register /** SPI_W6_REG register
* SPI CPU-controlled buffer6 * SPI CPU-controlled buffer6
*/ */
#define SPI_W6_REG (DR_REG_SPI_BASE + 0xb0) #define SPI_W6_REG(i) (DR_REG_SPI_BASE(i) + 0xb0)
/** SPI_BUF6 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF6 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2026,7 +2028,7 @@ extern "C" {
/** SPI_W7_REG register /** SPI_W7_REG register
* SPI CPU-controlled buffer7 * SPI CPU-controlled buffer7
*/ */
#define SPI_W7_REG (DR_REG_SPI_BASE + 0xb4) #define SPI_W7_REG(i) (DR_REG_SPI_BASE(i) + 0xb4)
/** SPI_BUF7 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF7 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2038,7 +2040,7 @@ extern "C" {
/** SPI_W8_REG register /** SPI_W8_REG register
* SPI CPU-controlled buffer8 * SPI CPU-controlled buffer8
*/ */
#define SPI_W8_REG (DR_REG_SPI_BASE + 0xb8) #define SPI_W8_REG(i) (DR_REG_SPI_BASE(i) + 0xb8)
/** SPI_BUF8 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF8 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2050,7 +2052,7 @@ extern "C" {
/** SPI_W9_REG register /** SPI_W9_REG register
* SPI CPU-controlled buffer9 * SPI CPU-controlled buffer9
*/ */
#define SPI_W9_REG (DR_REG_SPI_BASE + 0xbc) #define SPI_W9_REG(i) (DR_REG_SPI_BASE(i) + 0xbc)
/** SPI_BUF9 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF9 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2062,7 +2064,7 @@ extern "C" {
/** SPI_W10_REG register /** SPI_W10_REG register
* SPI CPU-controlled buffer10 * SPI CPU-controlled buffer10
*/ */
#define SPI_W10_REG (DR_REG_SPI_BASE + 0xc0) #define SPI_W10_REG(i) (DR_REG_SPI_BASE(i) + 0xc0)
/** SPI_BUF10 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF10 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2074,7 +2076,7 @@ extern "C" {
/** SPI_W11_REG register /** SPI_W11_REG register
* SPI CPU-controlled buffer11 * SPI CPU-controlled buffer11
*/ */
#define SPI_W11_REG (DR_REG_SPI_BASE + 0xc4) #define SPI_W11_REG(i) (DR_REG_SPI_BASE(i) + 0xc4)
/** SPI_BUF11 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF11 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2086,7 +2088,7 @@ extern "C" {
/** SPI_W12_REG register /** SPI_W12_REG register
* SPI CPU-controlled buffer12 * SPI CPU-controlled buffer12
*/ */
#define SPI_W12_REG (DR_REG_SPI_BASE + 0xc8) #define SPI_W12_REG(i) (DR_REG_SPI_BASE(i) + 0xc8)
/** SPI_BUF12 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF12 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2098,7 +2100,7 @@ extern "C" {
/** SPI_W13_REG register /** SPI_W13_REG register
* SPI CPU-controlled buffer13 * SPI CPU-controlled buffer13
*/ */
#define SPI_W13_REG (DR_REG_SPI_BASE + 0xcc) #define SPI_W13_REG(i) (DR_REG_SPI_BASE(i) + 0xcc)
/** SPI_BUF13 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF13 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2110,7 +2112,7 @@ extern "C" {
/** SPI_W14_REG register /** SPI_W14_REG register
* SPI CPU-controlled buffer14 * SPI CPU-controlled buffer14
*/ */
#define SPI_W14_REG (DR_REG_SPI_BASE + 0xd0) #define SPI_W14_REG(i) (DR_REG_SPI_BASE(i) + 0xd0)
/** SPI_BUF14 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF14 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2122,7 +2124,7 @@ extern "C" {
/** SPI_W15_REG register /** SPI_W15_REG register
* SPI CPU-controlled buffer15 * SPI CPU-controlled buffer15
*/ */
#define SPI_W15_REG (DR_REG_SPI_BASE + 0xd4) #define SPI_W15_REG(i) (DR_REG_SPI_BASE(i) + 0xd4)
/** SPI_BUF15 : R/W/SS; bitpos: [31:0]; default: 0; /** SPI_BUF15 : R/W/SS; bitpos: [31:0]; default: 0;
* 32-bit data buffer $n. * 32-bit data buffer $n.
*/ */
@ -2134,7 +2136,7 @@ extern "C" {
/** SPI_SLAVE_REG register /** SPI_SLAVE_REG register
* SPI slave control register * SPI slave control register
*/ */
#define SPI_SLAVE_REG (DR_REG_SPI_BASE + 0xe0) #define SPI_SLAVE_REG(i) (DR_REG_SPI_BASE(i) + 0xe0)
/** SPI_CLK_MODE : R/W; bitpos: [1:0]; default: 0; /** SPI_CLK_MODE : R/W; bitpos: [1:0]; default: 0;
* Configures SPI clock mode. * Configures SPI clock mode.
* 0: SPI clock is off when CS becomes inactive. * 0: SPI clock is off when CS becomes inactive.
@ -2265,7 +2267,7 @@ extern "C" {
/** SPI_SLAVE1_REG register /** SPI_SLAVE1_REG register
* SPI slave control register 1 * SPI slave control register 1
*/ */
#define SPI_SLAVE1_REG (DR_REG_SPI_BASE + 0xe4) #define SPI_SLAVE1_REG(i) (DR_REG_SPI_BASE(i) + 0xe4)
/** SPI_SLV_DATA_BITLEN : R/W/SS; bitpos: [17:0]; default: 0; /** SPI_SLV_DATA_BITLEN : R/W/SS; bitpos: [17:0]; default: 0;
* Configures the transferred data bit length in SPI slave full-/half-duplex modes. * Configures the transferred data bit length in SPI slave full-/half-duplex modes.
*/ */
@ -2291,7 +2293,7 @@ extern "C" {
/** SPI_CLK_GATE_REG register /** SPI_CLK_GATE_REG register
* SPI module clock and register clock control * SPI module clock and register clock control
*/ */
#define SPI_CLK_GATE_REG (DR_REG_SPI_BASE + 0xe8) #define SPI_CLK_GATE_REG(i) (DR_REG_SPI_BASE(i) + 0xe8)
/** SPI_CLK_EN : R/W; bitpos: [0]; default: 0; /** SPI_CLK_EN : R/W; bitpos: [0]; default: 0;
* Configures whether or not to enable clock gate. * Configures whether or not to enable clock gate.
* 0: Disable * 0: Disable
@ -2320,7 +2322,7 @@ extern "C" {
/** SPI_DATE_REG register /** SPI_DATE_REG register
* Version control * Version control
*/ */
#define SPI_DATE_REG (DR_REG_SPI_BASE + 0xf0) #define SPI_DATE_REG(i) (DR_REG_SPI_BASE(i) + 0xf0)
/** SPI_DATE : R/W; bitpos: [27:0]; default: 37761424; /** SPI_DATE : R/W; bitpos: [27:0]; default: 37761424;
* Version control register. * Version control register.
*/ */

View File

@ -11,6 +11,9 @@
extern "C" { extern "C" {
#endif #endif
#define DR_REG_UART_BASE(i) (DR_REG_UART0_BASE + (i) * 0x1000)
#define REG_UART_BASE(i) (DR_REG_UART0_BASE + (i) * 0x1000)
/** UART_FIFO_REG register /** UART_FIFO_REG register
* FIFO data register * FIFO data register
*/ */

View File

@ -0,0 +1,7 @@
/**
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// TODO: [ESP32H4] IDF-12393

View File

@ -0,0 +1,10 @@
choice ESPTOOLPY_FLASHFREQ
prompt "Flash SPI speed"
default ESPTOOLPY_FLASHFREQ_32M
config ESPTOOLPY_FLASHFREQ_64M
bool "64 MHz"
config ESPTOOLPY_FLASHFREQ_32M
bool "32 MHz"
config ESPTOOLPY_FLASHFREQ_16M
bool "16 MHz"
endchoice

View File

@ -0,0 +1,8 @@
#####################################################
# This file is auto-generated from SoC caps
# using gen_soc_caps_kconfig.py, do not edit manually
#####################################################
config SPI_FLASH_VENDOR_XMC_SUPPORTED
bool
default y

View File

@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#define SPI_FLASH_VENDOR_XMC_SUPPORTED (1)

View File

@ -10,4 +10,4 @@ examples/get-started/blink:
examples/get-started/hello_world: examples/get-started/hello_world:
enable: enable:
- if: INCLUDE_DEFAULT == 1 or IDF_TARGET in ["linux", "esp32c5", "esp32c61", "esp32h21"] - if: INCLUDE_DEFAULT == 1 or IDF_TARGET in ["linux", "esp32c5", "esp32c61", "esp32h21", "esp32h4"]

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | Linux | | Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | Linux |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | ----- | | ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | ----- |
# Hello World Example # Hello World Example

View File

@ -64,7 +64,7 @@ build_stage2() {
--size-file size.json \ --size-file size.json \
--keep-going \ --keep-going \
--collect-size-info size_info.txt \ --collect-size-info size_info.txt \
--default-build-targets esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c5 esp32c6 esp32h2 esp32p4 esp32c61 esp32h21 --default-build-targets esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c5 esp32c6 esp32h2 esp32p4 esp32c61 esp32h21 esp32h4
} }
build_stage1() { build_stage1() {
@ -78,7 +78,7 @@ build_stage1() {
--build-log ${BUILD_LOG_CMAKE} \ --build-log ${BUILD_LOG_CMAKE} \
--size-file size.json \ --size-file size.json \
--collect-size-info size_info.txt \ --collect-size-info size_info.txt \
--default-build-targets esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c5 esp32c6 esp32h2 esp32p4 esp32c61 esp32h21 --default-build-targets esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c5 esp32c6 esp32h2 esp32p4 esp32c61 esp32h21 esp32h4
} }
# Default arguments # Default arguments