1. Тема дня
Сегодня разбираем аппаратную защиту памяти:
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 таблицы:
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 описывает области памяти и назначает им:
адрес и размер
privileged/unprivileged access
read-only или read-write
execute-never
cacheable/bufferable/shareable
тип памятиMPU не создаёт виртуальную память и не заменяет MMU. Он отвечает, можно ли текущему коду читать/писать/исполнять данный физический адрес.
5.3.2 3.2. Типовая карта защиты
| Область | Доступ | Исполнение |
|---|---|---|
| Flash с кодом | read-only | разрешено |
| .rodata | read-only | обычно нет необходимости отдельно |
| SRAM | read-write | запрещено |
| Stack задач | read-write | запрещено |
| Heap | read-write | запрещено |
| DMA pool | read-write, non-cacheable | запрещено |
| Peripheral registers | privileged read-write | запрещено |
| Config snapshot | read-only после init | запрещено |
| Неиспользуемая память | no-access | запрещено |
Главная практическая защита:
RAM = XN, execute-never5.3.3 3.3. Stack overflow: уровни защиты
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:
xTaskCreateRestricted();
vTaskAllocateMPURegions();Идея:
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. Поэтому нужны:
точная длина 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 практический набор защиты:
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 parsers4. Типичные ошибки
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:
# 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-команда:
memprot statusПример:
memory protection:
MPU=enabled
regions=6
RAM_XN=yes
config_RO=yes
DMA_region=non-cacheable
stack_guards=3
last_fault=none6. Что почитать дальше
- CMSIS-Core MPU API.
- STM32CubeMX/CubeMX2 MPU configuration для выбранного STM32.
- FreeRTOS MPU support.
- ESP-IDF Fatal Errors и Heap Memory Debugging.
Короткий итог
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.