2024-03-06 23:48:51 -03:00
|
|
|
/*
|
2024-02-14 18:45:17 +01:00
|
|
|
* Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
|
2024-03-06 23:48:51 -03:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <soc.h>
|
|
|
|
#include <hal/mmu_hal.h>
|
|
|
|
#include <hal/mmu_types.h>
|
|
|
|
#include <hal/cache_types.h>
|
|
|
|
#include <hal/cache_ll.h>
|
|
|
|
#include <hal/cache_hal.h>
|
|
|
|
#include <rom/cache.h>
|
|
|
|
#include <esp_rom_sys.h>
|
2024-02-14 18:45:17 +01:00
|
|
|
#include <esp_err.h>
|
2024-03-06 23:48:51 -03:00
|
|
|
|
2024-02-14 18:45:17 +01:00
|
|
|
#include <esp_app_format.h>
|
2024-03-06 23:48:51 -03:00
|
|
|
#include <zephyr/storage/flash_map.h>
|
2024-09-26 15:04:17 -03:00
|
|
|
#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>
|
|
|
|
|
2025-01-10 10:48:37 -03:00
|
|
|
#include <zephyr/linker/linker-defs.h>
|
|
|
|
#include <kernel_internal.h>
|
|
|
|
|
2024-09-26 15:04:17 -03:00
|
|
|
#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"
|
2024-02-14 18:45:17 +01:00
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
#if defined(CONFIG_SOC_ESP32S3_APPCPU) || defined(CONFIG_SOC_ESP32_APPCPU)
|
|
|
|
#error "APPCPU does not need this file!"
|
|
|
|
#endif
|
|
|
|
|
2024-02-14 18:45:17 +01:00
|
|
|
#define TAG "boot"
|
|
|
|
|
|
|
|
#define CHECKSUM_ALIGN 16
|
2025-02-10 14:54:18 +01:00
|
|
|
#define IS_PADD(addr) (addr == 0)
|
|
|
|
#define IS_DRAM(addr) (addr >= SOC_DRAM_LOW && addr < SOC_DRAM_HIGH)
|
|
|
|
#define IS_IRAM(addr) (addr >= SOC_IRAM_LOW && addr < SOC_IRAM_HIGH)
|
|
|
|
#define IS_IROM(addr) (addr >= SOC_IROM_LOW && addr < SOC_IROM_HIGH)
|
|
|
|
#define IS_DROM(addr) (addr >= SOC_DROM_LOW && addr < SOC_DROM_HIGH)
|
2025-01-07 11:49:09 -03:00
|
|
|
#ifdef SOC_RTC_MEM_SUPPORTED
|
|
|
|
#define IS_RTC(addr) (addr >= SOC_RTC_DRAM_LOW && addr < SOC_RTC_DRAM_HIGH)
|
|
|
|
#else
|
|
|
|
#define IS_RTC(addr) 0
|
|
|
|
#endif
|
|
|
|
#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) && !IS_RTC(addr))
|
2024-03-06 23:48:51 -03:00
|
|
|
|
|
|
|
#define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used))
|
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
#if !defined(CONFIG_SOC_ESP32_APPCPU) && !defined(CONFIG_SOC_ESP32S3_APPCPU)
|
|
|
|
#define PART_OFFSET FIXED_PARTITION_OFFSET(slot0_partition)
|
|
|
|
#else
|
|
|
|
#define PART_OFFSET FIXED_PARTITION_OFFSET(slot0_appcpu_partition)
|
|
|
|
#endif
|
|
|
|
|
2024-03-06 23:48:51 -03:00
|
|
|
void __start(void);
|
|
|
|
static HDR_ATTR void (*_entry_point)(void) = &__start;
|
|
|
|
|
2024-09-26 15:04:17 -03:00
|
|
|
esp_image_header_t WORD_ALIGNED_ATTR bootloader_image_hdr;
|
2024-03-06 23:48:51 -03:00
|
|
|
extern uint32_t _image_irom_start, _image_irom_size, _image_irom_vaddr;
|
|
|
|
extern uint32_t _image_drom_start, _image_drom_size, _image_drom_vaddr;
|
2024-02-14 18:45:17 +01:00
|
|
|
|
2024-07-01 17:05:07 -03:00
|
|
|
#ifndef CONFIG_MCUBOOT
|
2025-01-07 11:49:09 -03:00
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
extern uint32_t _libc_heap_size;
|
2025-01-29 14:25:09 +01:00
|
|
|
static uint32_t libc_heap_size = (uint32_t)&_libc_heap_size;
|
2024-07-01 17:05:07 -03:00
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
static struct rom_segments map = {
|
|
|
|
.irom_map_addr = (uint32_t)&_image_irom_vaddr,
|
|
|
|
.irom_flash_offset = PART_OFFSET + (uint32_t)&_image_irom_start,
|
|
|
|
.irom_size = (uint32_t)&_image_irom_size,
|
|
|
|
.drom_map_addr = ((uint32_t)&_image_drom_vaddr),
|
|
|
|
.drom_flash_offset = PART_OFFSET + (uint32_t)&_image_drom_start,
|
|
|
|
.drom_size = (uint32_t)&_image_drom_size,
|
|
|
|
};
|
2024-02-14 18:45:17 +01:00
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
void map_rom_segments(int core, struct rom_segments *map)
|
2024-03-06 23:48:51 -03:00
|
|
|
{
|
2025-02-10 14:54:18 +01:00
|
|
|
uint32_t app_irom_vaddr_align = map->irom_map_addr & MMU_FLASH_MASK;
|
|
|
|
uint32_t app_irom_start_align = map->irom_flash_offset & MMU_FLASH_MASK;
|
2024-03-06 23:48:51 -03:00
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
uint32_t app_drom_vaddr_align = map->drom_map_addr & MMU_FLASH_MASK;
|
|
|
|
uint32_t app_drom_start_align = map->drom_flash_offset & MMU_FLASH_MASK;
|
2024-03-06 23:48:51 -03:00
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
/* Traverse segments to fix flash offset changes due to post-build processing */
|
2024-02-14 18:45:17 +01:00
|
|
|
#ifndef CONFIG_BOOTLOADER_MCUBOOT
|
|
|
|
esp_image_segment_header_t WORD_ALIGNED_ATTR segment_hdr;
|
|
|
|
size_t offset = FIXED_PARTITION_OFFSET(boot_partition);
|
|
|
|
bool checksum = false;
|
|
|
|
unsigned int segments = 0;
|
|
|
|
unsigned int ram_segments = 0;
|
|
|
|
|
|
|
|
offset += sizeof(esp_image_header_t);
|
|
|
|
|
|
|
|
while (segments++ < 16) {
|
|
|
|
|
2025-01-10 10:48:37 -03:00
|
|
|
if (esp_rom_flash_read(offset, &segment_hdr,
|
|
|
|
sizeof(esp_image_segment_header_t), true) != 0) {
|
2024-07-29 15:01:55 -03:00
|
|
|
ESP_EARLY_LOGE(TAG, "Failed to read segment header at %x", offset);
|
2024-02-14 18:45:17 +01:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: Find better end-of-segment detection */
|
|
|
|
if (IS_NONE(segment_hdr.load_addr)) {
|
|
|
|
/* Total segment count = (segments - 1) */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2024-07-29 15:01:55 -03:00
|
|
|
ESP_EARLY_LOGI(TAG, "%s: lma 0x%08x vma 0x%08x len 0x%-6x (%u)",
|
2025-01-07 11:49:09 -03:00
|
|
|
IS_NONE(segment_hdr.load_addr) ? "???" :
|
|
|
|
IS_MMAP(segment_hdr.load_addr) ?
|
|
|
|
IS_IROM(segment_hdr.load_addr) ? "IMAP" : "DMAP" :
|
|
|
|
IS_DRAM(segment_hdr.load_addr) ? "DRAM" :
|
|
|
|
IS_RTC(segment_hdr.load_addr) ? "RTC" : "IRAM",
|
|
|
|
offset + sizeof(esp_image_segment_header_t),
|
|
|
|
segment_hdr.load_addr, segment_hdr.data_len, segment_hdr.data_len);
|
2024-02-14 18:45:17 +01:00
|
|
|
|
|
|
|
/* Fix drom and irom produced be the linker, as it could
|
|
|
|
* be invalidated by the elf2image and flash load offset
|
|
|
|
*/
|
2025-02-10 14:54:18 +01:00
|
|
|
if (segment_hdr.load_addr == map->drom_map_addr) {
|
|
|
|
map->drom_flash_offset = offset + sizeof(esp_image_segment_header_t);
|
|
|
|
app_drom_start_align = map->drom_flash_offset & MMU_FLASH_MASK;
|
2024-02-14 18:45:17 +01:00
|
|
|
}
|
2025-02-10 14:54:18 +01:00
|
|
|
if (segment_hdr.load_addr == map->irom_map_addr) {
|
|
|
|
map->irom_flash_offset = offset + sizeof(esp_image_segment_header_t);
|
|
|
|
app_irom_start_align = map->irom_flash_offset & MMU_FLASH_MASK;
|
2024-02-14 18:45:17 +01:00
|
|
|
}
|
2025-01-07 11:49:09 -03:00
|
|
|
if (IS_SRAM(segment_hdr.load_addr) || IS_RTC(segment_hdr.load_addr)) {
|
2024-02-14 18:45:17 +01:00
|
|
|
ram_segments++;
|
|
|
|
}
|
2025-01-07 11:49:09 -03:00
|
|
|
|
2024-02-14 18:45:17 +01:00
|
|
|
offset += sizeof(esp_image_segment_header_t) + segment_hdr.data_len;
|
|
|
|
|
|
|
|
if (ram_segments == bootloader_image_hdr.segment_count && !checksum) {
|
|
|
|
offset += (CHECKSUM_ALIGN - 1) - (offset % CHECKSUM_ALIGN) + 1;
|
|
|
|
checksum = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (segments == 0 || segments == 16) {
|
2024-07-29 15:01:55 -03:00
|
|
|
ESP_EARLY_LOGE(TAG, "Error parsing segments");
|
2024-02-14 18:45:17 +01:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2024-07-29 15:01:55 -03:00
|
|
|
ESP_EARLY_LOGI(TAG, "Image with %d segments", segments - 1);
|
2024-02-14 18:45:17 +01:00
|
|
|
#endif /* !CONFIG_BOOTLOADER_MCUBOOT */
|
|
|
|
|
2024-03-06 23:48:51 -03:00
|
|
|
#if CONFIG_SOC_SERIES_ESP32
|
2025-02-10 14:54:18 +01:00
|
|
|
Cache_Read_Disable(core);
|
|
|
|
Cache_Flush(core);
|
2024-03-06 23:48:51 -03:00
|
|
|
#else
|
|
|
|
cache_hal_disable(CACHE_TYPE_ALL);
|
2024-02-14 18:45:17 +01:00
|
|
|
#endif /* CONFIG_SOC_SERIES_ESP32 */
|
2024-03-06 23:48:51 -03:00
|
|
|
|
|
|
|
/* Clear the MMU entries that are already set up,
|
|
|
|
* so the new app only has the mappings it creates.
|
|
|
|
*/
|
2025-02-10 14:54:18 +01:00
|
|
|
if (core == 0) {
|
|
|
|
mmu_hal_unmap_all();
|
|
|
|
}
|
2024-03-06 23:48:51 -03:00
|
|
|
|
|
|
|
#if CONFIG_SOC_SERIES_ESP32
|
|
|
|
int rc = 0;
|
|
|
|
uint32_t drom_page_count =
|
2025-02-10 14:54:18 +01:00
|
|
|
(map->drom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;
|
2024-03-06 23:48:51 -03:00
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
rc |= cache_flash_mmu_set(core, 0, app_drom_vaddr_align, app_drom_start_align, 64,
|
2024-09-26 15:04:17 -03:00
|
|
|
drom_page_count);
|
2024-03-06 23:48:51 -03:00
|
|
|
|
|
|
|
uint32_t irom_page_count =
|
2025-02-10 14:54:18 +01:00
|
|
|
(map->irom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE;
|
2024-03-06 23:48:51 -03:00
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
rc |= cache_flash_mmu_set(core, 0, app_irom_vaddr_align, app_irom_start_align, 64,
|
2024-09-26 15:04:17 -03:00
|
|
|
irom_page_count);
|
2024-03-06 23:48:51 -03:00
|
|
|
if (rc != 0) {
|
2025-02-10 14:54:18 +01:00
|
|
|
ESP_EARLY_LOGE(TAG, "Failed to setup flash cache (e=0x%X). Aborting!", rc);
|
2024-03-06 23:48:51 -03:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
#else
|
2024-07-01 17:05:07 -03:00
|
|
|
uint32_t actual_mapped_len = 0;
|
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
mmu_hal_map_region(core, MMU_TARGET_FLASH0, app_drom_vaddr_align, app_drom_start_align,
|
|
|
|
map->drom_size, &actual_mapped_len);
|
2024-03-06 23:48:51 -03:00
|
|
|
|
2025-02-10 14:54:18 +01:00
|
|
|
mmu_hal_map_region(core, MMU_TARGET_FLASH0, app_irom_vaddr_align, app_irom_start_align,
|
|
|
|
map->irom_size, &actual_mapped_len);
|
2024-02-14 18:45:17 +01:00
|
|
|
#endif /* CONFIG_SOC_SERIES_ESP32 */
|
2024-03-06 23:48:51 -03:00
|
|
|
|
|
|
|
/* ----------------------Enable corresponding buses---------------- */
|
2025-02-10 14:54:18 +01:00
|
|
|
cache_bus_mask_t bus_mask;
|
|
|
|
|
|
|
|
bus_mask = cache_ll_l1_get_bus(core, app_drom_vaddr_align, map->drom_size);
|
|
|
|
cache_ll_l1_enable_bus(core, bus_mask);
|
|
|
|
bus_mask = cache_ll_l1_get_bus(core, app_irom_vaddr_align, map->irom_size);
|
|
|
|
cache_ll_l1_enable_bus(core, bus_mask);
|
2024-03-06 23:48:51 -03:00
|
|
|
|
|
|
|
#if CONFIG_MP_MAX_NUM_CPUS > 1
|
2025-02-10 14:54:18 +01:00
|
|
|
bus_mask = cache_ll_l1_get_bus(1, app_drom_vaddr_align, map->drom_size);
|
2024-03-06 23:48:51 -03:00
|
|
|
cache_ll_l1_enable_bus(1, bus_mask);
|
2025-02-10 14:54:18 +01:00
|
|
|
bus_mask = cache_ll_l1_get_bus(1, app_irom_vaddr_align, map->irom_size);
|
2024-03-06 23:48:51 -03:00
|
|
|
cache_ll_l1_enable_bus(1, bus_mask);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* ----------------------Enable Cache---------------- */
|
|
|
|
#if CONFIG_SOC_SERIES_ESP32
|
|
|
|
/* Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) */
|
2025-02-10 14:54:18 +01:00
|
|
|
Cache_Read_Enable(core);
|
2024-03-06 23:48:51 -03:00
|
|
|
#else
|
|
|
|
cache_hal_enable(CACHE_TYPE_ALL);
|
2024-02-14 18:45:17 +01:00
|
|
|
#endif /* CONFIG_SOC_SERIES_ESP32 */
|
|
|
|
|
2024-04-16 20:05:37 +02:00
|
|
|
#if !defined(CONFIG_SOC_SERIES_ESP32) && !defined(CONFIG_SOC_SERIES_ESP32S2)
|
|
|
|
/* Configure the Cache MMU size for instruction and rodata in flash. */
|
2024-09-26 15:04:17 -03:00
|
|
|
uint32_t cache_mmu_irom_size =
|
2025-02-10 14:54:18 +01:00
|
|
|
((map->irom_size + CONFIG_MMU_PAGE_SIZE - 1) / CONFIG_MMU_PAGE_SIZE) *
|
2024-09-26 15:04:17 -03:00
|
|
|
sizeof(uint32_t);
|
2024-04-16 20:05:37 +02:00
|
|
|
|
|
|
|
/* Split the cache usage by the segment sizes */
|
2024-09-26 15:04:17 -03:00
|
|
|
Cache_Set_IDROM_MMU_Size(cache_mmu_irom_size, CACHE_DROM_MMU_MAX_END - cache_mmu_irom_size);
|
2024-04-16 20:05:37 +02:00
|
|
|
#endif
|
2024-03-06 23:48:51 -03:00
|
|
|
}
|
2025-02-10 14:54:18 +01:00
|
|
|
#endif /* !CONFIG_MCUBOOT */
|
2024-03-06 23:48:51 -03:00
|
|
|
|
|
|
|
void __start(void)
|
|
|
|
{
|
2024-02-14 18:45:17 +01:00
|
|
|
#ifdef CONFIG_RISCV_GP
|
2025-01-10 10:48:37 -03:00
|
|
|
|
|
|
|
__asm__ __volatile__("la t0, _esp_vector_table\n"
|
|
|
|
"csrw mtvec, t0\n");
|
|
|
|
|
|
|
|
/* Disable normal interrupts. */
|
|
|
|
csr_read_clear(mstatus, MSTATUS_MIE);
|
|
|
|
|
2024-02-14 18:45:17 +01:00
|
|
|
/* Configure the global pointer register
|
|
|
|
* (This should be the first thing startup does, as any other piece of code could be
|
|
|
|
* relaxed by the linker to access something relative to __global_pointer$)
|
|
|
|
*/
|
|
|
|
__asm__ __volatile__(".option push\n"
|
2024-09-26 15:04:17 -03:00
|
|
|
".option norelax\n"
|
|
|
|
"la gp, __global_pointer$\n"
|
|
|
|
".option pop");
|
2024-02-14 18:45:17 +01:00
|
|
|
|
2025-01-10 10:48:37 -03:00
|
|
|
z_bss_zero();
|
|
|
|
|
|
|
|
#else /* xtensa */
|
|
|
|
|
|
|
|
extern uint32_t _init_start;
|
|
|
|
|
|
|
|
/* Move the exception vector table to IRAM. */
|
|
|
|
__asm__ __volatile__("wsr %0, vecbase" : : "r"(&_init_start));
|
|
|
|
|
|
|
|
z_bss_zero();
|
|
|
|
|
|
|
|
__asm__ __volatile__("" : : "g"(&__bss_start) : "memory");
|
|
|
|
|
|
|
|
/* Disable normal interrupts. */
|
|
|
|
__asm__ __volatile__("wsr %0, PS" : : "r"(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE));
|
|
|
|
|
|
|
|
/* Initialize the architecture CPU pointer. Some of the
|
|
|
|
* initialization code wants a valid arch_current_thread() before
|
|
|
|
* arch_kernel_init() is invoked.
|
|
|
|
*/
|
|
|
|
__asm__ __volatile__("wsr.MISC0 %0; rsync" : : "r"(&_kernel.cpus[0]));
|
|
|
|
|
|
|
|
#endif /* CONFIG_RISCV_GP */
|
|
|
|
|
|
|
|
/* Initialize hardware only during 1st boot */
|
|
|
|
#if defined(CONFIG_MCUBOOT) || defined(CONFIG_ESP_SIMPLE_BOOT)
|
2024-09-26 15:04:17 -03:00
|
|
|
if (hardware_init()) {
|
2024-07-29 15:01:55 -03:00
|
|
|
ESP_EARLY_LOGE(TAG, "HW init failed, aborting");
|
2024-02-14 18:45:17 +01:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
#endif
|
2024-03-06 23:48:51 -03:00
|
|
|
|
2025-01-10 10:48:37 -03:00
|
|
|
#if defined(CONFIG_ESP_SIMPLE_BOOT) || defined(CONFIG_BOOTLOADER_MCUBOOT)
|
2025-02-10 14:54:18 +01:00
|
|
|
map_rom_segments(0, &map);
|
|
|
|
|
|
|
|
/* 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", "IROM",
|
|
|
|
map.irom_flash_offset, map.irom_map_addr, map.irom_size, map.irom_size);
|
|
|
|
ESP_EARLY_LOGI(TAG, "%s segment: paddr=%08xh, vaddr=%08xh, size=%05Xh (%6d) map", "DROM",
|
|
|
|
map.drom_flash_offset, map.drom_map_addr, map.drom_size, map.drom_size);
|
|
|
|
esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
|
|
|
|
|
2024-07-09 14:04:20 -03:00
|
|
|
/* Disable RNG entropy source as it was already used */
|
2024-09-26 15:04:17 -03:00
|
|
|
soc_random_disable();
|
2025-01-10 10:48:37 -03:00
|
|
|
|
2024-07-09 14:04:20 -03:00
|
|
|
/* Disable glitch detection as it can be falsely triggered by EMI interference */
|
2024-09-26 15:04:17 -03:00
|
|
|
ana_clock_glitch_reset_config(false);
|
2025-01-10 10:48:37 -03:00
|
|
|
|
2025-01-29 14:25:09 +01:00
|
|
|
ESP_EARLY_LOGI(TAG, "libc heap size %d kB.", libc_heap_size / 1024);
|
2025-01-10 10:48:37 -03:00
|
|
|
|
|
|
|
__esp_platform_app_start();
|
|
|
|
#endif /* CONFIG_ESP_SIMPLE_BOOT || CONFIG_BOOTLOADER_MCUBOOT */
|
|
|
|
|
|
|
|
#if defined(CONFIG_MCUBOOT)
|
|
|
|
__esp_platform_mcuboot_start();
|
2025-01-29 14:25:09 +01:00
|
|
|
#endif
|
2024-03-06 23:48:51 -03:00
|
|
|
}
|