首页 > 其他分享 >【ESP 乐鑫相关】ESP32-S3启动流程

【ESP 乐鑫相关】ESP32-S3启动流程

时间:2025-01-18 09:57:21浏览次数:1  
标签:bootloader 函数 ESP S3 ESP32 start main app

转载自:https://blog.itpub.net/70040860/viewspace-3053923/

ESP32-S3启动流程

       本文将会介绍ESP32-S3从上电到运行app_main函数中间所经历的步骤(即启动流程)。从宏观上,该启动流程可分为如下3个步骤。

       ①:一级引导程序,它被固化在ESP32-S3内部的ROM中,它会从flash的0x00处地址加载二级引导程序至RAM中。

       ②:二级引导程序从flash中加载分区表和主程序镜像至内存中,主程序中包含了RAM段和通过flash高速缓存映射的只读段。

       ③:应用程序启动阶段运行,这时第二个CPU和freeRTOS的调度器启动,最后进入app_main函数执行用户代码。

       下面作者根据IDF库相关的代码来讲解这三个引导流程,如下:

 

       一、一级引导程序

       该部分程序是直接存储在ESP32-S3内部ROM中,所以普通开发者无法直接查看,它主要是做一些前期的准备工作(复位向量代码),然后从flash 0x00偏移地址中读取二级引导程序文件头中的配置信息,并使用这些信息来加载剩余的二级引导程序。

 

       二、二级引导程序

       该程序是可以查看且可被修改,在搭建ESP-IDF环境完成后,可在esp-idf\components\bootloader/subproject/main/路径下找到bootloader_start.c文件,此文件就是二级引导程序启动处。首先我们克隆ESP-IDF库,克隆过程如下所示。

 

图4.6.1 克隆ESP-IDF库

 

       克隆完成后,使用VSCode打开ESP-IDF库,接着找到bootloader_start.c,如下图所示。

 

图4.6.2 bootloader_start.c文件路径

 

       在这个文件下,找到call_start_cpu0函数,此函数是bootloader程序,如下是bootloader程序的部分代码。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 /*  ROM引导加载程序完成从闪存加载第二阶段引导加载程序之后到达这里  */ void __attribute__((noreturn)) call_start_cpu0(void) {     if (bootloader_before_init) {         bootloader_before_init();     }    /* 1. 硬件初始化:清楚bss段、开启cache、复位mmc等操作 bootloader_support/src/esp32s3/bootloader_esp32s3.c */     if (bootloader_init() != ESP_OK) {         bootloader_reset();     }        if (bootloader_after_init) {         bootloader_after_init();     }           /* 2. 选择启动分区的数量:加载分区表,选择boot分区 */     bootloader_state_t bs = {0};     int boot_index = select_partition_number(&bs);           if (boot_index == INVALID_INDEX){         bootloader_reset();     }    /* 3. 加载应用程序映像并启动 bootloader_support/src/esp32s3/bootloader_utility.c */     bootloader_utility_load_boot_image(&bs, boot_index); }

       ESP-IDF使用二级引导程序可以增加FLASH分区的灵活性(使用分区表),并且方便实现FLASH加密,安全引导和空中升级(OTA)等功能。主要的作用是从flash的0x8000处加载分区表(请看在线ESP32-IDF编程指南分区表章  节)。根据分区表运行应用程序。

 

       三、三级引导程序

       应用程序的入口是在esp-idf/components/esp_system/port/路径下的cpu_star.c文件,在此文件下找到call_start_cpu0函数(端口层初始化函数)。这个函数由二级引导加载程序执行,并且从不返回。因此你看不到是哪个函数调用了它,它是从汇编的最 底层直接调用的。

       个函数会初始化基本的C运行环境(“CRT”),并对SOC的内部硬件进行了初始配置。执行call_start_cpu0函数完成之后,在components\esp_system\startup.c文件下调用start_cpu0(在110行中,弱关联start_cpu0_default函数)系统层初始化函数,如下start_cpu0_default函数的部分代码。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 static void start_cpu0_default(void) {        ESP_EARLY_LOGI(TAG, "Pro cpu start user code");     /* 获取CPU时钟 */     int cpu_freq = esp_clk_cpu_freq();     ESP_EARLY_LOGI(TAG, "cpu freq: %d Hz", cpu_freq);        /* 初始化核心组件和服务 */     do_core_init();        /* 执行构造函数 */     do_global_ctors();        /* 执行其他组件的init函数 */     do_secondary_init();     /* 开启APP程序 */     esp_startup_start_app();     while (1); }

       到了这里,就完成了二级程序引导,并调用esp_startup_start_app函数进入三级引导程序,该函数的源码如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 /* components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c */ /* 开启APP程序 */ void esp_startup_start_app(void) {     /* 省略部分代码 */     /* 新建main任务函数 */     esp_startup_start_app_common();        /* 开启FreeRTOS任务调度 */     vTaskStartScheduler(); }    /* components/freertos/FreeRTOS-Kernel/portable/port_common.c */ /* 新建main任务函数 */ void esp_startup_start_app_common(void) {     /* 省略部分代码 */     /* 创建main任务 */     portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",                                                 ESP_TASK_MAIN_STACK, NULL,                                                 ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE);     assert(res == pdTRUE);     (void)res; }    /* main任务函数 */ static void main_task(void* args) {     /* 省略部分代码 */     /* 执行app_main函数 */     app_main();     vTaskDelete(NULL); }

       从上述源码可知,首先在esp_startup_start_app_common函数调用FreeRTOS API创建main任务,然后开启freeRTOS任务调度器,最后在main任务下调用app_main函数(此函数在创建工程时,在main.c下定义的)。

       同理,ESP32S3的MicroPython固件也是以这种方式启动的。此外,MicroPython的app_main函数是在ports/esp32/main.c文件中定义的。在该文件中,会进行UART、USB和特定库的初始化操作。

标签:bootloader,函数,ESP,S3,ESP32,start,main,app
From: https://www.cnblogs.com/FBsharl/p/18678053

相关文章

  • 举例说明在css3中怎么实现背景裁剪?
    在CSS3中,你可以使用background-clip属性来实现背景裁剪。background-clip属性定义背景的绘制区域,也就是说,它决定了背景图像或背景色应该显示到哪个边界为止。这个属性有四个可能的值:border-box、padding-box、content-box和text。下面是一个简单的例子来说明如何使用background-c......
  • libsql 多租户namespace模式试用
    libsql支持基于db分离的多租户模式,但是需要开启namespace能力,以下是一个简单说明以及测试开启namepace我基于docker-compose部署,目前docker部署的缺少环境变量支持,我基于了cmd运行,核心是--enable-namespacesdocker-composeservices:db1:image:ghcr.io/turs......
  • 基于 KubeSphere v4 的 Kubernetes 生产环境部署架构设计及成本分析
    本文作者:运维有术。今天分享的主题是:如何规划设计一个高可用、可扩展的中小规模生产级K8s集群?通过本文的指导,您将掌握以下设计生产级K8s集群的必备技能:集群规划能力合理规划节点规模和资源配置设计高可用的控制平面、计算平面、存储平面架构规划网络拓扑和安全策略制......
  • 如何使用css3实现一个div设置多张背景图片?
    在CSS3中,你可以使用background-image属性为一个div设置多张背景图片。这些图片将按照它们在值列表中的顺序堆叠,第一张图片位于最前面(即最靠近用户),最后一张图片位于最后面。以下是一个示例:div{width:500px;height:500px;background-image:url(image1.jpg),url(image......
  • 小白开发选择树莓派还是ESP
    树莓派(RaspberryPi)和ESP(如ESP8266、ESP32)都是非常受欢迎的开源硬件平台,它们各有优缺点,适用于不同的开发场景。对于小白开发者来说,选择哪一个取决于你的具体需求、项目目标和预算。以下是对树莓派和ESP的详细对比,帮助你做出选择:1.性能树莓派处理器:树莓派通常配备四核ARM......
  • Peripheral Myelin Protein P2 (53-78),bovine;外周髓鞘蛋白P2(53-78),牛;TESPFKNTEISFKLGQEFE
    【PeripheralMyelinProteinP2(53-78),bovine 简介】    PeripheralMyelinProteinP2(53-78),bovine(简称PMP2)是一种来源于牛的外周髓鞘P2蛋白的肽段,具体来说,是由该蛋白的第53至78位氨基酸残基组成的片段。PeripheralMyelinProteinP2(53-78),bovine是一种......
  • gesp(C++五级)(5)洛谷:B3929:[GESP202312 五级] 小杨的幸运数
    gesp(C++五级)(5)洛谷:B3929:[GESP202312五级]小杨的幸运数题目描述小杨认为,所有大于等于aaa的完全平方数都是他的超级幸运数。小杨还认为,所有超级幸运数的倍数都是他......
  • gesp(C++五级)(6)洛谷:B3930:[GESP202312 五级] 烹饪问题
    gesp(C++五级)(6)洛谷:B3930:[GESP202312五级]烹饪问题题目描述有NNN种食材,编号从00......
  • 【花雕学编程】Arduino动手做(246)---ESP8266 NodeMCU V3 Web Server
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来——小小的......
  • 【花雕学编程】Arduino动手做(246)---设置ESP8266 V3 通过串口输出软AP的IP、MAC和WiFi
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来——小小的......