深入了解 ESP32-CAM:系统架构、内存地址和开机流程详解

介绍 ESP32-CAM 系统架构、内存地址、开机流程

目录

  • 介绍 ESP32-CAM 系统架构、内存地址、开机流程
  • ESP32-CAM 系统架构
  • ESP32 启动流程
  • 参考资料
  • ESP32-CAM 系统架构

    因为 ESP32-CAM 内核是 ESP32,所以以下所有的说明来自 ESP32 技术参考手册。 ESP32 是一个双核系统,具有两个哈佛架构(Harvard Architecture) Xtensa LX6 CPU。所有嵌入式内存(embedded memory),外部内存(external memory)和外围设备(peripherals)位于这些 CPU 的数据总线和/或指令总线上。

    两个 CPU 的地址映射是对称的,这意味着它们使用相同的地址访问相同的内存。系统中的多个外设可以通过 DMA (Direct Memory Access 直接内存存取,以下简称 DMA) 访问嵌入式内存。

    这两个 CPU 被命名为 “PRO_CPU” 和 “APP_CPU”(分别代表“协议(Protocol)”和“应用程序(Application”),但是,对于大多数用途而言,这两个 CPU 是可以互换的。

    地址空间

  • 对称地址映射
  • 4 GB(32 位)地址空间用于数据总线和指令总线
  • 1296 KB 嵌入式内存地址空间
  • 19704 KB 外部内存地址空间
  • 512 KB 外设地址空间
  • 一些嵌入式和外部内存区域可以通过数据总线或指令总线访问
  • 328 KB DMA 地址空间
  • 嵌入式内存

  • 448 KB 内部 ROM
  • 520 KB 内部 SRAM
  • 8 KB RTC (Real-Time Clock 实时时钟, 以下简称 RTC) 快速内存
  • 8 KB RTC 慢内存
  • 外部内存
    片外(off-Chip) SPI (Serial Peripheral Interface串行外设接口, 以下简称 SPI)存储器可以映射到可用地址空间作为外部内存。部分的嵌入式内存可用作该外部内存的透明缓存。

  • 支持高达 16 MB 的 off-Chip SPI 闪存 (Flash)。
  • 支持高达 8 MB 的 off-Chip SPI SRAM (PSRAM)。
  • 外围设备

  • 41 个外设 (Peripherals)
  • 直接存取

  • 13 个模块能够进行 DMA 操作
  • 常用存储器的介绍:

  • 数据易失性的存储器:这类存储器读写速度较快,但是掉电后数据会丢失,在 SoC 设计中通常被用作数据缓存、程序缓存。常见的是随机存取存储器 (Random Access Memory, 以下简称 RAM) ,常见的种类有 DRAM (Dynamic RAM,动态 RAM)-需要实时刷新来保持数据,价格便宜,一般用于大容量产品;SRAM (Static RAM,静态RAM) -不需要刷新。速度快,面积大。;
  • 数据非易失性存储器 (Non-Volatile Memory):这类存储器读写速度比较慢,但是在掉电后数据不会丢失。因此,在 SoC 设计中可用作大数据的存储或者固件程序的存储。如 NAND/NOR flash,NOR flash 属于是可以随机访问的,是属于非易失性随机访问存储器 (Non-Volatile Random Access Memory, 以下简称 NVRAM);NAND flash 属于顺序访问 (sequential access)。
  • 新出现的存储器 PSRAM(pseudo SRAM),称之为伪静态随机存取器。它具有 SRAM 的接口协议,但是它的内核架构却是 DRAM 架构;相较于传统的 SRAM , PSRAM 可以实现较大的存储容量;
  • 下图是 ESP32 系统架构图,PRO_CPU 和 APP_CPU 面对的是相同的地址空间,可以直接读取嵌入式内存与外围设备地址,而对于外部内存空间,需要透过快取 (Cache) 与内存管理单元 (Memory Management Unit, 以下简称 MMU) 才能进行存取。

    图 01 ESP32 系统架构

    图 02 ESP32 系统地址对应图

    图 03 ESP32 系统地址对应表格

    ESP32 启动流程

    ESP32 从上电到运行 Micropython 中间所经历的启动流程步骤。

    宏观上,启动流程可以分为如下 3 个步骤:

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

    一级引导程序
    ESP32 SoC (System on a Chip, 简称SoC)复位后,PRO CPU 会立即开始运行,执行复位向量代码,而 APP CPU 仍然保持复位状态。在启动过程中,PRO CPU 会执行所有的初始化操作。APP CPU 的复位状态会在应用程序启动代码的 call_start_cpu0 函数中失效。复位向量代码位于 ESP32 芯片掩膜 ROM 处,且不能被修改。二级引导程序二进制镜像会从 flash 的 0x1000 偏移地址处加载。

    二级引导程序
    ESP-IDF (Espressif IoT Development Framework, 以下简称 ESP-IDF) 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux 和 macOS 操作系统。
    下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 supported 代表已支持,preview 代表目前处于预览支持状态。预览支持状态通常有时间限制,而且仅适用于测试版芯片。请确保使用与芯片相匹配的 ESP-IDF 版本。

    表 01. ESP-IDF 各版本中的支持状态

    芯片 v4.1 v4.2 v4.3 v4.4 v5.0 v5.1
    ESP32 supported supported supported supported supported supported
    ESP32-S2   supported supported supported supported supported
    ESP32-C3     supported supported supported supported
    ESP32-S3       supported supported supported
    ESP32-C2         supported supported
    ESP32-C6           supported
    ESP32-H2 beta1/2       preview preview preview

    使用 ESP-IDF 针对 ESP32 芯片所编译出来的二进制镜像,透过烧录软件(esptool.py)烧录到 flash 的 0x1000 偏移地址处,那个二进制镜像就是二级引导程序。二级引导程序的源码可以在 ESP-IDF 的 components/bootloader 目录下找到。ESP-IDF 使用二级引导程序可以增加 flash 分区的灵活性(使用分区表),并且方便实现 flash 加密,安全引导和空中升级(Over The Air, OTA)等功能。

    图 04 ESP-IDF 的二级引导程序源码所在

    当一级引导程序校验并加载完二级引导程序后,它会从二进制镜像的头部找到二级引导程序的入口点,并跳转过去运行。二级引导程序默认从 flash 的 0x8000 偏移地址处(可配置的值)读取分区表。引导程序会寻找工厂分区和 OTA 应用程序分区。如果在分区表中找到了 OTA 应用程序分区,引导程序将查询 otadata 分区以确定应引导哪个分区。

    应用程序
    应用程序启动包含了从应用程序开始执行到 app_main 函数在主任务内部运行前的所有过程。可分为三个阶段:

    1. 端口初始化:端口层的初始化功能会初始化基本的 C 运行环境,并对 SoC 的内部硬件进行了初始配置。

    2. 为应用程序重新配置 CPU 异常。
    3. 初始化内部存储器。
    4. 完成 MMU 高速缓存配置。
    5. 如果配置了 PSRAM,则使能 PSRAM。
    6. 将 CPU 时钟设置为项目配置的频率。
    7. 根据应用程序头部设置重新配置主 SPI flash,这是为了与 ESP-IDF V4.0 之前的引导程序版本兼容。
    8. 如果应用程序被配置为在多个内核上运行,则启动另一个内核 (APP_CPU) 并等待其初始化
    9. 系统初始化:主要的系统初始化任务包括以下

    10. 如果默认的日志级别允许,则记录该应用程序的相关信息。
    11. 初始化堆分配器。
    12. 初始化 newlib 组件的系统调用和时间函数。
    13. 配置断电检测器。
    14. 根据 串行控制台配置 设置 libc stdin、stdout、和 stderr。
    15. 执行与安全有关的检查。
    16. 初始化 SPI flash API 支持。
    17. 调用全局 C++ 构造函数和任何标有 __attribute__((constructor)) 的 C 函数。
    18. 运行主任务:在所有其他组件都初始化后,主任务会被创建,FreeRTOS 调度器开始运行。做完一些初始化任务后,主任务在固件中运行应用程序提供的函数 app_main。

    APP CPU 的内核启动流程
    当运行系统初始化时,PRO CPU 上的代码会给 APP CPU 设置好入口地址,解除其复位状态,然后等待 APP CPU 上运行的代码设置一个全局标志,以表明 APP CPU 已经正常启动。

    参考资料

  • ESP32 Technical Reference Manual,https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
  • Xtensa LX6 Customizable DPU, https://mirrobo.ru/wp-content/uploads/2016/11/Cadence_Tensillica_Xtensa_LX6_ds.pdf
  • ESP32 系列模组,https://www.espressif.com/zh-hans/products/modules/esp32
  • 常用存储器(SRAM、DRAM、NVRAM、PSRAM)简单介绍, https://blog.csdn.net/houxiaoni01/article/details/124152941
  • RTC唤醒是什么意思?如何操作?, https://zhidao.baidu.com/question/1900179422888970220.html
  • 应用程序的启动流程,https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-guides/startup.html
  • Espressif IoT Development Framework, https://github.com/espressif/esp-idf
  • FreeRTOS, https://github.com/FreeRTOS/FreeRTOS
  • 物联沃分享整理
    物联沃-IOTWORD物联网 » 深入了解 ESP32-CAM:系统架构、内存地址和开机流程详解

    发表评论