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 非易失性存儲庫。