深入解析ESP32C3(3)- bootloader启动流程

ESP32C3启动流程可以分为如下3 个步骤:

  1. 一级引导程序(PBL):被固化在了ESP32-C3 内部的ROM 中,它会从flash 的0x0 偏移地址处加载二级引导程序至RAM (IRAM & DRAM) 中。
  2. 二级引导程序(SBL):从flash 中加载分区表和主程序镜像至内存中,主程序中包含了RAM 段和通过flash高速缓存映射的只读段。
  3. 应用程序(RTOS):APP启动运行,这时RTOS 的调度器和第二个CPU(多核)启动。

一级引导程序(PBL) 

PBL固化在ESP32C3芯片内部ROM,无法更改。由于官方没有公开PBL的代码,这里直接参考开发向导的功能介绍。
SoC 复位上电后,CPU 会立即跳转至0x4000_0000地址处,开始执行初始化操作。乐鑫提供了ELF格式的内部固件,以下是ELF头信息:

> riscv32-esp-elf-readelf.exe -h G:\Program\Espressif\tools\esp-rom-elfs\20230113\esp32c3_rev3_rom.elf
ELF Header:Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00Class:                             ELF32Data:                              2's complement, little endianVersion:                           1 (current)OS/ABI:                            UNIX - System VABI Version:                       0Type:                              EXEC (Executable file)Machine:                           RISC-VVersion:                           0x1Entry point address:               0x40000000Start of program headers:          52 (bytes into file)Start of section headers:          553332 (bytes into file)Flags:                             0x1, RVC, soft-float ABISize of this header:               52 (bytes)Size of program headers:           32 (bytes)Number of program headers:         28Size of section headers:           40 (bytes)Number of section headers:         75Section header string table index: 74

 PBL开机日志:

ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x15 (USB_UART_CHIP_RESET),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x4004c634
0x4004c634: uart_rx_readbuff in ROMSPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5820,len:0x1710
load:0x403cc710,len:0x968
load:0x403ce710,len:0x2f9c
entry 0x403cc710
//上面是PBL日志,后面是SBL日志
I (15) boot: ESP-IDF HEAD-HASH-NOTFOUND 2nd stage bootloader
I (15) boot: compile time Jan 23 2024 19:23:22
I (15) boot: chip revision: v0.4

复位向量调用的启动代码会根据GPIO_STRAP_REG 寄存器的值来确定ESP32-C3 的启动模式,该寄存器保存着复位后bootstrap 引脚的电平状态。bootstrap引脚包括:
        • 芯片启动模式– GPIO2、GPIO8 和GPIO9
        • ROM 代码日志打印– GPIO8 (默认开启并从USB Serial打印,GPIO8任意值)

从上表可知,bootstrap引脚决定是否进入下载模式或SPI启动模式。

1)下载模式

用户可通过UART0 或USB 接口将代码下载至flash 中,或将程序加载到SRAM 并在SRAM 中运行程序。
下面几个eFuse 可用于控制启动模式的具体行为:

  • EFUSE_DIS_FORCE_DOWNLOAD
    如果此eFuse 设置为0(默认),软件可通过设置RTC_CNTL_FORCE_DOWNLOAD_BOOT,触发CPU 复位,将芯片启动模式强制从SPI Boot 模式切换至Download Boot 模式;如果此eFuse 设置为1,则禁用RTC_CNTL_FORCE_DOWNLOAD_BOOT。
  • EFUSE_DIS_DOWNLOAD_MODE
    如果此eFuse 设置为1,则禁用Download Boot 模式。
  • EFUSE_ENABLE_SECURITY_DOWNLOAD
    如果此eFuse 设置为1,则在Download Boot 模式下,只允许读取、写入和擦除明文flash,不支持SRAM或寄存器操作。如已禁用Download Boot 模式,请忽略此eFuse。

2)SPI启动模式 

CPU 通过从SPI flash 中读取程序来启动系统。SPI Boot 模式可进一步细分为以下两种启动方式:

  • 常规flash 启动方式:支持安全启动,程序运行在RAM 中
  • 直接启动方式:不支持安全启动,程序直接运行在flash 中。如需使能这一启动方式,请确保下载至flash的bin 文件其前两个字(地址:0x42000000)为0xaedb041d。

SoC复位的原因会被保存于寄存器RTC_CNTL_RESET_CAUSE_PROCPU中,数值定义如下:

CPU在复位后可读取该值,根据不同的复位原因,程序会执行不同的操作: 

(a) 深度睡眠模式复位

深度睡眠模式下,芯片的ROM 和RAM 均将断电,因此在唤醒时SPI 启动(从flash 复制数据)所需时间更长,而RTC 快速内存处于上电状态。因此,为了加速芯片唤醒过程,用户可以将一些代码规模不大(即小于8 KB 的“deep sleep wake stub” )写入RTC 快速内存,并将入口地址写入寄存器RTC_CNTL_STORE6_REG,将RTC 快速内存的CRC 码保存到寄存器RTC_CNTL_STORE7_REG。
当CPU 开启时,开始进行ROM 解包和部分初始化工作。此后,再次计算RTC 快速内存的CRC 码。如果与寄存器RTC_CNTL_STORE7_REG中保存的结果一致,则CPU 跳转至RTC 快速内存的入口地址;否则,运行SoC上电复位的启动流程。

(b) 上电复位、软件SoC 复位、看门狗SoC 复位等

CPU 复位后,PBL引导程序从SPI flash加载SBL引导程序,然后从SBL头部找到程序入口地址并跳转运行,进入SBL引导程序。

IDF系统软件定义了11种复位原因,见代码定义项。

FILE: \components\esp_system\include\esp_system.h
/*** @brief Reset reasons*/
typedef enum {ESP_RST_UNKNOWN,    //!< Reset reason can not be determinedESP_RST_POWERON,    //!< Reset due to power-on eventESP_RST_EXT,        //!< Reset by external pin (not applicable for ESP32)ESP_RST_SW,         //!< Software reset via esp_restartESP_RST_PANIC,      //!< Software reset due to exception/panicESP_RST_INT_WDT,    //!< Reset (software or hardware) due to interrupt watchdogESP_RST_TASK_WDT,   //!< Reset due to task watchdogESP_RST_WDT,        //!< Reset due to other watchdogsESP_RST_DEEPSLEEP,  //!< Reset after exiting deep sleep modeESP_RST_BROWNOUT,   //!< Brownout reset (software or hardware)ESP_RST_SDIO,       //!< Reset over SDIO
} esp_reset_reason_t;

二级引导程序(SBL)

ESP-IDF的二级引导程序(SBL)主要实现了以下的功能:
   增加flash 分区的灵活性(使用分区表);
   方便实现flash 加密;
   安全引导;
   空中升级(OTA) 。
SBL引导固件被烧录于SPI Flash 的0x0000_0000偏移地址处,默认分区大小限制在32KB(见宏CONFIG_PARTITION_TABLE_OFFSET)。其主要源码在ESP-IDF \ component下的子目录bootloader\、bootloader_support\,还有其他被引用的组件,所涉及到的组件可查看编译日志,或直接查看编译结果的子目录情况:

 SBL程序入口 是call_start_cpu0()函数,而该函数结构清晰,内部的步骤,很直观展示SBL的运行流程,分为3个阶段:

  • 初始化阶段
  • 分区选择阶段
  • 镜像加载阶段

File: components\bootloader\subproject\main\bootloader_start.c 

void __attribute__((noreturn)) call_start_cpu0(void)
{// (0. Call the before-init hook, if available)if (bootloader_before_init) {bootloader_before_init();}// 1. Hardware initializationif (bootloader_init() != ESP_OK) {bootloader_reset();}// (1.1 Call the after-init hook, if available)if (bootloader_after_init) {bootloader_after_init();}#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP// If this boot is a wake up from the deep sleep then go to the short way,// try to load the application which worked before deep sleep.// It skips a lot of checks due to it was done before (while first boot).bootloader_utility_load_boot_image_from_deep_sleep();// If it is not successful try to load an application as usual.
#endif// 2. Select the number of boot partitionbootloader_state_t bs = {0};int boot_index = select_partition_number(&bs);if (boot_index == INVALID_INDEX) {bootloader_reset();}// 3. Load the app image for bootingbootloader_utility_load_boot_image(&bs, boot_index);
}

1)初始化阶段

--> bootloader_init(void) : // 步骤1. Hardware initialization  bootloader_hardware_init();bootloader_ana_reset_config();bootloader_init_mem();bootloader_clear_bss_section();bootloader_console_init();bootloader_init_spi_flash()bootloader_config_wdt();     // config WDTbootloader_enable_random();  // enable RNG early entropy source

2)分区选择阶段

-->select_partition_number(&bs)      // 步骤2. Select the number of boot partitionbootloader_utility_load_partition_table(bs) // (1) Load partition tableselected_boot_partition(bs)                 // (2) Select the number of boot partition-->bootloader_utility_get_selected_boot_partition(bs)return FACTORY_INDEX; // 如果未设置OTA分区,则返回FACTORYread_otadata()  // 读取ota_info分区,获得OTA分区的配置信息bootloader_common_get_active_otadata(otadata)write_otadata() //若使能APP回滚机制,OTA机制根据状态来更新ota_info分区的数据update_anti_rollback() //若使能防回滚机制,保证固件版本不会回落到低版本

3)镜像加载阶段

-->bootloader_utility_load_boot_image(&bs, boot_index);  // 步骤3. Load the app image for bootingtry_load_partition(&bs->test, &image_data)-->bootloader_load_image(partition, data) --> image_load(mode, part, data)process_image_header(data, part->offset...)process_segments(data, silent...)process_checksum(sha_handle, checksum_word...)process_appended_hash_and_sig(data, part->offset...)verify_secure_boot_signature(sha_handle, data...)bootloader_sha256_finish(sha_handle, NULL);should_load(load_addr)load_image(&image_data);-->esp_secure_boot_v2_permanently_enable(image_data);  esp_efuse_batch_write_begin();   /* Batch all efuse writes at the end of this function */esp_efuse_batch_write_commit();-->esp_secure_boot_generate_digest()   esp_image_verify_bootloader_data(&bootloader_data);secure_boot_generate(image_len)-->esp_flash_encrypt_init();-->esp_flash_encrypt_contents();-->esp_flash_encrypt_enable();-->unpack_load_app(image_data); // 加载APP程序的代码、数据段到RAM,配置MMU映射并使能Cacheset_cache_and_start_app(drom_addr, .......data->image.entry_addr);--> mmu_hal_map_region(0, MMU_TARGET_FLASH0, drom_load_addr_aligned....)--> mmu_hal_map_region(0, MMU_TARGET_FLASH0, irom_load_addr_aligned....)--> cache_ll_l1_enable_bus(0, bus_mask);     //Enable corresponding buses--> cache_hal_enable(CACHE_TYPE_ALL);    //Enable Cache--> ESP_LOGD(TAG, "start: 0x%08"PRIx32, entry_addr);--> entry_t entry = ((entry_t) entry_addr);    // entry_addr = data->image.entry_addr--> (*entry)();  //跳转到APP应用程序中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/686270.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python解构赋值详解(包含leetcode226.翻转二叉树题目讲解以及python代码)

目录 一、背景 1.1问题 1.2原因 二、解构赋值 2.1定义 2.2解题应用 2.2.1翻转二叉树 2.2.2 思路以及代码 一、背景 1.1问题 在写二叉树相关代码赋值的时候发现这样的写法&#xff0c;担心会发生这样的情况&#xff1a;先把node.right的值给node.left&#xff0c;在把…

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(3)-系统数据集合设计

前言 前几章教程我们把ToDoList系统的基本框架搭建好了&#xff0c;现在我们需要根据我们的需求把ToDoList系统所需要的系统集合&#xff08;相当于关系型数据库中的数据库表&#xff09;。接下来我们先简单概述一下这个系统主要需要实现的功能以及实现这些功能我们需要设计那些…

互联网加竞赛 基于设深度学习的人脸性别年龄识别系统

文章目录 0 前言1 课题描述2 实现效果3 算法实现原理3.1 数据集3.2 深度学习识别算法3.3 特征提取主干网络3.4 总体实现流程 4 具体实现4.1 预训练数据格式4.2 部分实现代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习机器视觉的…

【RL】Value Iteration and Policy Iteration(利用迭代算法求解贝尔曼最优等式)

Lecture 4: Value Iteration and Policy Iteration Value Iteration Algorithm 对于Bellman最优公式&#xff1a; v f ( v ) m a x π ( r γ P π v ) \mathbf{v} f(\mathbf{v}) max_{\pi}(\mathbf{r} \gamma \mathbf{P}_{\pi} \mathbf{v}) vf(v)maxπ​(rγPπ​v) …

『运维备忘录』之 Sed 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等只是&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…

【大厂AI课学习笔记】【2.1 人工智能项目开发规划与目标】(1)发现与明确问题

抱歉&#xff0c;过春节这几天&#xff0c;没有更新。赶紧续上。 人就是这样&#xff0c;放假之前呢&#xff0c;想着趁着这个假期&#xff0c;把很多之前没有做好的事情&#xff0c;都梳理好&#xff0c;该补的也补上&#xff0c;结果一个假期就这样过去了&#xff0c;很多想…

stm32:pwm output模块,记录一下我是用smt32,输出pwm波的记录--(实现--重要)

我是实现了输出pwm波&#xff0c;频率固定&#xff0c;占空比可以不断调整的方法&#xff0c;将PA0接到示波器上&#xff0c;可以看到是一个标准的PWM波&#xff0c;如图下面示波器图。 1&#xff0c;首先是ioc的配置 我刚开始设置的分频的倍数是7199&#xff0c;使得分频的太…

Fiddler抓包(网页、手机、MUMU模拟器)

前置条件&#xff1a;电脑上下载安装好了Fiddler&#xff0c;有浏览器 一、网页抓包 1、fiddler下载安装证书 Tools-Options 勾选下面两个框 点击下面的选项&#xff0c;信任证书 会弹出弹窗&#xff0c;点击yes&#xff08;这个时候注意&#xff0c;DO_NOT_TRUST_FiddlerRo…

七天入门大模型 :大模型量化及低成本部署最佳实践

七天入门大模型已完成了5篇&#xff0c;喜欢记得收藏、关注、点赞。 七天入门大模型 &#xff1a;LLM大模型基础知识最全汇总七天入门大模型 &#xff1a;提示词工程 Prompt Engineering&#xff0c;最全的总结来了&#xff01;七天入门大模型 &#xff1a;LLM和多模态模型高效…

【web | CTF】BUUCTF [BJDCTF2020]Easy MD5

天命&#xff1a;好像也挺实用的题目&#xff0c;也是比较经典吧 天命&#xff1a;把php的MD5漏洞都玩了一遍 第一关&#xff1a;MD5绕过 先声明一下&#xff1a;这题的MD5是php&#xff0c;不是mysql的MD5&#xff0c;把我搞迷糊了 一进来题目啥也没有&#xff0c;那么就要看…

人工智能学习与实训笔记(十五):Scikit-learn库的基础与使用

人工智能专栏文章汇总&#xff1a;人工智能学习专栏文章汇总-CSDN博客 本篇目录 一、介绍 1. 1 Scikit-learn的发展历程及定义 1.2 理解算法包、算法库及算法框架之间的区别和联系 二、Scikit-learn官网结构 三、安装与设置 3.1 Python环境的安装与配置 3.2 Scikit-lea…

【Windows】MacOS制作纯净版Windows10安装U盘

方法一、在window系统中更新win10&#xff08;不更新引导程序&#xff09; cp -rp /Volumes/Windows10专业版\ 64位/* /Volumes/WIN10/https://baijiahao.baidu.com/s?id1760695844372493842&wfrspider&forpc 方法二、在window系统中更新win10&#xff08;更新引导程…

软件实例分享,洗车店系统管理软件会员卡电子系统教程

软件实例分享&#xff0c;洗车店系统管理软件会员卡电子系统教程 一、前言 以下软件教程以 佳易王洗车店会员管理软件V16.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、会员卡号可以绑定车牌号或手机号 2、卡号也可以直接使用手机号&a…

优秀的电机驱动MCU:MM32SPIN360C

DC-DC电源布局注意点&#xff1a; 电源模块布局布线可提前下载芯片的datasheet&#xff08;数据表&#xff09;&#xff0c;按照推荐的布局和布线进行设计。 1) 芯片电源接近原则&#xff1a; 对于为芯片提供电压的开关电源&#xff0c;应确保它尽量靠近芯片放置。这样可以避…

2024 CKS 题库 | 8、沙箱运行容器 gVisor

不等更新题库 CKS 题库 8、沙箱运行容器 gVisor Context 该 cluster 使用 containerd 作为 CRI 运行时。containerd 的默认运行时处理程序是 runc 。 containerd 已准备好支持额外的运行时处理程序 runsc (gVisor)。 Task 使用名为 runsc 的现有运行时处理程序&#xff0c;…

【打工日常】使用docker部署可视化工具docker-ui

一、docker-ui介绍 docker-ui是一个易用且轻量化的Docker管理工具&#xff0c;透过Web界面的操作&#xff0c;方便快捷操作docker容器化工作。 docker-ui拥有易操作化化界面&#xff0c;不须记忆docker指令&#xff0c;仅需下载镜像即可立刻加入完成部署。基于docker的特性&…

AGAST角点检测

一、AGAST角点检测 C #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/common/io.h> #include <pcl/visualization/pcl_visualizer.h> #include <boost/thread/thread.hpp> #include <p…

支付交易——跨境交易

摘要 老王兢兢业业经营生意多年&#xff0c;一步步从小杂货店做到现在&#xff0c;成立大型贸易公司。在做大做强的过程中&#xff0c;老王觉得国内市场已经饱和&#xff0c;竞争处处是红海。老王留意海外很多年了&#xff0c;决定走出去&#xff0c;转向海外:将国外的商品引进…

【51单片机】AD模数转换DA数模转换(江科大)

1.AD/DA介绍 AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号 DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号 AD/DA转换打开了计算机与模拟信号的大门,极大的提高了计算机系统的应用范围,也为模拟信号数字化处理…

Java面向对象案例之打印机对象Printer(一)

类主要结构图 抽象类&#xff1a;Printer&#xff08;打印机作为父类&#xff09;子类&#xff1a;DotMatrixPrinter&#xff08;针式打印机类&#xff09;、InkpetPrinter&#xff08;喷墨打印机类&#xff09;、LaserPrinter&#xff08;激光打印机类&#xff09;测试类&…