Перейти к содержанию

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 memoryRTC 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 CPUULP во время сна, процессор в активном режиме
Что хранят по ESP-IDFкод wake stub, адрес приложения для быстрого старта, флаг factory resetпеременные RTC_DATA_ATTR, программа и данные ULP
Домен питанияESP_PD_DOMAIN_RTC_FAST_MEMESP_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.

Источники

  1. 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 КБ
  2. 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-битными словами
  3. 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
Страница помогла?

Нашли ошибку? ·