Программирование ARM: решение проблем, FAQ ESP-IDF: что такое ESP PSRAM? Tue, December 09 2025  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


ESP-IDF: что такое ESP PSRAM? Печать
Добавил(а) microsin   

PSRAM (Pseudo Static Random-Access Memory, или псевдо-статическая оперативная память) — это внешний чип динамической памяти (DRAM) со встроенным контроллером для автообновления, что позволяет использовать её как более простую статическую память (SRAM). Обычно это чип оперативной памяти (внешний или внутренний, расположенный в корпусе микроконтроллера), подключенный через SPI.

Основные характеристики ESP PSRAM:

Характеристика Описание Важные детали
Тип памяти Динамическая (DRAM), но с интерфейсом, похожим на статическую (SRAM). Работает через SPI-интерфейс, медленнее внутренней RAM.
Цель Расширение оперативной памяти ESP32. Используется для хранения данных (массивов, буферов), не для исполнения кода.
Подключение Подключается к ESP32 по SPI, обычно на той же шине, что и flash-память. Требует поддержки в аппаратной платформе (например, модули ESP32-WROVER).
Ёмкость Часто 4 МБ для ESP32. На некоторых платах чип может быть 8 МБ, но одновременно доступно только 4 МБ.  
Управление ESP-IDF интегрирует PSRAM в общую систему памяти. Память можно использовать через стандартные функции (malloc(), heap_caps_malloc()) или специальные (ps_malloc()).

[Как использовать PSRAM в ESP-IDF]

В ESP-IDF работа с PSRAM требует правильной настройки и активации. Основные шаги и функции:

1. Включение в меню конфигурации (idf.py menuconfig):

Component Config → ESP32-specific → Support for external, SPI-connected RAM → [*] Yes

Здесь же можно настроить другие параметры, например, способ доступа к памяти.

2. Проверка наличия и инициализации. После включения конфигурации память инициализируется автоматически при старте. Проверить это можно так:

#include "esp_spiram.h"

if (esp_spiram_is_initialized()) {
printf("PSRAM инициализирована, размер: %u байт\n", esp_spiram_get_size()); }

3. Выделение памяти. PSRAM интегрируется в общую кучу (heap). Самый простой способ — использовать стандартные функции выделения, такие как malloc(), но важно помнить о необходимости включения соответствующей опции в menuconfig (Make RAM allocatable using malloc() as well).

// Пример выделения большого буфера в PSRAM
#define LARGE_BUFFER_SIZE (1024 * 1024 * 2) // 2 МБ

char *big_buffer = (char *)malloc(LARGE_BUFFER_SIZE);
if (big_buffer == NULL) {
printf("Не удалось выделить память!\n"); }

Если этот способ не работает, можно использовать специальные функции, такие как heap_caps_malloc(size, MALLOC_CAP_SPIRAM) или ps_malloc(), которые явно запрашивают память из PSRAM.

4. Работа с PSRAM в коде. Память используется как обычная RAM для данных (например, для буферов изображений, аудио, больших массивов).

// Заполнение буфера данными
memset(big_buffer, 0, LARGE_BUFFER_SIZE);
// Использование буфера sprintf(big_buffer, "Данные в PSRAM");
// Освобождение памяти (обязательно!) free(big_buffer);

[Важные ограничения PSRAM]

При работе с PSRAM необходимо учитывать её ограничения:

- Нет DMA: невозможно использовать для прямого доступа к периферии (например, для SPI, I2S, камеры) без промежуточного копирования.
- Зависимость от кэша: при отключении кэша flash-памяти (например, во время записи) доступ к PSRAM также блокируется. Это частая причина паники `Cache disabled but cached memory region accessed`.
- Стек задач: по умолчанию стек задач не размещается в PSRAM. Для этого требуется специальная настройка и использование xTaskCreateStatic().
- Производительность: скорость доступа ниже, чем у внутренней RAM, особенно при работе с большими (>32 КБ) блоками данных.

[Полезные команды для отладки]

heap_caps_print_heap_info(MALLOC_CAP_SPIRAM) — выводит детальную информацию о куче в PSRAM (свободно, использовано, фрагментация).
heap_caps_get_free_size(MALLOC_CAP_SPIRAM) — возвращает объём свободной памяти в PSRAM.

[Таблица поддержки PSRAM по сериям чипов]

Да, не все чипы Espressif поддерживают подключение внешней PSRAM. Поддержка зависит от архитектуры, целевого назначения и серии чипа.

[Таблица поддержки PSRAM по сериям чипов]

В таблице ниже обобщена информация о поддержке PSRAM для современных серий чипов Espressif:

Серия чипа (Chip Series) Поддержка PSRAM Типичные объёмы Ключевые детали
ESP32 (LX6) ✅ Да До 4 МБ (внешняя) Классический чип с поддержкой до 4 МБ внешней PSRAM через SPI.
ESP32-S2 (LX7) ✅ Да До 2 МБ (встроенная) Поддерживает встроенную (in-package) PSRAM, например, версия ESP32-S2R2.
ESP32-S3 (LX7) ✅ Да 2, 8, 16 МБ Широкая линейка: от 2 МБ (ESP32-S3FH4R2) до 16 МБ (ESP32-S3R16V) встроенной PSRAM.
ESP32-C3 (RISC-V) ❌ Нет - Не поддерживает PSRAM.
ESP32-C6 (RISC-V) ❌ Нет (базовые версии) - Основные версии (ESP32-C6, ESP32-C6FH4) не имеют PSRAM.
ESP32-C61 (RISC-V) ✅ Да 2 или 8 МБ Новейшая серия с поддержкой встроенной PSRAM, например, версии ESP32-C61HR2 и ESP32-C61HR8.
ESP32-P4 (RISC-V) ✅ Да 16 или 32 МБ Высокопроизводительный MCU без Wi-Fi/Bluetooth, но с большой встроенной PSRAM для мультимедиа.
ESP32-H2 (RISC-V) ✅ Да 2 или 4 МБ Ориентирован на IEEE 802.15.4 (Zigbee, Thread) и Bluetooth LE, имеет встроенную PSRAM.

Важное замечание: "встроенная" (in-package) PSRAM, как у ESP32-S3, физически находится в одном корпусе с чипом и не требует дополнительных цепей на плате. "Внешняя" PSRAM, как у классического ESP32 — это отдельная микросхема, которую можно добавить на плату.

[На что обратить внимание при выборе чипа]

Выбор зависит от конкретных задач:

1. Объём памяти: для задач AI, работы с изображениями или большими буферами аудио лучше подойдут ESP32-S3 (до 16 МБ) или ESP32-P4 (до 32 МБ).
2. Экономия и простота: если PSRAM не нужна, чипы серии ESP32-C3 и базовые версии ESP32-C6 — самые бюджетные варианты.
3. Протоколы связи: для задач с Wi-Fi 6 (802.11ax) потребуется ESP32-C6, а для Zigbee/Thread — ESP32-H2 или ESP32-C6.

Если в вашем проекте используется плата WaveShare ESP32-S3-ETH с модулем ESP32-S3R8, то вы уже работаете с чипом, который имеет отличную поддержку PSRAM (в данном случае 8 МБ встроенной PSRAM). Это один из самых популярных и мощных вариантов.

[Лог загрузки программы, вывод информации о куче]

Пример вывода информации в логе:

I (226) heap_init: Initializing. RAM available for dynamic allocation:
I (226) heap_init: At 3FC9F078 len 0004A698 (297 KiB): RAM
I (226) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (226) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (227) heap_init: At 600FE11C len 00001ECC (7 KiB): RTCRAM

Этот лог означает, что система успешно инициализировала менеджер динамической памяти (heap). В таблице перечислены все **незанятые (свободные) области оперативной памяти**, которые будут использоваться для динамического выделения памяти (через `malloc`, `calloc` и т.д.) в вашем приложении.

Расшифровка строк лога. Каждая строка имеет формат: At начальный_адрес len длина (размер в килобайтах): ТИП ПАМЯТИ.

Строка лога Начальный адрес Длина (байты) Размер (килобайт) Тип памяти Комментарий
At 3FC9F078 len 0004A698 0x3FC9F078 304792 (0x4A698) ~297 КБ RAM Основная область кучи. Больше всего места.
At 3FCE9710 len 00005724 0x3FCE9710 22308 (0x5724) ~21 КБ RAM Дополнительная область.
At 3FCF0000 len 00008000 0x3FCF0000 32768 (0x8000) 32 КБ DRAM Память для данных, DATA RAM (D/IRAM).
At 600FE11C len 00001ECC 0x600FE11C 7884 (0x1ECC) ~7 КБ RTCRAM Память RTC (сохраняется в глубоком сне).

Итоговый общий размер кучи: ~357 КБ (297 + 21 + 32 + 7).

Важные выводы для этого примера:

1. PSRAM отсутствует в списке. Это полностью подтверждает, что в вашей конфигурации ESP32-S3 PSRAM отключена или не обнаружена. В логе нет строк с адресами в диапазонах PSRAM (0x3F800000 - 0x3FBFFFFF или 0x40000000 - 0x40FFFFFF).

2. Куча инициализирована корректно. Система видит свободные области памяти и подготовила их для работы. Это означает, что на самом раннем этапе загрузки проблем с памятью не было.

3. Ошибки вида invalid mmu entry указывают на повреждение структур кучи во время выполнения программы. Наиболее вероятные причины:

- Выход за границы массива (Buffer Overflow): запись за пределы выделенного буфера, которая повреждает служебные данные менеджера памяти, расположенные рядом.
- Использование освобождённой памяти (Use-After-Free): обращение к памяти после вызова free().
- Двойное освобождение (Double Free): повторный вызов free() для того же указателя.

 

 

Добавить комментарий


Защитный код
Обновить

Top of Page