esp32idf 关于SPIRAM的使用
一、ESP32资源介绍
数据手册
从这里可以看到不同型号对应的FLASH、和SPIRAM的大小,我这里使用的是ESP32-S3-WROOM-1-N16R8 也就是FLASH 16M SPIRAM 8M 。
二、SPIRAM使用menuconfig进行配置
1、打开menuconfig
注意选择Mode (QUAD/OCT) of SPI RAM chip in use
这里面选的是 Octal Mode
这么选择以后保存配置,就自动初始化了,接下来我们做个例子查看一下对不对。
至于怎么调用spiram,看例子
三、代码示例
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "esp_psram.h"
#include "esp_heap_caps.h"
#define TAG "AUDIO_QUEUE"
#define QUEUE_MAX_ITEMS 100// 音频数据块结构体
typedef struct
{uint8_t data[1024];size_t len;uint32_t timestamp; // 添加时间戳用于处理
} audio_wav_chunk_t;// 队列相关变量
QueueHandle_t audio_wav_queue = NULL;
StaticQueue_t queue_struct;
uint8_t *queue_buffer = NULL;
#include "esp_timer.h"#include <math.h>
// 生成正弦波音频数据
void generate_sine_wave(uint8_t *buffer, size_t len, uint32_t counter)
{float frequency = 1.0f + (counter % 10) * 0.1f; // 频率变化float amplitude = 127.0f;float phase = counter * 0.1f;for (int i = 0; i < len; i++){// 生成正弦波,幅度0-255,频率和相位变化float value = sinf(2.0f * M_PI * frequency * i / len + phase);buffer[i] = (uint8_t)(amplitude * value + amplitude + 0.5f);}
}
// 生产者任务:生成并发送音频数据到队列
void producer_task(void *pvParameters)
{audio_wav_chunk_t chunk;static uint32_t counter = 0;while (1){// 生成模拟音频数据(这里用递增数字填充)generate_sine_wave(chunk.data, sizeof(chunk.data), counter);chunk.len = sizeof(chunk.data);chunk.timestamp = esp_timer_get_time(); // 获取当前时间戳// 发送数据到队列BaseType_t status = xQueueSendToBack(audio_wav_queue, &chunk, portMAX_DELAY);if (status == pdPASS){ESP_LOGI(TAG, "Producer: Sent chunk #%ld, len=%d, time=%ldus",counter, chunk.len, chunk.timestamp);}else{ESP_LOGE(TAG, "Producer: Failed to send data to queue");}counter++;vTaskDelay(pdMS_TO_TICKS(10)); // 每100ms生成一个数据块}
}// 消费者任务:从队列读取并处理音频数据
void consumer_task(void *pvParameters)
{audio_wav_chunk_t received_chunk;uint32_t processed_count = 0;while (1){// 从队列接收数据BaseType_t status = xQueueReceive(audio_wav_queue, &received_chunk, portMAX_DELAY);if (status == pdPASS){// 处理音频数据(这里只是简单计算平均值作为示例)uint32_t sum = 0;for (int i = 0; i < received_chunk.len; i++){sum += received_chunk.data[i];}float average = (float)sum / received_chunk.len;uint32_t current_time = esp_timer_get_time();uint32_t latency = current_time - received_chunk.timestamp;ESP_LOGI(TAG, "Consumer: Processed chunk #%ld, len=%d, avg=%.2f, latency=%ldus",processed_count, received_chunk.len, average, latency);processed_count++;}else{ESP_LOGE(TAG, "Consumer: Failed to receive data from queue");}}
}void app_main(void)
{// // 初始化PSRAM// if (esp_psram_init() != ESP_OK) {// ESP_LOGE(TAG, "PSRAM initialization failed");// return;// }// 打印内存信息ESP_LOGI(TAG, "Internal RAM free: %ld k bytes", esp_get_free_heap_size() / 1024);ESP_LOGI(TAG, "PSRAM free: %d k bytes", esp_psram_get_size() / 1024);// 在PSRAM中分配队列存储区queue_buffer = (uint8_t *)heap_caps_malloc(sizeof(audio_wav_chunk_t) * QUEUE_MAX_ITEMS,MALLOC_CAP_SPIRAM);if (queue_buffer == NULL){ESP_LOGE(TAG, "Failed to allocate queue storage in PSRAM");return;}// 创建静态队列audio_wav_queue = xQueueCreateStatic(QUEUE_MAX_ITEMS,sizeof(audio_wav_chunk_t),queue_buffer,&queue_struct);if (audio_wav_queue == NULL){ESP_LOGE(TAG, "Failed to create queue");heap_caps_free(queue_buffer);return;}ESP_LOGI(TAG, "Queue created successfully in PSRAM");// // 创建生产者和消费者任务// xTaskCreate(// producer_task,// "producer",// 4096,// NULL,// 5,// NULL);// xTaskCreate(// consumer_task,// "consumer",// 4096,// NULL,// 5,// NULL);// 主任务可以处理其他事务或进入低功耗模式while (1){vTaskDelay(pdMS_TO_TICKS(1000));}
}
四、打印调试信息
I (27) boot: ESP-IDF v5.4.1-dirty 2nd stage bootloader
I (27) boot: compile time Jun 10 2025 09:42:51
I (27) boot: Multicore bootloader
I (28) boot: chip revision: v0.2
I (30) boot: efuse block revision: v1.3
I (34) boot.esp32s3: Boot SPI Speed : 80MHz
I (38) boot.esp32s3: SPI Mode : DIO
I (42) boot.esp32s3: SPI Flash Size : 16MB
I (45) boot: Enabling RNG early entropy source...
I (50) boot: Partition Table:
I (52) boot: ## Label Usage Type ST Offset Length
I (59) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (65) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (72) boot: 2 factory factory app 00 00 00010000 00100000
I (78) boot: End of partition table
I (82) esp_image: segment 0: paddr=00010020 vaddr=3c020020 size=0a788h ( 42888) map
I (97) esp_image: segment 1: paddr=0001a7b0 vaddr=3fc92d00 size=02cdch ( 11484) load
I (99) esp_image: segment 2: paddr=0001d494 vaddr=40374000 size=02b84h ( 11140) load
I (106) esp_image: segment 3: paddr=00020020 vaddr=42000020 size=18124h ( 98596) map
I (129) esp_image: segment 4: paddr=0003814c vaddr=40376b84 size=0c0c8h ( 49352) load
I (140) esp_image: segment 5: paddr=0004421c vaddr=600fe100 size=0001ch ( 28) load
I (146) boot: Loaded app from partition at offset 0x10000
I (146) boot: Disabling RNG early entropy source...
I (158) octal_psram: vendor id : 0x0d (AP)
I (158) octal_psram: dev id : 0x02 (generation 3)
I (158) octal_psram: density : 0x03 (64 Mbit)
I (160) octal_psram: good-die : 0x01 (Pass)
I (164) octal_psram: Latency : 0x01 (Fixed)
I (169) octal_psram: VCC : 0x01 (3V)
I (173) octal_psram: SRF : 0x01 (Fast Refresh)
I (178) octal_psram: BurstType : 0x01 (Hybrid Wrap)
I (182) octal_psram: BurstLen : 0x01 (32 Byte)
I (187) octal_psram: Readlatency : 0x02 (10 cycles@Fixed)
I (192) octal_psram: DriveStrength: 0x00 (1/1)
I (196) esp_psram: Found 8MB PSRAM device
I (200) esp_psram: Speed: 40MHz
I (203) cpu_start: Multicore app
I (937) esp_psram: SPI SRAM memory test OK
I (946) cpu_start: Pro cpu start user code
I (946) cpu_start: cpu freq: 160000000 Hz
I (946) app_init: Application information:
I (946) app_init: Project name: hello_world
I (950) app_init: App version: 1
I (954) app_init: Compile time: Jun 10 2025 12:01:27
I (959) app_init: ELF file SHA256: 336c8e012...
I (963) app_init: ESP-IDF: v5.4.1-dirty
I (967) efuse_init: Min chip rev: v0.0
I (971) efuse_init: Max chip rev: v0.99
I (975) efuse_init: Chip rev: v0.2
I (979) heap_init: Initializing. RAM available for dynamic allocation:
I (985) heap_init: At 3FC96338 len 000533D8 (332 KiB): RAM
I (991) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (996) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (1001) heap_init: At 600FE11C len 00001ECC (7 KiB): RTCRAM
I (1006) esp_psram: Adding pool of 8192K of PSRAM memory to heap allocator
I (1014) spi_flash: detected chip: gd
I (1016) spi_flash: flash io: dio
I (1019) sleep_gpio: Configure to isolate all GPIO pins in sleep state
I (1026) sleep_gpio: Enable automatic switching of GPIO sleep configuration
I (1033) main_task: Started on CPU0
I (1063) esp_psram: Reserving pool of 32K of internal memory for DMA/internal allocations
I (1063) main_task: Calling app_main()
I (1063) AUDIO_QUEUE: Internal RAM free: 8535 k bytes
I (1073) AUDIO_QUEUE: PSRAM free: 8192 k bytes
I (1073) AUDIO_QUEUE: Queue created successfully in PSRAM
五、总结
有了外部SPIRAM 我们可用的资源就很多了,在需要大RAM的场合可以使用这个。