ESP32 快速入门(十):ESP32 存储系统

1. ESP32 存储系统简介

ESP32 存储系统分为片上存储和片外存储。

其中片上存储包括:

  • 448 KB 的 ROM,用于程序启动和内核功能调用
  • 520 KB 片上 SRAM,用于数据和指令存储
  • RTC 快速存储器,为 8 KB 的 SRAM,可以在 Deep-sleep 模式下 RTC 启动时用于数据存储以及被主 CPU
    访问
  • RTC 慢速存储器,为 8 KB 的 SRAM,可以在 Deep-sleep 模式下被协处理器访问
  • 1 Kbit 的 eFuse,其中 256 bit 为系统专用(MAC 地址和芯片设置) ; 其余 768 bit 保留给用户程序, 这些程
    序包括 flash 加密和芯片 ID
  • 嵌入式 flash ESP32-D2WD带有16Mbit,40MHz的嵌入式flash,与GPIO16,GPIO17,SD_CMD,SD_CLK,SD_DATA_0和SD_DATA_1连接。

ESP32 支持多个外部 QSPI flash 和静态随机存储器 SRAM。外部 flash 可以同时映射到 CPU 指令和只读数据空间。外部 flash 最大可支持 16 MB。外部 SRAM 可映射到 CPU 数据空间。外部 SRAM 最大可支持 8 MB。一次最多可映射 4 MB。虽然 ESP32 能够支持多种类型的 RAM 芯片,但 ESP32_SDK 目前支持 ESP_PSRAM32、ESP_PSRAM64。在芯片启动后,用户程序可以 MAP 外部 SRAM 或 flash 到 CPU 地址空间。

2. 地址映射

ESP32 地址映射如下:
ESP32 快速入门(十):ESP32 存储系统_第1张图片
地址 0x4000_0000 以下的部分属于数据总线的地址范围;
地址 0x4000_0000~0x4FFF_FFFF 部分属于指令总线的地址范围;
地址 0x5000_0000 及以上的部分是数据总线和指令总线共用的地址范围。

ESP32 快速入门(十):ESP32 存储系统_第2张图片

3. SRAM 简析

静态随机存取存储器(Static Random-Access Memory,SRAM)
SRAM 分为 IRAM 和 DRAM:

  • IRAM 储存指令(程序)
  • DRAM 储存数据(堆等)

4. 软件支持的外部 RAM(External RAM)

ESP-IDF 完全支持在应用程序中使用外部 RAM,在启动时初始化外部 RAM,提供了多种方式来配置处理外部 RAM。

Initialize SPI RAM when booting the ESP32,即在 ESP32 boot 时初始化 SPI RAM。

方式1、整合 RAM 到 ESP32 内存映射。这是一个外部 RAM 的基本选项。外部 RAM 指向地址空间 0x3F800000(字节访问)。外部 RAM 的区域大小是 SPI RAM 大小(最大 4 MB)。通过指针指向外部 RAM 来放置数据。

方式2、初始化 RAM 并将其添加到功能分配器。这就允许程序使用 heap_caps_malloc(size,MALLOC_CAP_SPIRAM) 专门分配一块外部 RAM。可以使用该内存,然后使用正常的 free() 来释放。映射到 0x3F800000.

方式3、初始化 RAM,将其添加到功能分配器,并将内存添加到可由 malloc() 返回的 RAM 池中。 这允许任何应用程序使用外部 RAM 而无需重写代码以使用 heap_caps_malloc。这是默认。

方式4、允许在外部 RAM 放置 BSS 段,这段地址空间起始于 0x3F800000,用于 lwip、net80211、libpp 和 bluedroid ESP-IDF 库存储初始化为零的数据( bss 段)。通过在静态声明中应用 EXT_RAM_ATTR 宏(未初始化为 0 值)从内部 BSS 段移到外部 RAM。这有效减少 BSS 段使用的内部静态内存。

5. SPI flash 的操作方法

在 ESP-IDF 中定义已经好了 SPI flash 相关的操作函数了,我们在使用时只要按照要求初始化就可以调用相关 API 操作 flash 了。 使用方法:

void spi_flash_init();//flash 初始化在使用 spi-flash 之前需要调用此函数进行初始化。
size_t spi_flash_get_chip_size();//获取当前 flash 的容量大小。
/*按照扇区擦除 flash,sector 为扇区号*/
esp_err_t spi_flash_erase_sector(size_t sector);
/*按照地址擦除 flash,start_address 擦除的起始地址,size 是擦除大小,地址必须是 4 的倍数*/
esp_err_t spi_flash_erase_range(size_t start_address, size_t size);
/*将数据写入 flash,dest_addr flash 首地址,src 是要写入数据的首地址,size 是 src 数据的大小*/
esp_err_t spi_flash_write(size_t dest_addr, const void *src, size_t size);

/*从 flash 中读出数据,src_addr 是要 flash, dest 是接收数据的首地址,size 是读取的大小*/
esp_err_t spi_flash_read(size_t src_addr, void *dest, size_t size);

如果在调用 flash 期间调用中断,则需要在函数前面加上 IARM_ATTR 属性

#include "esp_attr.h"

void IRAM_ATTR gpio_isr_handler(void* arg)
{
    // ...
}

为常量添加DRAM_ATTR和DRAM_STR 属性

void IRAM_ATTR gpio_isr_handler(void* arg)
{
   const static DRAM_ATTR uint8_t INDEX_DATA[] = { 45, 33, 12, 0 };
   const static char *MSG = DRAM_STR("I am a string stored in RAM");
}

6. 分区表简介

ESP-IDF 工程使用分区表保存 SPI flash 各区信息,包括引导程序、各种应用程序二进制文件、数据及文件系统等。 分区表相关介绍参考 ESP32 分区表。

7. 非易失性存储库(NVS)

非易失性存储 (NVS) 库主要用于在 flash 中存储键值格式的数据。具体请参考 ESP32 非易失性存储库。

8. 参考资料

  • ESP32 存储系统及Flash,进而考虑HTTP升级文件
  • 物联网项目开发快速入门(六):esp32存储简介

你可能感兴趣的:(ESP32)