ESP32 是一种基于 ARM Cortex-M 处理器的 32 位微控制器,集成了 2.4GHz Wi-Fi 和蓝牙双模功能。 ESP32 的启动过程可以分为以下三个阶段:
- 一级引导程序:当 ESP32 上电或复位后,PRO CPU 会立即开始运行,执行复位向量代码,而 APP CPU 仍然保持复位状态。 复位向量代码会检查 GPIO_STRAP_REG 寄存器的值,确定 ESP32 的启动模式,如 UART 下载模式、自定义启动模式等。如果是正常启动模式,程序会配置 SPI flash,然后尝试从 flash 的 0x1000 偏移地址处加载二级引导程序的二进制镜像。 程序会校验镜像的校验和,如果正确,就会跳转到镜像的入口点运行。
- 二级引导程序:二级引导程序的源码可以在 ESP-IDF 的 components/bootloader 目录下找到。 二级引导程序会从 flash 的 0x8000 偏移地址处读取分区表,分区表包含了 flash 上不同分区的类型、偏移地址、大小等信息。 二级引导程序会寻找工厂分区和 OTA 应用程序分区,如果存在 OTA 应用程序分区,还会查询 otadata 分区,以确定应该引导哪个分区。 对于选定的分区,二级引导程序会从 flash 中逐段读取应用程序镜像,对于需要加载到 RAM 中的段,会将数据从 flash 复制到它们的加载地址处,对于需要从 flash 中运行的段,会通过配置 flash MMU,提供正确的映射。 一旦处理完所有段,二级引导程序会验证应用程序的完整性,如果使用了安全启动或 flash 加密功能,还会进行相应的验证和解密。最后,二级引导程序会跳转到应用程序镜像的入口点运行。
- 应用程序启动:应用程序启动包含了从应用程序开始执行到 app_main 函数在主任务内部运行前的所有过程。 应用程序启动可以分为三个子阶段:端口初始化:这个阶段会初始化基本的 C 运行环境,配置 CPU 异常,初始化内部存储器,设置 CPU 时钟,如果配置了 PSRAM,还会使能 PSRAM。如果应用程序被配置为在多个内核上运行,还会启动另一个内核并等待其初始化。系统初始化:这个阶段会初始化软件服务和 FreeRTOS,包括堆栈、中断、任务、定时器、事件组、队列、信号量等。 还会初始化一些系统组件,如 NVS、SPI flash、日志、应用程序跟踪等。主任务运行:这个阶段会创建一个主任务,并在其中调用 app_main 函数,这是应用程序的入口函数,用户可以在这里编写自己的代码,实现各种功能和服务。