Почему DMA1 на STM32H743 не передаёт данные из буфера?
Обновлено Редакция GAW
У большинства STM32 обычная SRAM начинается с адреса 0x2000 0000, и туда компоновщик кладёт все переменные. У STM32H742/743/750 по этому адресу находится DTCM-RAM — память, тесно связанная с ядром, — и если скрипт компоновщика размещает данные там, в DTCM попадёт и буфер DMA. А контроллеры DMA1 и DMA2 до неё не дотягиваются.
Кто куда может обращаться
Таблица 3 RM0433 перечисляет пути от ведущих шин к ведомым. Для буфера DMA важны четыре строки:
| Память | Адрес (RM0433, табл. 7) | Кэшируется по умолчанию | DMA1, DMA2 | BDMA |
|---|---|---|---|---|
| DTCM-RAM | 0x2000 0000 – 0x2001 FFFF | нет, доступ мимо кэша | нет | нет |
| AXI SRAM | 0x2400 0000 – 0x2407 FFFF | да, write-back | да | нет |
| SRAM1, SRAM2, SRAM3 (D2) | 0x3000 0000 – 0x3004 7FFF | да, write-back | да | нет |
| SRAM4 (D3) | 0x3800 0000 | — | да | да |
ST сама советует SRAM1 и SRAM2 как буферы DMA домена D2, SRAM3 — для Ethernet и USB, SRAM4 — для BDMA. SRAM4 — единственная из перечисленных памятей, куда достают и BDMA, и DMA1 с DMA2, так что общий буфер для них кладут туда.
Как перенести буфер
- В скрипте компоновщика описать область, например
RAM_D2 (rw) : ORIGIN = 0x30000000, LENGTH = 128K— это SRAM1 до 0x3001 FFFF, — и секцию.dma_bufferв ней. - Пометить буфер атрибутом:
// DMA1/DMA2 cannot reach DTCM on STM32H743: place the buffer in D2 SRAM
__attribute__((section(".dma_buffer"), aligned(32))) static uint8_t rx_buf[512];
- Перед использованием SRAM1–SRAM3 включить их тактирование — по RM0433 оно выключено после сброса; подробности в ответе «Тактирование SRAM1–SRAM3 на STM32H743».
- Решить вопрос с кэшем: SRAM1–SRAM3 и AXI SRAM кэшируются, в отличие от DTCM. Как выделить некэшируемую область, разобрано в ответе «Некэшируемая область для DMA через MPU».
Выравнивание по 32 байта — размер строки кэша Cortex-M7 — избавит от проблем с соседними переменными при обслуживании кэша. Объёмы памяти разных линеек H7 — на странице STM32H7, устройство потоков DMA — в термине DMA.
Похожие вопросы
Как узнать, куда компоновщик положил буфер?
Посмотреть адрес переменной в отладчике или в map-файле сборки. Адрес 0x2000 xxxx у STM32H743 — это DTCM, 0x2400 xxxx — AXI SRAM, 0x3000 xxxx — SRAM1–SRAM3, 0x3800 xxxx — SRAM4. У других STM32 0x2000 0000 — обычная SRAM, поэтому привычный по F1 или F4 код «молча» перестаёт работать на H7.
Можно ли оставить буфер в DTCM и использовать MDMA?
Да: MDMA — единственный контроллер DMA, у которого по RM0433 есть путь к DTCM через порт AHBS ядра. Но MDMA устроен иначе, чем DMA1 и DMA2, и подключение периферии к нему сложнее; обычно проще перенести буфер.
Нужно ли что-то делать с кэшем, если буфер в AXI SRAM?
Да: AXI SRAM кэшируется, и при включённом D-cache ядро и DMA могут видеть разные данные. Либо обслуживают кэш — clean перед передачей и invalidate перед чтением, — либо выделяют под буферы некэшируемую область через MPU. DTCM мимо кэша работает, поэтому там этой проблемы не было.
Источники
- STMicroelectronics. RM0433 Reference manual STM32H742, STM32H743/753 and STM32H750 Value line, Rev 9 — табл. 7 Memory map and default device memory area attributes: DTCM 0x2000 0000 – 0x2001 FFFF, AXI SRAM 0x2400 0000 – 0x2407 FFFF, SRAM1 0x3000 0000 – 0x3001 FFFF, SRAM2 0x3002 0000 – 0x3003 FFFF, SRAM3 0x3004 0000 – 0x3004 7FFF, тип Normal, кэш write-back, write allocate; табл. 3 Bus-master-to-bus-slave interconnect: к ITCM и DTCM имеют путь только Cortex-M7 (шины ITCM и DTCM) и MDMA через AHBS; к AXI SRAM — ядро по AXIM, MDMA, DMA1, DMA2, DMA2D, LTDC и другие, но не BDMA; к SRAM1–SRAM3 — ядро, DMA1, DMA2 и другие ведущие D2, но не BDMA; к SRAM4 — ядро по AXIM, MDMA, DMA1, DMA2 и BDMA; разд. 2.4: AXI SRAM с адреса 0x2400 0000 доступна всем ведущим, кроме BDMA; SRAM1 — 0x3000 0000, SRAM2 — 0x3002 0000, SRAM3 — 0x3004 0000, их рекомендуется использовать как буферы DMA домена D2, SRAM3 — для Ethernet и USB; SRAM4 — 0x3800 0000, для буферов BDMA домена D3; DTCM-RAM по адресу 0x2000 0000 доступна ядру и MDMA через ведомую шину AHBS
- Arm. Cortex-M7 Processor Technical Reference Manual r1p2 (DDI 0489F), разд. «TCM interfaces», «AHBS interface» — TCM подключены к ядру собственными интерфейсами; внешний DMA получает доступ к TCM только через ведомый порт AHBS ядра; доступ к TCM идёт мимо кэша
Нашли ошибку?
Смотрите также
- TCM (ITCM, DTCM)ОЗУ на прямых интерфейсах ядра Cortex-M7: предсказуемый доступ без кэша
- DMAПрямой доступ к памяти без участия ядра
- STM32H7Cortex-M7 от 280 до 600 МГц, двухъядерные H745/H747 — линейки, память, загрузка и распиновки
- Нужно ли включать тактирование SRAM1–SRAM3 на STM32H743?Да: SRAM1EN, SRAM2EN, SRAM3EN в RCC_AHB2ENR после сброса равны 0
- Как сделать некэшируемую область для DMA через MPU на STM32H7?Регион MPU: TEX = 001, C = 0, B = 0, размер — степень двойки, база выровнена по размеру