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 地址映射如下:
在這裏插入圖片描述
地址 0x4000_0000 以下的部分屬於數據總線的地址範圍;
地址 0x4000_0000~0x4FFF_FFFF 部分屬於指令總線的地址範圍;
地址 0x5000_0000 及以上的部分是數據總線和指令總線共用的地址範圍。

在這裏插入圖片描述

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. 參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章