以下内容来自B站UP主:宸芯IOT的个人空间-宸芯IOT个人主页-哔哩哔哩视频

程序存储结构

1. DRAM(数据 RAM)
  • 定义:DRAM 是指用于存储程序运行时的数据的 RAM 区域。
  • 用途
    • 存储非常量静态数据(.data 段),例如已初始化的全局变量和静态变量。
    • 存储零初始化数据(.bss 段),例如值为 0 的全局变量和静态变量。
  • 存储位置
    • 默认情况下,这些数据由链接器分配到内部 SRAM 中。
    • 开发者可以通过配置,将这些数据存储在外部 RAM 中(如 PSRAM)。
  • 特点
    • 这些数据是在程序启动时被初始化的。
    • .data 段中的数据会被加载到 RAM 中并初始化为指定的值。
    • .bss 段中的数据会被清零。
2. “noinit” DRAM
  • 定义:未初始化的全局变量或静态变量的存储区域。
  • 用途
    • 存储那些不需要在程序启动时被初始化的全局变量。
  • 存储位置
    • 默认情况下分配到内部 SRAM 中。
    • 可以通过配置放入外部 RAM。
  • 特点
    • 这些变量在程序启动时不会被初始化。
    • 它们的值在复位后可能会保留,具体取决于硬件实现。
    • 适合用于需要在复位后保留状态的场景。

####3. IRAM(指令 RAM)

  • 定义:IRAM 是指用于存储可执行代码的内部 RAM 区域。
  • 用途
    • 存储需要快速访问的代码段。
    • 特别是一些中断服务程序(ISR)或对性能要求较高的函数。
  • 存储位置
    • ESP-IDF 默认将内部 SRAM0(SRAM 分为 SRAM0、SRAM1 和 SRAM2)的一部分区域分配为 IRAM。
  • 特点
    • 代码可以直接从 IRAM 执行,无需从 Flash 加载,因此速度更快。
    • 开发者可以使用 IRAM_ATTR 宏显式指定某些函数放到 IRAM 中。
    • 适合用于需要低延迟和高实时性的场景。
4. IROM(代码从 Flash 中运行)
  • 定义:IROM 是指存储在 Flash 中的代码区域。
  • 用途
    • 存储大部分的程序代码。
    • 如果一个函数没有被显式地声明放入 IRAM 或 RTC 存储器中,则它会被默认放置在 Flash 中。
  • 特点
    • 代码存储在 Flash 中,运行时需要从 Flash 加载到 CPU 的缓存中执行。
    • 虽然速度比 IRAM 慢,但 Flash 的容量远大于 RAM,因此适合存储大量的代码。
    • 适合用于对实时性要求不高的普通函数。
5. DROM(数据存储在 Flash 中)
  • 定义:DROM 是指存储在 Flash 中的只读数据区域。
  • 用途
    • 存储程序中的常量数据,例如 const 修饰的变量。
  • 特点
    • 数据存储在 Flash 中,运行时直接从 Flash 访问。
    • 不占用 RAM 空间,节省了宝贵的内部 SRAM。
    • 适合用于存储像字符串、查找表等只读数据。
6. RTC Slow Memory(RTC 慢速存储器)
  • 定义:RTC Slow Memory 是一种低功耗的存储区域,位于 RTC 外设中。
  • 用途
    • 存储需要在深度睡眠模式下保持不变的数据。
  • 特点
    • 数据在深度睡眠模式下不会丢失。
    • 开发者可以使用 RTC_NONINIT_ATTR 属性宏将数据放入 RTC Slow Memory。
    • 适合用于需要在设备唤醒后继续使用的状态信息。
7. RTC FAST Memory(RTC 快速存储器)
  • 定义:RTC FAST Memory 是一种高速的存储区域,也位于 RTC 外设中。
  • 用途
    • 存储需要在深度睡眠模式下保持不变的数据。
    • 存储从深度睡眠模式唤醒后必须运行的代码。
  • 特点
    • 同一区域既可以作为指令存储器也可以作为数据存储器使用。
    • 代码或数据在深度睡眠模式下不会丢失。
    • 适合用于需要在唤醒后立即执行的关键代码(例如唤醒后的初始化代码)。
总结

ESP 的程序存储结构设计是为了平衡性能、功耗和存储容量的需求。以下是每种存储类型的适用场景:

存储类型 用途 特点
DRAM 静态数据和零初始化数据 需要初始化,速度快,适合频繁访问的数据。
“noinit” DRAM 未初始化的全局变量 不会被初始化,可能保留复位前的值。
IRAM 高性能代码 速度快,适合中断服务程序或对实时性要求高的代码。
IROM 普通代码 存储在 Flash 中,容量大,但速度较慢。
DROM 只读数据 存储在 Flash 中,节省 RAM,适合常量数据。
RTC Slow Memory 深度睡眠模式下的数据存储 数据在深度睡眠模式下保持不变,适合保存状态信息。
RTC FAST Memory 深度睡眠模式下的代码和数据存储 高速存储,适合唤醒后立即执行的代码或关键数据。

通过合理利用这些存储类型,开发者可以在性能、功耗和存储容量之间找到最佳平衡点,从而优化 ESP 系统的整体表现。

启动流程

1、一级引导程序 (ROM Bootloader)
  • 位置:固化的在芯片ROM中,无法修改。
  • 功能
    • 当ESP芯片上电或复位时,首先执行的是固化在ROM中的一级引导程序。
    • 它负责检查硬件状态(例如IO0引脚的状态)以决定进入哪种模式。如果检测到IO0为低电平,则进入下载/烧录模式;否则,继续执行二级引导程序。
    • 这个阶段还包括基本的硬件初始化和加载二级引导程序到RAM中运行的任务。
2、二级引导程序 (Bootloader)
  • 位置:通常存储在Flash的0x8000地址处。
  • 功能
    • 负责从Flash中读取分区表(Partition Table),该表定义了应用程序、数据和其他部分在Flash中的位置。
    • 根据分区表的信息,二级引导程序会找到并加载主应用程序映像(通常是位于偏移量0x10000的区域)。
    • 在加载应用程序之前,它还会进行一些必要的配置,如设置Flash的工作频率、校验应用程序的完整性等。
    • 最终,它会跳转到应用程序的入口点开始执行。
3、应用程序
  • 初始化过程
    • 首先,硬件外设和基本C语言运行环境会被初始化。这包括设置CPU寄存器、堆栈指针以及各种系统级别的配置。
    • 接下来,FreeRTOS操作系统会被初始化。FreeRTOS是一个流行的实时操作系统,它允许开发者创建多个任务(线程),并管理这些任务的调度。
    • 最后,调用app_main()函数,这是用户代码的入口点。在这里,开发者可以编写自己的应用逻辑,比如配置Wi-Fi连接、处理传感器数据等。
总结

ESP的启动流程始于一个不可更改的一级引导程序,用于确定是否进入下载模式或者继续执行二级引导程序。接着,二级引导程序加载实际的应用程序,并完成必要的初始化工作。最后,应用程序接管控制权,执行用户编写的app_main()函数来实现特定的功能。这个过程确保了即使在复杂的应用场景下,ESP设备也能可靠地启动并运行所需的服务。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐