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

Кольцевой режим DMA (circular mode)

Чтобы АЦП непрерывно оцифровывал сигнал или UART принимал поток данных без потерь, DMA должен писать в буфер без остановки. Для этого есть кольцевой режим: дойдя до конца буфера, поток сам возвращается в начало. Разбираем, как он работает в STM32F4 и как обрабатывать данные на лету.

Обновлено Редакция GAW

Кольцевой режим DMA (circular mode) — режим потока DMA, в котором после передачи последнего элемента счётчик автоматически перезагружается начальным значением, адрес возвращается в начало буфера, и передача продолжается без участия процессора. Буфер в памяти работает как кольцевой, а поток данных не прерывается.

Как включается

В STM32F4 — битом CIRC в регистре DMA_SxCR, в STM32F1 — тем же битом в DMA_CCRx (RM0008): кольцевой режим и флаги половины и конца передачи есть и у простого DMA. RM0090 называет типичные применения: кольцевые буферы и непрерывные потоки данных, например режим сканирования АЦП. Без кольцевого режима поток после последнего элемента останавливается, и программа должна перезапустить его — за это время можно потерять отсчёты.

Обработка по половинам

Данные идут непрерывно, поэтому программа читает буфер, пока DMA пишет. Для этого у потока есть два флага:

  • HTIF — передана половина данных; DMA заполняет вторую половину, первую можно обрабатывать;
  • TCIF — передача завершена; DMA уже пишет в первую половину, обрабатывают вторую.

Пример: АЦП с частотой 100 кГц, буфер на 1000 отсчётов. Прерывание приходит каждые 500 отсчётов, то есть каждые 5 мс, и на обработку половины у программы есть 5 мс, пока DMA не вернётся к ней.

Ограничения

  1. При пакетных передачах счётчик NDTR должен быть кратен размеру пакета с учётом размеров данных, иначе RM0090 не гарантирует целостность.
  2. Режим память — память с кольцевым несовместим.
  3. Кольцевой режим не защищает от переполнения: если программа не успела обработать половину, DMA её перезапишет.

Для приёма UART неизвестной длины кольцевой режим часто сочетают с прерыванием по паузе в линии — см. статью о кольцевых буферах для UART. Если нужно подменять буфер на лету, используют двойной буфер.

Частые вопросы

Как обрабатывать данные, если DMA пишет в буфер без остановки?

По половинам. RM0090 даёт флаг половины передачи HTIF и флаг конца TCIF. Когда пришло прерывание половины, DMA пишет во вторую половину буфера, а программа обрабатывает первую; по прерыванию конца — наоборот. Обработка половины должна успевать, пока DMA заполняет другую половину.

Чем кольцевой режим DMA отличается от двойного буфера?

В кольцевом режиме один буфер, и программа сама делит его на половины по флагам. В режиме двойного буфера у потока два адреса памяти, и DMA переключается между ними в конце каждой передачи; адрес незанятого буфера можно менять на лету. В STM32F4 двойной буфер автоматически включает и кольцевой режим.

Можно ли использовать кольцевой режим для копирования память — память?

Нет. RM0090 прямо указывает, что режим память — память с кольцевым режимом несовместим. Кольцевой режим предназначен для потоков от периферии или к ней: АЦП, ЦАП, UART, SPI, I²S.

Источники

  1. STMicroelectronics. RM0090 Reference manual: STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439, Rev 21 (June 2024) — разд. 10.3.8: кольцевой режим нужен для кольцевых буферов и непрерывных потоков данных (например, режима сканирования АЦП), включается битом CIRC в DMA_SxCR; число элементов автоматически перезагружается начальным значением, запросы DMA продолжают обслуживаться; при пакетном режиме памяти DMA_SxNDTR должно быть кратно (Mburst beat) · (Msize/Psize), пример: INCR8, MSIZE байт, PSIZE полуслово — кратно 4, иначе поведение и целостность данных не гарантируются; разд. 10.3.9: в режиме двойного буфера кольцевой режим включается автоматически; режим память — память с кольцевым несовместим; разд. 10.3.17: после передачи половины данных устанавливается флаг HTIF и при HTIE генерируется прерывание; 10.2: пять флагов событий — половина передачи, конец передачи, ошибка передачи, ошибка FIFO, ошибка прямого режима
  2. STMicroelectronics. RM0008 Reference manual: STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx and STM32F107xx, Rev 21 (February 2021) — разд. 13.2: поддержка кольцевого буфера, три флага событий — половина передачи, конец передачи, ошибка; разд. 13.3.3: кольцевой режим для кольцевых буферов и непрерывных потоков (например, сканирование АЦП) включается битом CIRC в DMA_CCRx, число данных автоматически перезагружается, запросы продолжают обслуживаться; после передачи половины данных устанавливается HTIF и при HTIE генерируется прерывание, в конце — TCIF

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