Commit cdbd2b55 authored by Lucas Tamborrino's avatar Lucas Tamborrino Committed by Benjamin Cabé
Browse files

soc: espressif: Add hardware initialization

Bring hardware initialization to zephyr code base.

Signed-off-by: default avatarLucas Tamborrino <lucas.tamborrino@espressif.com>
parent 2df905dc
Loading
Loading
Loading
Loading
+12 −0
Changes for soc/espressif/common/include/hw_init.h: 12 added lines, 0 removed lines.
Original line number Diff line number Diff line
/*
 * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef _SOC_ESPRESSIF_COMMON_HW_INIT_H_
#define _SOC_ESPRESSIF_COMMON_HW_INIT_H_

int hardware_init(void);

#endif /* _SOC_ESPRESSIF_COMMON_HW_INIT_H_ */
+81 −60
Changes for soc/espressif/common/loader.c: 81 added lines, 60 removed lines.
Original line number Diff line number Diff line
@@ -14,16 +14,39 @@
#include <esp_rom_sys.h>
#include <esp_err.h>

#define MMU_FLASH_MASK    (~(CONFIG_MMU_PAGE_SIZE - 1))

#include <esp_app_format.h>
#include <zephyr/storage/flash_map.h>
#include "esp_rom_uart.h"
#include "esp_flash.h"
#include "esp_log.h"
#include "bootloader_init.h"
#include "bootloader_random.h"
#include "bootloader_soc.h"
#include <esp_rom_uart.h>
#include <esp_flash.h>
#include <esp_log.h>
#include <bootloader_clock.h>
#include <bootloader_common.h>

#include <esp_cpu.h>

#if CONFIG_SOC_SERIES_ESP32C6
#include <soc/hp_apm_reg.h>
#include <soc/lp_apm_reg.h>
#include <soc/lp_apm0_reg.h>
#include <soc/pcr_reg.h>
#endif /* CONFIG_SOC_SERIES_ESP32C6 */

#include <esp_flash_internal.h>
#include <bootloader_flash.h>
#include <bootloader_flash_priv.h>
#include <hal/efuse_ll.h>
#include <hal/efuse_hal.h>
#include <hal/wdt_hal.h>
#include <soc/chip_revision.h>
#include <soc/rtc.h>
#ifndef CONFIG_SOC_SERIES_ESP32
#include <soc/assist_debug_reg.h>
#include <soc/system_reg.h>
#endif

#include "hw_init.h"
#include "soc_init.h"
#include "soc_random.h"

#define TAG "boot"

@@ -35,25 +58,25 @@
#define IS_DROM(addr)  (addr >= SOC_DROM_LOW && addr < SOC_DROM_HIGH)
#define IS_SRAM(addr)  (IS_IRAM(addr) || IS_DRAM(addr))
#define IS_MMAP(addr)  (IS_IROM(addr) || IS_DROM(addr))
#define IS_NONE(addr) (!IS_IROM(addr) && !IS_DROM(addr) \
			&& !IS_IRAM(addr) && !IS_DRAM(addr) && !IS_PADD(addr))
#define IS_NONE(addr)                                                                              \
	(!IS_IROM(addr) && !IS_DROM(addr) && !IS_IRAM(addr) && !IS_DRAM(addr) && !IS_PADD(addr))

#define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used))

void __start(void);
static HDR_ATTR void (*_entry_point)(void) = &__start;

extern esp_image_header_t bootloader_image_hdr;
esp_image_header_t WORD_ALIGNED_ATTR bootloader_image_hdr;
extern uint32_t _image_irom_start, _image_irom_size, _image_irom_vaddr;
extern uint32_t _image_drom_start, _image_drom_size, _image_drom_vaddr;

#ifndef CONFIG_MCUBOOT
static uint32_t _app_irom_start = (FIXED_PARTITION_OFFSET(slot0_partition) +
						(uint32_t)&_image_irom_start);
static uint32_t _app_irom_start =
	(FIXED_PARTITION_OFFSET(slot0_partition) + (uint32_t)&_image_irom_start);
static uint32_t _app_irom_size = (uint32_t)&_image_irom_size;

static uint32_t _app_drom_start = (FIXED_PARTITION_OFFSET(slot0_partition) +
						(uint32_t)&_image_drom_start);
static uint32_t _app_drom_start =
	(FIXED_PARTITION_OFFSET(slot0_partition) + (uint32_t)&_image_drom_start);
static uint32_t _app_drom_size = (uint32_t)&_image_drom_size;
#endif

@@ -61,15 +84,14 @@ static uint32_t _app_irom_vaddr = ((uint32_t)&_image_irom_vaddr);
static uint32_t _app_drom_vaddr = ((uint32_t)&_image_drom_vaddr);

#ifndef CONFIG_BOOTLOADER_MCUBOOT
static esp_err_t spi_flash_read(uint32_t address, void *buffer, size_t length)
static int spi_flash_read(uint32_t address, void *buffer, size_t length)
{
	return esp_flash_read(NULL, buffer, address, length);
}
#endif /* CONFIG_BOOTLOADER_MCUBOOT */

void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr,
			uint32_t app_drom_size, uint32_t app_irom_start,
			uint32_t app_irom_vaddr, uint32_t app_irom_size)
void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr, uint32_t app_drom_size,
		      uint32_t app_irom_start, uint32_t app_irom_vaddr, uint32_t app_irom_size)
{
	uint32_t app_irom_start_aligned = app_irom_start & MMU_FLASH_MASK;
	uint32_t app_irom_vaddr_aligned = app_irom_vaddr & MMU_FLASH_MASK;
@@ -88,8 +110,7 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr,

	while (segments++ < 16) {

		if (spi_flash_read(offset, &segment_hdr,
				sizeof(esp_image_segment_header_t)) != ESP_OK) {
		if (spi_flash_read(offset, &segment_hdr, sizeof(esp_image_segment_header_t)) != 0) {
			ESP_EARLY_LOGE(TAG, "Failed to read segment header at %x", offset);
			abort();
		}
@@ -101,13 +122,14 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr,
		}

		ESP_EARLY_LOGI(TAG, "%s: lma 0x%08x vma 0x%08x len 0x%-6x (%u)",
			IS_NONE(segment_hdr.load_addr) ? "???" :
			 IS_MMAP(segment_hdr.load_addr) ?
			  IS_IROM(segment_hdr.load_addr) ? "IMAP" : "DMAP" :
			   IS_PADD(segment_hdr.load_addr) ? "padd" :
			    IS_DRAM(segment_hdr.load_addr) ? "DRAM" : "IRAM",
			offset + sizeof(esp_image_segment_header_t),
			segment_hdr.load_addr, segment_hdr.data_len, segment_hdr.data_len);
			       IS_NONE(segment_hdr.load_addr) ? "???"
			       : IS_MMAP(segment_hdr.load_addr)
				       ? IS_IROM(segment_hdr.load_addr) ? "IMAP" : "DMAP"
			       : IS_PADD(segment_hdr.load_addr) ? "padd"
			       : IS_DRAM(segment_hdr.load_addr) ? "DRAM"
								: "IRAM",
			       offset + sizeof(esp_image_segment_header_t), segment_hdr.load_addr,
			       segment_hdr.data_len, segment_hdr.data_len);

		/* Fix drom and irom produced be the linker, as it could
		 * be invalidated by the elf2image and flash load offset
@@ -155,18 +177,18 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr,
	uint32_t drom_page_count =
		(app_drom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;

	rc |= cache_flash_mmu_set(0, 0, app_drom_vaddr_aligned,
					app_drom_start_aligned, 64, drom_page_count);
	rc |= cache_flash_mmu_set(1, 0, app_drom_vaddr_aligned,
					app_drom_start_aligned, 64, drom_page_count);
	rc |= cache_flash_mmu_set(0, 0, app_drom_vaddr_aligned, app_drom_start_aligned, 64,
				  drom_page_count);
	rc |= cache_flash_mmu_set(1, 0, app_drom_vaddr_aligned, app_drom_start_aligned, 64,
				  drom_page_count);

	uint32_t irom_page_count =
		(app_irom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;

	rc |= cache_flash_mmu_set(0, 0, app_irom_vaddr_aligned,
					app_irom_start_aligned, 64, irom_page_count);
	rc |= cache_flash_mmu_set(1, 0, app_irom_vaddr_aligned,
					app_irom_start_aligned, 64, irom_page_count);
	rc |= cache_flash_mmu_set(0, 0, app_irom_vaddr_aligned, app_irom_start_aligned, 64,
				  irom_page_count);
	rc |= cache_flash_mmu_set(1, 0, app_irom_vaddr_aligned, app_irom_start_aligned, 64,
				  irom_page_count);
	if (rc != 0) {
		ESP_EARLY_LOGE(TAG, "Failed to setup XIP, aborting");
		abort();
@@ -174,12 +196,10 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr,
#else
	uint32_t actual_mapped_len = 0;

	mmu_hal_map_region(0, MMU_TARGET_FLASH0,
				app_drom_vaddr_aligned, app_drom_start_aligned,
	mmu_hal_map_region(0, MMU_TARGET_FLASH0, app_drom_vaddr_aligned, app_drom_start_aligned,
			   app_drom_size, &actual_mapped_len);

	mmu_hal_map_region(0, MMU_TARGET_FLASH0,
				app_irom_vaddr_aligned, app_irom_start_aligned,
	mmu_hal_map_region(0, MMU_TARGET_FLASH0, app_irom_vaddr_aligned, app_irom_start_aligned,
			   app_irom_size, &actual_mapped_len);
#endif /* CONFIG_SOC_SERIES_ESP32 */

@@ -206,22 +226,20 @@ void map_rom_segments(uint32_t app_drom_start, uint32_t app_drom_vaddr,

#if !defined(CONFIG_SOC_SERIES_ESP32) && !defined(CONFIG_SOC_SERIES_ESP32S2)
	/* Configure the Cache MMU size for instruction and rodata in flash. */
	uint32_t cache_mmu_irom_size = ((app_irom_size + CONFIG_MMU_PAGE_SIZE - 1) /
			CONFIG_MMU_PAGE_SIZE) * sizeof(uint32_t);
	uint32_t cache_mmu_irom_size =
		((app_irom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE) *
		sizeof(uint32_t);

	/* Split the cache usage by the segment sizes */
	Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size,
				CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
	Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
#endif
	/* Show map segments continue using same log format as during MCUboot phase */
	ESP_EARLY_LOGI(TAG, "%s segment: paddr=%08xh, vaddr=%08xh, size=%05Xh (%6d) map",
			"DROM",
			app_drom_start_aligned, app_drom_vaddr_aligned,
			app_drom_size, app_drom_size);
	ESP_EARLY_LOGI(TAG, "%s segment: paddr=%08xh, vaddr=%08xh, size=%05Xh (%6d) map",
			"IROM",
			app_irom_start_aligned, app_irom_vaddr_aligned,
			app_irom_size, app_irom_size);
	ESP_EARLY_LOGI(TAG, "%s segment: paddr=%08xh, vaddr=%08xh, size=%05Xh (%6d) map", "DROM",
		       app_drom_start_aligned, app_drom_vaddr_aligned, app_drom_size,
		       app_drom_size);
	ESP_EARLY_LOGI(TAG, "%s segment: paddr=%08xh, vaddr=%08xh, size=%05Xh (%6d) map", "IROM",
		       app_irom_start_aligned, app_irom_vaddr_aligned, app_irom_size,
		       app_irom_size);
	esp_rom_uart_tx_wait_idle(0);
}

@@ -240,22 +258,25 @@ void __start(void)

#ifndef CONFIG_BOOTLOADER_MCUBOOT
	/* Init fundamental components */
	if (bootloader_init()) {
	if (hardware_init()) {
		ESP_EARLY_LOGE(TAG, "HW init failed, aborting");
		abort();
	}
#endif

#if !defined(CONFIG_MCUBOOT) && !defined(CONFIG_SOC_ESP32S3_APPCPU)
	map_rom_segments(_app_drom_start, _app_drom_vaddr, _app_drom_size,
			 _app_irom_start, _app_irom_vaddr, _app_irom_size);
	map_rom_segments(_app_drom_start, _app_drom_vaddr, _app_drom_size, _app_irom_start,
			 _app_irom_vaddr, _app_irom_size);
#endif

#ifndef CONFIG_SOC_SERIES_ESP32C2
	/* Disable RNG entropy source as it was already used */
	bootloader_random_disable();

	soc_random_disable();
#endif /* CONFIG_SOC_SERIES_ESP32C2 */
#if defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3)
	/* Disable glitch detection as it can be falsely triggered by EMI interference */
	bootloader_ana_clock_glitch_reset_config(false);

	ESP_EARLY_LOGI(TAG, "Disabling glitch detection");
	ana_clock_glitch_reset_config(false);
#endif /* CONFIG_SOC_SERIES_ESP32S2 */
	ESP_EARLY_LOGI(TAG, "Jumping to the main image...");
	__esp_platform_start();
}
+2 −0
Changes for soc/espressif/esp32/CMakeLists.txt: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@ endif()

zephyr_include_directories(.)

zephyr_sources_ifndef(CONFIG_BOOTLOADER_MCUBOOT hw_init.c)

zephyr_library_sources_ifdef(CONFIG_NEWLIB_LIBC newlib_fix.c)

zephyr_library_sources_ifdef(CONFIG_GDBSTUB gdbstub.c)
+12 −11
Changes for soc/espressif/esp32/default.ld: 12 added lines, 11 removed lines.
Original line number Diff line number Diff line
@@ -274,6 +274,12 @@ SECTIONS
    *libzephyr.a:log_output.*(.literal .text .literal.* .text.*)
    *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*)
    *libzephyr.a:loader.*(.literal .text .literal.* .text.*)
    *libzephyr.a:flash_init.*(.literal .text .literal.* .text.*)
    *libzephyr.a:soc_flash_init.*(.literal .text .literal.* .text.*)
    *libzephyr.a:console_init.*(.literal .text .literal.* .text.*)
    *libzephyr.a:soc_random.*(.literal .text .literal.* .text.*)
    *libzephyr.a:soc_init.*(.literal .text .literal.* .text.*)
    *libzephyr.a:hw_init.*(.literal .text .literal.* .text.*)
    *libzephyr.a:rtc_*.*(.literal .text .literal.* .text.*)
    *libzephyr.a:cpu_util.*(.literal .text .literal.* .text.*)
    *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*)
@@ -403,21 +409,14 @@ SECTIONS
  .loader.text :
  {
    . =  ALIGN(4);
    *libzephyr.a:bootloader_init.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_esp32.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_clock_init.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_wdt.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_flash.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_flash_config_esp32.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_common.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_mem.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_random.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_utility.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_sha.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_console.*(.literal .text .literal.* .text.*)
    *libzephyr.a:bootloader_panic.*(.literal .text .literal.* .text.*)

    *libzephyr.a:esp_image_format.*(.literal .text .literal.* .text.*)
@@ -520,6 +519,12 @@ SECTIONS
    *libzephyr.a:log_backend_uart.*(.rodata .rodata.*)
    *libzephyr.a:log_output.*(.rodata .rodata.*)
    *libzephyr.a:loader.*(.rodata .rodata.*)
    *libzephyr.a:flash_init.*(.rodata .rodata.*)
    *libzephyr.a:soc_flash_init.*(.rodata .rodata.*)
    *libzephyr.a:console_init.*(.rodata .rodata.*)
    *libzephyr.a:soc_random.*(.rodata .rodata.*)
    *libzephyr.a:soc_init.*(.rodata .rodata.*)
    *libzephyr.a:hw_init.*(.rodata .rodata.*)
    *libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*)
    *libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*)
    *libzephyr.a:esp_memory_utils.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
@@ -625,14 +630,10 @@ SECTIONS
  {
    . = ALIGN(4);
    _loader_data_start = ABSOLUTE(.);
    *libzephyr.a:bootloader_init.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
    *libzephyr.a:bootloader_esp32.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
    *libzephyr.a:bootloader_clock_init.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
    *libzephyr.a:bootloader_wdt.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
    *libzephyr.a:bootloader_flash.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
    *libzephyr.a:bootloader_flash_config_esp32.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
    *libzephyr.a:bootloader_common.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
    *libzephyr.a:bootloader_common_loader.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
    *libzephyr.a:bootloader_efuse.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)

    *libzephyr.a:cpu_util.*(.rodata .rodata.* .sdata2 .sdata2.* .srodata .srodata.*)
+94 −0
Changes for soc/espressif/esp32/hw_init.c: 94 added lines, 0 removed lines.
Original line number Diff line number Diff line
/*
 * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "hw_init.h"
#include <stdint.h>
#include <esp_cpu.h>
#include <soc/rtc.h>
#include <esp_rom_sys.h>

#include <bootloader_clock.h>
#include <bootloader_flash.h>
#include <esp_flash_internal.h>
#include <esp_log.h>

#include <console_init.h>
#include <flash_init.h>
#include <soc_flash_init.h>
#include <soc_init.h>
#include <soc_random.h>

const static char *TAG = "hw_init";

int hardware_init(void)
{
	int err = 0;

#if XCHAL_ERRATUM_572
	uint32_t memctl = XCHAL_CACHE_MEMCTL_DEFAULT;

	WSR(MEMCTL, memctl);
#endif /*XCHAL_ERRATUM_572*/

#ifdef CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE
	esp_cpu_configure_region_protection();
#endif
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
	rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();

	if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) {
		cfg.drefh = 3;
		cfg.drefm = 3;
		cfg.drefl = 3;
		cfg.force = 1;
		rtc_vddsdio_set_config(cfg);
		esp_rom_delay_us(10);
	}
#endif /* CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V */

	bootloader_clock_configure();

	/* initialize console, from now on, we can log */
	esp_console_init();
	print_banner();

	spi_flash_init_chip_state();
	err = esp_flash_init_default_chip();
	if (err != 0) {
		ESP_EARLY_LOGE(TAG, "Failed to init flash chip, error %d", err);
		return err;
	}

	reset_mmu();
	flash_update_id();

	err = bootloader_flash_xmc_startup();
	if (err != 0) {
		ESP_EARLY_LOGE(TAG, "failed when running XMC startup flow, reboot!");
		return err;
	}

	err = read_bootloader_header();
	if (err != 0) {
		return err;
	}

	err = check_bootloader_validity();
	if (err != 0) {
		return err;
	}

	err = init_spi_flash();
	if (err != 0) {
		return err;
	}

	check_wdt_reset();
	config_wdt();
	soc_random_enable();

	return 0;
}
Loading