RTC-память ESP32 (RTC FAST и RTC SLOW memory)
После глубокого сна ESP32 стартует заново, и обычная оперативная память к этому моменту уже ничего не помнит. Единственное, что переживает сон внутри чипа, — два маленьких блока RTC-памяти по 8 КБ, и ESP-IDF даёт для них отдельные атрибуты.
Обновлено Редакция GAW
RTC-память (RTC memory) — два блока SRAM в домене питания RTC ESP32, которые можно оставить под напряжением в глубоком сне, когда основная оперативная память и процессоры выключены. По даташиту ESP32 v5.3 их два по 8 КБ: RTC FAST memory, к которой главный процессор обращается при старте после сна, и RTC SLOW memory, с которой работает сопроцессор ULP. Всё, что должно пережить сон внутри чипа — счётчик пробуждений, последнее измерение, код быстрого пробуждения, — размещают именно здесь.
Две области
| RTC FAST memory | RTC SLOW memory | |
|---|---|---|
| Размер (даташит, разд. 4.1.2) | 8 КБ | 8 КБ |
| Адреса (табл. 4-1) | 0x3FF8_0000–0x3FF8_1FFF (данные), 0x400C_0000–0x400C_1FFF (команды) | 0x5000_0000–0x5000_1FFF |
| Кто обращается | главный процессор при RTC Boot после Deep-sleep; в двухъядерном режиме — только PRO CPU | ULP во время сна, процессор в активном режиме |
| Что хранят по ESP-IDF | код wake stub, адрес приложения для быстрого старта, флаг factory reset | переменные RTC_DATA_ATTR, программа и данные ULP |
| Домен питания | ESP_PD_DOMAIN_RTC_FAST_MEM | ESP_PD_DOMAIN_RTC_SLOW_MEM |
RTC FAST отображена дважды — как память данных и как память команд, — поэтому из неё можно выполнять код. ULP адресует RTC SLOW 32-битными словами.
Атрибуты ESP-IDF
RTC_DATA_ATTR,RTC_RODATA_ATTR— записываемые и только для чтения данные. По умолчанию попадают в RTC SLOW; опцияCONFIG_ESP32_RTCDATA_IN_FAST_MEMпереносит их в RTC FAST, чтобы освободить медленную память под ULP, но работает только в одноядерной сборке.RTC_FAST_ATTR,RTC_SLOW_ATTR— принудительное размещение в конкретной области.RTC_NOINIT_ATTR— данные в RTC SLOW, которые по ESP-IDF сохраняют значение после пробуждения из глубокого сна.RTC_IRAM_ATTR— код в RTC FAST для wake stub.COREDUMP_RTC_ATTR,COREDUMP_RTC_FAST_ATTR— переменная попадёт в core dump.
Данные в RTC-памяти инициализируются при каждом старте чипа, кроме пробуждения из глубокого сна: тогда сохраняются значения, записанные до сна. После пробуждения содержимое RTC FAST проверяется по CRC, и только затем выполняется wake stub.
Питание и сон
esp_deep_sleep_start() по умолчанию выключает домены RTC, которые не нужны источникам пробуждения. Исключения: если в программе есть переменные RTC_DATA_ATTR, домен RTC SLOW остаётся включённым; если включён ULP, его программа выполняется из RTC SLOW; в ревизии 0 ESP32 домен RTC FAST включён в глубоком сне всегда, чтобы мог работать wake stub. Переопределить это можно функцией esp_sleep_pd_config(). В light-sleep вопрос не стоит — там сохраняется вся оперативная память. Ещё одно требование ESP-IDF: у задачи, которая вызывает сон, стек должен лежать во внутренней памяти — в DRAM или RTC FAST, а не в PSRAM.
Как куча
В одноядерной сборке свободный остаток RTC FAST добавляется в кучу (CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP), и его можно запросить флагом MALLOC_CAP_RTCRAM. Эта память чуть медленнее DRAM и недоступна DMA. Ещё RTC FAST использует загрузчик второй ступени: при CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP он хранит там адрес приложения и после пробуждения запускает его без проверки образа. Остальные характеристики чипа — на странице ESP32.
Частые вопросы
Чем RTC FAST отличается от RTC SLOW?
По даташиту ESP32 v5.3 обе области по 8 КБ, но у них разные потребители. RTC FAST (0x3FF80000 и 0x400C0000) доступна главному процессору сразу после пробуждения — в ней по ESP-IDF лежит код wake stub, поэтому она отображена и как память команд, и как память данных. RTC SLOW (0x50000000) доступна сопроцессору ULP: там хранится его программа, и туда же по умолчанию попадают переменные RTC_DATA_ATTR. В двухъядерном режиме RTC FAST доступна только PRO CPU.
Как сохранить переменную через глубокий сон?
Объявить её с атрибутом RTC_DATA_ATTR (или RTC_RODATA_ATTR для констант). По ESP-IDF данные в RTC-памяти инициализируются при каждом старте, кроме пробуждения из глубокого сна — тогда сохраняется значение, записанное до сна. Если в программе есть такие переменные, ESP-IDF по умолчанию оставляет домен RTC SLOW под питанием. Для данных, которые не должны сбрасываться при старте, есть RTC_NOINIT_ATTR — по ESP-IDF такие значения тоже сохраняются после пробуждения из глубокого сна.
Можно ли использовать RTC-память как обычную кучу?
Частично. В одноядерном режиме (CONFIG_FREERTOS_UNICORE) ESP-IDF добавляет свободный остаток RTC FAST в кучу, если не выключена опция CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP; выделить её явно можно флагом MALLOC_CAP_RTCRAM. Память чуть медленнее DRAM и не годится для DMA. В двухъядерном режиме так нельзя, потому что к RTC FAST имеет доступ только PRO CPU.
Источники
- Espressif. ESP32 Series Datasheet, Version 5.3 — разд. 4.1.2 Internal Memory: 8 КБ SRAM в домене RTC — RTC FAST Memory, для хранения данных, доступна главному процессору при RTC Boot после Deep-sleep; 8 КБ SRAM — RTC SLOW Memory, доступна сопроцессору ULP во время Deep-sleep; табл. 4-1 Memory and Peripheral Mapping: RTC FAST Memory 0x3FF8_0000–0x3FF8_1FFF и 0x400C_0000–0x400C_1FFF, 8 КБ; RTC SLOW Memory 0x5000_0000–0x5000_1FFF, 8 КБ
- Espressif. ESP-IDF Programming Guide v6.1, ESP32: Memory Types; Deep-sleep Wake Stubs; Sleep Modes; ESP32 ULP Coprocessor Instruction Set — Memory Types: RTC Slow Memory — глобальные и статические переменные кода, работающего из RTC-памяти, переменные для глубокого сна, код и данные ULP; RTC_NOINIT_ATTR — значения сохраняются после пробуждения из глубокого сна; RTC FAST Memory — одна область доступна как память команд и данных, код после пробуждения должен быть в RTC-памяти; в одноядерном режиме остаток RTC FAST добавляется в кучу (CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP), память чуть медленнее DRAM и без DMA; в двухъядерном режиме RTC FAST доступна только PRO CPU; Deep-sleep Wake Stubs: после пробуждения RTC fast memory проверяется по CRC; данные в RTC-памяти инициализируются при каждом старте, кроме пробуждения из глубокого сна; RTC_DATA_ATTR и RTC_RODATA_ATTR — записываемые и только для чтения данные; CONFIG_ESP32_RTCDATA_IN_FAST_MEM переносит их в RTC FAST, по умолчанию они в RTC SLOW; RTC_FAST_ATTR и RTC_SLOW_ATTR — принудительное размещение, RTC_FAST_ATTR только для PRO_CPU; Sleep Modes: ULP выполняет программу из RTC SLOW memory; если переменные размещены в RTC SLOW (RTC_DATA_ATTR), домен остаётся под питанием по умолчанию, переопределяется esp_sleep_pd_config(); в ревизии 0 ESP32 RTC FAST всегда включена в Deep-sleep; домены ESP_PD_DOMAIN_RTC_SLOW_MEM и ESP_PD_DOMAIN_RTC_FAST_MEM; задача, вызывающая сон, должна иметь стек во внутренней памяти — DRAM или RTC fast memory; ULP Instruction Set: ULP адресует 8 КБ RTC_SLOW_MEM 32-битными словами
- Espressif. ESP-IDF Programming Guide v6.1, ESP32: Bootloader; Core Dump; Heap Memory Allocation — Bootloader: при CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP адрес приложения хранится в RTC FAST memory, flag factory reset также занимает RTC FAST; Core Dump: COREDUMP_RTC_ATTR и COREDUMP_RTC_FAST_ATTR включают переменную в дамп; Heap: MALLOC_CAP_RTCRAM — выделение в RTC fast memory
Нашли ошибку? ·
Смотрите также
- Глубокий сон ESP32Режимы сна, токи, пробуждение по таймеру и выводам, RTC-память, расчёт батареи
- Wake stub (глубокий сон ESP32)Код из RTC FAST memory, который выполняется до загрузчика после deep sleep
- ULP-сопроцессорМаломощный сопроцессор ESP32 для работы в глубоком сне
- Light-sleep ESP32Лёгкий сон ESP32: процессор остановлен, пробуждение без перезагрузки
- Загрузчик второй ступени ESP-IDFbootloader.bin по адресу 0x1000: таблица разделов, выбор приложения, флеш, secure boot
- Core dump ESP-IDFСнимок стеков и регистров задач при панике: раздел coredump, формат ELF, разбор idf.py coredump-info
- PSRAMВнешняя оперативная память на шине SPI: размеры, режимы, выводы
- ESP32ESP32, S2, S3, C2, C3, C5, C6, H2, P4: ядра, радио, USB, GPIO — сравнение и выбор