深入解析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 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           RISC-V
  Version:                           0x1
  Entry point address:               0x40000000
  Start of program headers:          52 (bytes into file)
  Start of section headers:          553332 (bytes into file)
  Flags:                             0x1, RVC, soft-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         28
  Size of section headers:           40 (bytes)
  Number of section headers:         75
  Section 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 ROM

SPIWP: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 determined
    ESP_RST_POWERON,    //!< Reset due to power-on event
    ESP_RST_EXT,        //!< Reset by external pin (not applicable for ESP32)
    ESP_RST_SW,         //!< Software reset via esp_restart
    ESP_RST_PANIC,      //!< Software reset due to exception/panic
    ESP_RST_INT_WDT,    //!< Reset (software or hardware) due to interrupt watchdog
    ESP_RST_TASK_WDT,   //!< Reset due to task watchdog
    ESP_RST_WDT,        //!< Reset due to other watchdogs
    ESP_RST_DEEPSLEEP,  //!< Reset after exiting deep sleep mode
    ESP_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 initialization
    if (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 partition
    bootloader_state_t bs = {0};
    int boot_index = select_partition_number(&bs);
    if (boot_index == INVALID_INDEX) {
        bootloader_reset();
    }

    // 3. Load the app image for booting
    bootloader_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 WDT
    bootloader_enable_random();  // enable RNG early entropy source

2)分区选择阶段

-->select_partition_number(&bs)      // 步骤2. Select the number of boot partition
    bootloader_utility_load_partition_table(bs) // (1) Load partition table
    selected_boot_partition(bs)                 // (2) Select the number of boot partition
     -->bootloader_utility_get_selected_boot_partition(bs)
           return FACTORY_INDEX; // 如果未设置OTA分区,则返回FACTORY
           read_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 booting
    try_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映射并使能Cache
         set_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应用程序中

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

什么是数据同步利器DataX,如何使用?

转载至我的博客 https://www.infrastack.cn &#xff0c;公众号&#xff1a;架构成长指南 今天给大家分享一个阿里开源的数据同步工具DataX&#xff0c;在Github拥有14.8k的star&#xff0c;非常受欢迎&#xff0c;官网地址&#xff1a;https://github.com/alibaba/DataX 什么…

【Java程序设计】【C00265】基于Springboot的地方废物回收机制管理系统(有论文)

基于Springboot的地方废物回收机制管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的地方废物回收机构管理系统 本系统分为管理员功能模块以及员工功能模块。 管理员功能模块&#xff1a;管理员登录系统后…

spring boot3登录开发-1(整合jwt)

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 jwt简介 导依赖 编写jwt工具类 1.配置项直接嵌入代码&#xff0c;通过类名.静态方法使用 2.配置项写到…

算法刷题:无重复字符的最长字串

无重复字符的最长字串 .题目链接题目详情算法原理题目解析滑动窗口定义指针进窗口判断出窗口更新结果 我的答案 . 题目链接 无重复字符的最长字串 题目详情 算法原理 题目解析 首先,为了使字符串遍历的更加方便,我们选择将字符串转换为数组 题目要求子串中不能有重复的字符…

LaTeX中的documentclass命令:指定文档的类型和整体布局

诸神缄默不语-个人CSDN博文目录 documentclass 是 LaTeX 中一个基础且重要的命令&#xff0c;用于定义文档的整体布局和样式。这个命令告诉 LaTeX 编译器文档是属于哪一类的&#xff0c;比如是文章、报告、书籍等&#xff0c;每一类都有其预定义的格式和结构。 文章目录 基本语…

MongoDB从入门到实战之.NET Core使用MongoDB开发ToDoList系统(2)-Swagger框架集成

Swagger是什么&#xff1f; Swagger是一个规范且完整API文档管理框架&#xff0c;可以用于生成、描述和调用可视化的RESTful风格的 Web 服务。Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口&#xff0c;可以让人和计算机拥有无须访问源码、文档或网络流量监测就…

JDBC 核心 API

引入 mysql-jdbc 驱动 驱动 jar 版本的选择&#xff1a;推荐使用 8.0.25&#xff0c;省略时区设置java 工程导入依赖 项目创建 lib 文件夹导入驱动依赖 jar 包jar 包右键 - 添加为库 JDBC 基本使用步骤 注册驱动获取连接创建发送 sql 语句对象发送 sql 语句&#xff0c;并获…

清华AutoGPT:掀起AI新浪潮,与GPT4.0一较高下

引言&#xff1a; 随着人工智能技术的飞速发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域迎来了一个又一个突破。最近&#xff0c;清华大学研发的AutoGPT成为了业界的焦点。这款AI模型以其出色的性能&#xff0c;展现了中国在AI领域的强大实力。 目录 引言&…

字符串拼接 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 给定 M 个字符( a-z ) &#xff0c;从中取出任意字符(每个字符只能用一次)拼接成长度为 N 的字符串&#xff0c;要求相同的字符不能相邻。 计算出给定的字符列表…

突发!亚马逊创始人贝索斯抛售60亿美元股票,外网疑其或加仓比特币

号外&#xff1a;2.16教链内参《内参&#xff1a;OpenAI Sora惊艳发布&#xff0c;加密圈有人获利超700倍》 前世界首富、全球知名电商平台亚马逊&#xff08;amazon&#xff09;创始人杰夫贝索斯&#xff08;Jeff Bezos&#xff09;最近一周以来接连抛售自家公司股票&#xff…

BulingBuling[Beyond the To-Do List] - 《让金钱为你服务》 [ Make Money Work for You ]

与《财务自由: 赚到足够的钱的有效方法》作者Grant的简短访谈 让钱为你工作 超越待办事项清单 主持人&#xff1a;Erik Fisher Make Money Work for You Beyond the To-Do List Hosted by Erik Fisher 与Erik Fisher一起探索如何确定你生活中最大的财务杠杆以及使用它们的最佳方…

【Linux系统化学习】文件重定向

目录 文件内核对象 文件描述符的分配规则 重定向 重定向的概念 dup2系统调用 输出重定向 追加重定向 输入重定向 stderr解析 重定向到同一个文件中 分离常规输出和错输出 文件内核对象 上篇文章中我们介绍到了操作系统中的文件&#xff0c;操作系统为了方…

什么是智慧公厕,智慧公厕有哪些功能

1.什么是智慧公厕&#xff1f; 随着智慧城市的快速发展&#xff0c;公共厕所作为城市基础设施的一部分&#xff0c;也在逐步升级转型。那么&#xff0c;什么是智慧公厕&#xff1f;智慧公厕作为智慧城市的重要组成部分&#xff0c;将公共厕所的建设、设计、使用、运营和管理等…

报错405(errAxiosError: Request failed with status code 405)

errAxiosError: Request failed with status code 405 前端调用接口的方法跟后台定义接口的方法不一致

docker (四)-docker网络

默认网络 docker会自动创建三个网络&#xff0c;bridge,host,none bridge桥接网络 如果不指定&#xff0c;新创建的容器默认将连接到bridge网络。 默认情况下&#xff0c;使用bridge网络&#xff0c;宿主机可以ping通容器ip&#xff0c;容器中也能ping通宿主机。 容器之间只…

UE4学习笔记 FPS游戏制作5 动画蒙太奇制作开枪动画

创建一个蒙太奇 选择角色的骨骼&#xff0c;并重命名 编辑蒙太奇 将我们需要的动画拖动到Default下的两个白杠的上边那个里 然后在下方的Sections节点中&#xff0c;点击Preview后的Default&#xff0c;选中后&#xff0c;再点击PreviewAllScetions上百年的长的绿色的Defalut&…

使用miniconda管理Python环境

之前经常使用pipenv管理虚拟环境&#xff0c;但是有一个问题就是代码给别人使用的时候&#xff0c;别人使用的Python版本和自己的不一致时&#xff0c;安装依赖包的时候会有问题。所以现在使用miniconda来管理虚拟环境&#xff0c;不仅小巧方便&#xff0c;还能为每个环境指定不…

Gitee入门之工具的安装

一、gitee是什么&#xff1f; Gitee&#xff08;码云&#xff09;是由开源中国社区在2013年推出的一个基于Git的代码托管平台&#xff0c;它提供中国本土化的代码托管服务。它旨在为个人、团队和企业提供稳定、高效、安全的云端软件开发协作平台&#xff0c;具备代码质量分析、…

LeetCode 100题目(python版本)待续...

一.哈希 1.两数之和 题目 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复…

【LeetCode: 103. 二叉树的锯齿形层序遍历 + BFS】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…