1. Тема дня

Сегодня разбираем аппаратную защиту памяти:

text
MPU — Memory Protection Unit
привилегированный и непривилегированный код
read-only и execute-never регионы
stack guard
защита конфигурации
изоляция DMA-буферов
FreeRTOS MPU tasks
ESP32 stack watchpoints и memory protection

Главная мысль: MPU не исправляет ошибку, но превращает скрытое повреждение памяти в немедленный и диагностируемый fault рядом с виновной инструкцией.

2. Зачем это нужно в твоих проектах

Для EC25 и AT-парсера MPU помогает поймать выход за буфер немедленно, а не через позднее падение в malloc() или MQTT. Для детектора фаз можно защитить read-only таблицы:

text
GPIO mapping
active level каналов
пороговые значения
phase transition policy
разрешённые комбинации фаз

Для DMA MPU не всегда ограничивает сам DMA, но помогает выделить отдельный DMA pool, сделать его non-cacheable и XN, а также поставить guard/canary между DMA и критичными структурами.

3. Теория

5.3.1 3.1. Что такое MPU

MPU описывает области памяти и назначает им:

text
адрес и размер
privileged/unprivileged access
read-only или read-write
execute-never
cacheable/bufferable/shareable
тип памяти

MPU не создаёт виртуальную память и не заменяет MMU. Он отвечает, можно ли текущему коду читать/писать/исполнять данный физический адрес.

5.3.2 3.2. Типовая карта защиты

ОбластьДоступИсполнение
Flash с кодомread-onlyразрешено
.rodataread-onlyобычно нет необходимости отдельно
SRAMread-writeзапрещено
Stack задачread-writeзапрещено
Heapread-writeзапрещено
DMA poolread-write, non-cacheableзапрещено
Peripheral registersprivileged read-writeзапрещено
Config snapshotread-only после initзапрещено
Неиспользуемая памятьno-accessзапрещено

Главная практическая защита:

text
RAM = XN, execute-never

5.3.3 3.3. Stack overflow: уровни защиты

text
1. Правильный размер stack.
2. Software canary FreeRTOS.
3. Hardware watchpoint конца stack на ESP32.
4. MPU guard region рядом со stack.

MPU guard ловит запись в запрещённую область сразу, до повреждения соседней задачи.

5.3.4 3.4. FreeRTOS MPU port

FreeRTOS MPU-варианты позволяют создавать restricted tasks:

c
xTaskCreateRestricted();
vTaskAllocateMPURegions();

Идея:

text
unprivileged modem logic
→ command queue
→ privileged UART driver

То есть AT-парсер не должен иметь прямой доступ к силовым GPIO, Flash configuration или stack других задач.

5.3.5 3.5. MPU и DMA

MPU ядра не обязательно ограничивает DMA, потому что DMA — отдельный bus master. Поэтому нужны:

text
точная длина transfer
static assertions размеров
DMA descriptors
guard/canary после буфера
sequence numbers
проверка DMA error flags

На STM32H7/F7 полезно выделять non-cacheable DMA pool.

5.3.6 3.6. ESP32 без классического MPU

Для ESP32-WROOM-32U практический набор защиты:

text
FreeRTOS end-of-stack watchpoint
FreeRTOS stack overflow checks
GCC stack protector
heap poisoning
heap integrity checks
hardware watchpoints
core dump
owner-task architecture
bounds-checked parsers

4. Типичные ошибки

text
1. Включить MPU без полного memory map.
2. Разрешить privileged default map и считать всё защищённым.
3. Сделать всю SRAM executable.
4. Защитить stack не с той стороны.
5. Guard находится в том же разрешающем MPU-регионе.
6. Копировать MPU-настройку от другого Cortex-M.
7. Неправильно настроить cacheability DMA-региона.
8. Ожидать, что MPU остановит DMA.
9. Слишком маленький guard.
10. HardFault handler печатает через повреждённый stack.
11. Делать MPU первым шагом вместо исправления ownership.

5. Практическое задание на 30-60 минут

Создай MEMORY_PROTECTION_POLICY.md:

markdown
# Memory protection policy
1. Flash code is read-only and executable.
2. General SRAM is read-write and execute-never.
3. Peripheral memory is privileged and execute-never.
4. DMA pool is execute-never and has explicit cache policy.
5. Validated runtime configuration becomes read-only.
6. Critical task stacks have guard protection where possible.
7. MemManage faults save PC, LR, CFSR and MMFAR.
8. MPU configuration is generated for the exact MCU architecture.

Для STM32: создай защищённую конфигурационную область, переведи её в read-only и попытайся записать в неё в debug-сборке. Для ESP32: включи stack watchpoint/stack protector и controlled stack overflow test в отдельной HIL/debug firmware. CLI-команда:

text
memprot status

Пример:

text
memory protection:
MPU=enabled
regions=6
RAM_XN=yes
config_RO=yes
DMA_region=non-cacheable
stack_guards=3
last_fault=none

6. Что почитать дальше

  • CMSIS-Core MPU API.
  • STM32CubeMX/CubeMX2 MPU configuration для выбранного STM32.
  • FreeRTOS MPU support.
  • ESP-IDF Fatal Errors и Heap Memory Debugging.

Короткий итог

text
owner-task architecture
→ bounded buffers
→ stack sizing
→ canaries/watchpoints
→ XN для RAM
→ read-only config
→ DMA memory policy
→ stack guards
→ restricted RTOS tasks
→ HIL fault injection

Задание

CPU write в защищённый configuration snapshot правильно вызывает fault, но DMA портит соседнюю память. Объясните, почему MPU result не доказывает DMA safety.

Критерии самопроверки: Отделить CPU access control от DMA bounds. Успешный CPU protection test не заменяет проверку DMA ownership/length.

Показать ответ автора

CPU MPU может не ограничивать отдельный DMA bus master. Проверить transfer lengths, destination capacity, descriptors, buffer ownership и guard/canary evidence; использовать DMA-access и cache policy платформы.

Задание

Спроектируйте controlled stack-guard test в debug/HIL build. Какие свойства платформы проверить до намеренного достижения guard?

Критерии самопроверки: Показать положение guard вне разрешённого stack access и независимость diagnostics от уже повреждённого stack.

Показать ответ автора

Проверить stack growth direction, region alignment/size, overlapping MPU permissions, watchpoint/MPU capability платформы и пригодный stack fault handler. Запускать тест только в изолированной debug setup и сохранять fault evidence.