esp32蓝牙启动流程_ESP32启动流程

esp32蓝⽛启动流程_ESP32启动流程
应⽤程序的启动流程
本⽂将会介绍 ESP32 从上电到运⾏ app_main 函数中间所经历的步骤(即启动流程)。
宏观上,该启动流程可以分为如下 3 个步骤:
⼀级引导程序被固化在了 ESP32 内部的 ROM 中,它会从 Flash 的 0x1000 偏移地址处加载⼆级引导程序⾄ RAM(IRAM & DRAM)中。
⼆级引导程序从 Flash 中加载分区表和主程序镜像⾄内存中,主程序中包含了 RAM 段和通过 Flash ⾼速缓存映射的只读段。
主程序运⾏,这时第⼆个 CPU 和 RTOS 的调度器可以开始运⾏。
下⾯会对上述过程进⾏更为详细的阐述。
⼀级引导程序
SoC 复位后,PRO CPU 会⽴即开始运⾏,执⾏复位向量代码,⽽ APP CPU 仍然保持复位状态。在启
动过程中,PRO CPU 会执⾏所有的初始化操作。APP CPU 的复位状态会在应⽤程序启动代码的 call_start_cpu0 函数中失效。复位向量代码位于 ESP32 芯⽚掩膜 ROM 的 0x40000400 地址处,该地址不能被修改。
复位向量调⽤的启动代码会根据 GPIO_STRAP_REG 寄存器的值来确定 ESP32 的⼯作模式,该寄存器保存着复位后 bootstrap 引脚的电平状态。根据不同的复位原因,程序会执⾏不同的操作:雨水收集利用系统
从深度睡眠模式复位:如果 RTC_CNTL_STORE6_REG 寄存器的值⾮零,并且 RTC_CNTL_STORE7_REG 寄存器中的 RTC 内存的CRC 校验值有效,那么程序会使⽤ RTC_CNTL_STORE6_REG 寄存器的值作为⼊⼝地址,并⽴即跳转到该地址运⾏。如
果 RTC_CNTL_STORE6_REG 的值为零,或者 RTC_CNTL_STORE7_REG 中的 CRC 校验值⽆效,⼜或者跳转
到 RTC_CNTL_STORE6_REG 地址处运⾏的程序返回,那么将会执⾏上电复位的相关操作。 注意 :如果想在这⾥运⾏⾃定义的代码,可以参考 :doc:`深度睡眠 ` ⽂档⾥⾯介绍的⽅法。
上电复位、软件 SoC 复位、看门狗 SoC 复位:检查 GPIO_STRAP_REG 寄存器,判断是否 UART 或 SDIO 请求进⼊下载模式。如果是,则配置好 UART 或者 SDIO,然后等待下载代码。否则程序将会执⾏软件 CPU 复位的相关操作。
软件 CPU 复位、看门狗 CPU 复位:根据 EFUSE 中的值配置 SPI Flash,然后尝试从 Flash 中加载代码,这部分的内存将会在后⾯⼀⼩节详细介绍。如果从 Flash 中加载代码失败,就会将 BASIC 解析器加压缩到 RAM 中启动。需要注意的是,此时 RTC 看门狗还在使能状态,如果在⼏百毫秒内没有任何输⼊事件,那么看门狗会再次复位 SoC,重复整个过程。如果解析器收到了来⾃ UART 的输⼊,程序会关闭看门狗。
应⽤程序的⼆进制镜像会从 Flash 的 0x1000 地址处加载。Flash 的第⼀个 4kB 扇区⽤于存储安全引导程序和应⽤程序镜像的签名。有关详细信息,请查看安全启动⽂档。
⼆级引导程序
在 ESP-IDF 中,存放在 Flash 的 0x1000 偏移地址处的⼆进制镜像就是⼆级引导程序。⼆级引导程序的源码可以在 ESP-IDF 的components/bootloader ⽬录下到。请注意,对于 ESP32 芯⽚来说,这并不是唯⼀的安排程序镜像的⽅式。事实上⽤户完全可以把⼀个功能齐全的应⽤程序烧写到 Flash 的 0x1000 偏移地址处运⾏,但这超出本⽂档的范围。ESP-IDF 使⽤⼆级引导程序可以增加 Flash
分区的灵活性(使⽤分区表),并且⽅便实现 Flash 加密,安全引导和空中升级(OTA)等功能。
当⼀级引导程序校验并加载完⼆级引导程序后,它会从⼆进制镜像的头部到⼆级引导程序的⼊⼝点,并跳转过去运⾏。
⼆级引导程序从 Flash 的 0x8000 偏移地址处读取分区表。详细信息请参阅分区表⽂档 :doc:`分区表 ` 。⼆级引导程序会寻出⼚分区和OTA 分区,然后根据 OTA 信息 分区的数据决引导哪个分区。
平板电脑手机对于选定的分区,⼆级引导程序将映射到 IRAM 和 DRAM 的数据和代码段复制到它们的加载地址处。对于⼀些加载地址位于 DROM 和IROM 区域的段,会通过配置 Flash MMU 为其提供正确的映射。请注意,⼆级引导程序会为 PRO CPU 和 APP CPU 都配置 Flash MMU,但它只使能了 PRO CPU 的 Flash MMU。这么做的原因在于⼆级引导程序的代码被加载到了 APP CPU 的⾼速缓存使⽤的内存区域,因此使能 APP CPU ⾼速缓存的任务就交给了应⽤程序。⼀旦代码加载完毕并且设置好 Flash MMU,⼆级引导程序会从应⽤程序⼆进制镜像⽂件的头部寻⼊⼝地址,然后跳转到该地址处运⾏。
⽬前还不⽀持添加钩⼦函数到⼆级引导程序中以⾃定义应⽤程序分区选择的逻辑,但是可以通过别的途径实现这个需求,⽐如根据某个GPIO 的不同状态来引导不同的应⽤程序镜像。此类⾃定义的功能将在未来添加到 ESP-IDF 中。⽬前,可以通过将 bootloader 组件复制到应⽤程序⽬录并在那⾥进⾏必要的更改来⾃定义引导程序。在这种情况下,ESP-IDF 的编译系统将编译应⽤程序⽬录中的组件⽽不是ESP-IDF 组件⽬录。
应⽤程序启动阶段开关信号
手机展示架
ESP-IDF 应⽤程序的⼊⼝是 components/esp32/cpu_start.c ⽂件中的 call_start_cpu0 函数,该函数主要完成了两件事,⼀是启⽤堆分配器,⼆是使 APP CPU 跳转到其⼊⼝点—— call_start_cpu1 函数。PRO CPU 上的代码会给 APP CPU 设置好⼊⼝地址,解除其复位状态,然后等待 APP CPU 上运⾏的代码设置⼀个全局标志,以表明 APP CPU 已经正常启动。 完成后,PRO CPU 跳转
到 start_cpu0 函数,APP CPU 跳转到 start_cpu1 函数。
start_cpu0 和 start_cpu1 这两个函数都是弱类型的,这意味着如果某些特定的应⽤程序需要修改初始化顺序,就可以通过重写这两个函数来实现。 start_cpu0 默认的实现⽅式是初始化⽤户在 menuconfig 中选择的组件,具体实现步骤可以阅
读 components/esp32/cpu_start.c ⽂件中的源码。请注意,此阶段会调⽤应⽤程序中存在的 C++ 全局构造函数。⼀旦所有必要的组件都初始化好,就会创建 main task ,并启动 FreeRTOS 的调度器。
当 PRO CPU 在 start_cpu0 函数中进⾏初始化的时候,APP CPU 在 start_cpu1 函数中⾃旋,等待 PRO CPU 上的调度器启动。⼀旦PRO CPU 上的调度器启动后,APP CPU 上的代码也会启动调度器。
主任务是指运⾏ app_main 函数的任务,主任务的堆栈⼤⼩和优先级可以在 menuconfig 中进⾏配置。
应⽤程序可以⽤此任务来完成⽤户程序相关的初始化设置,⽐如启动其他的任务。应⽤程序还可以将主任务⽤于事件循环和其他通⽤活动。如果 app_main 函数返回,那么主任务将会被删除。
应⽤程序的内存布局
ESP32 芯⽚具有灵活的内存映射功能,本⼩节将介绍 ESP-IDF 默认使⽤这些功能的⽅式。
ESP-IDF 应⽤程序的代码可以放在以下内存区域之⼀。
IRAM(指令 RAM)
ESP-IDF 将内部 SRAM0 区域(在技术参考⼿册中有定义)的⼀部分分配为指令 RAM。除了开始的 64kB ⽤作 PRO CPU 和 APP CPU 的⾼速缓存外,剩余内存区域(从 0x40080000 ⾄ 0x400A0000 )被⽤来存储应⽤程序中部分需要在RAM中运⾏的代码。
⼀些 ESP-IDF 的组件和 WiFi 协议栈的部分代码通过链接脚本⽂件被存放到了这块内存区域。
如果⼀些应⽤程序的代码需要放在 IRAM 中运⾏,可以使⽤ IRAM_ATTR 宏定义进⾏声明。
#include "esp_attr.h"
void IRAM_ATTR gpio_isr_handler(void* arg)
{
自由落体运动实验// ...
}
下⾯列举了应⽤程序中可能或者应该放⼊ IRAM 中运⾏例⼦。
当注册中断处理程序的时候设置了 ESP_INTR_FLAG_IRAM ,那么中断处理程序就必须要放在 IRAM 中运⾏。这种情况下,ISR 只能调⽤存放在 IRAM 或者 ROM 中的函数。 注意 :⽬前所有 FreeRTOS 的 API 都已经存放到了 IRAM 中,所以在中断中调⽤ FreeRTOS 的中断专属 API 是安全的。如果将 ISR 放在 IRAM 中运⾏,那么必须使⽤宏定义 DRAM_ATTR 将该 ISR ⽤到所有常量数据和调⽤的函数(包括但不限于 const char 数组)放⼊ DRAM 中。
可以将⼀些时间关键的代码放在 IRAM 中,这样可以缩减从 Flash 加载代码所消耗的时间。ESP32 是通过 32kB 的⾼速缓存来从外部Flash 中读取代码和数据的,将函数放在 IRAM 中运⾏可以减少由⾼速缓存未命中引起的时间延迟。
⽏庸置疑,不建议在 ISR 中使⽤ printf 和其余输出函数。出于调试的⽬的,可以在 ISR 中使⽤ ESP_EARLY_LOGx 来输出⽇志,不过要确保将 TAG 和格式字符串都放在了 DRAM 中。
⼩结:
⾸先ESP32是双核CPU,分别是PRO CPU 和 APP CPU。平时都是PRO CPU在跑,APP CPU围观(保持复位)。
琴谱架然后ESP32有两个引导程序BootLoader。最后就是ESP32所谓应⽤程序就是FreeRTOS.
1、Soc复位后,PRO CPU 会⽴即开始运⾏复位向量代码,APP CPU围观。开始执⾏BootLoader1,BootLoader1的⽬的是从 Flash 的 0x1000 地址处加载BootLoader2到RAM.
2、BootLoader2从 Flash 的 0x8000 偏移地址处读取分区表,会通过配置 Flash MMU 为其提供正确的映射。为 PRO CPU 和 APP CPU 都配置 Flash MMU,但它只使能了 PRO CPU 的 Flash MMU,此时APP CPU保持围观。⼀旦代码加载完毕并且设置好 Flash MMU,就会从跳转执⾏应⽤程序,分区表有应⽤程序的地址,如下所⽰。
3、initArduino()初始化FreeRTOS,  xTaskCreatePinnedToCore开始创建PRO CPU的任务loopTask,可以看到任务调⽤了setup()和  loop()函数。
ESP32程序上传过程:
esptool.py v2.1-beta1
<
Chip is ESP32D0WDQ6 (revision (unknown 0xa))
Changing baud rate to 921600
Changed.
Configuring
Auto-detected Flash size: 4MB
Compressed 8192bytes
Writing (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.0 seconds (effective 9362.3 kbit/s)...
Hash of data verified.
Compressed 10464bytes
Writing (100 %)
Wrote 10464 bytes (7012 compressed) at 0x00001000 in 0.1 seconds (effective 973.4 kbit/s)...
Hash of data verified.
Compressed 288720bytes
Writing (8 %)
Writing (16 %)
Writing (25 %)
Writing (33 %)
Writing (41 %)
Writing (50 %)
Writing (58 %)
Writing (66 %)
Writing (75 %)
Writing (83 %)
Writing (91 %)
Writing (100 %)
Wrote 288720 bytes (183136 compressed) at 0x00010000 in 2.5 seconds (effective 928.7 kbit/s)... Hash of data verified.
Compressed 3072bytes
Writing (100 %)
Wrote 3072 bytes (122 compressed) at 0x00008000 in 0.0 seconds (effective 3071.9 kbit/s)...
Hash of data verified.
<
0x0000e000 写了8192 bytes  boot_app0.bin
0x00001000 写了10464 bytes bootloader.bin
0x00010000 写了288720 bytes app0
0x00008000 写了3072 bytes default.bin通过default.csv⽣成

本文发布于:2024-09-25 16:36:17,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/311126.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:程序   代码   引导   复位   地址   函数
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议