Кольцевой режим 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 не вернётся к ней.
Ограничения
- При пакетных передачах счётчик NDTR должен быть кратен размеру пакета с учётом размеров данных, иначе RM0090 не гарантирует целостность.
- Режим память — память с кольцевым несовместим.
- Кольцевой режим не защищает от переполнения: если программа не успела обработать половину, DMA её перезапишет.
Для приёма UART неизвестной длины кольцевой режим часто сочетают с прерыванием по паузе в линии — см. статью о кольцевых буферах для UART. Если нужно подменять буфер на лету, используют двойной буфер.
Частые вопросы
Как обрабатывать данные, если DMA пишет в буфер без остановки?
По половинам. RM0090 даёт флаг половины передачи HTIF и флаг конца TCIF. Когда пришло прерывание половины, DMA пишет во вторую половину буфера, а программа обрабатывает первую; по прерыванию конца — наоборот. Обработка половины должна успевать, пока DMA заполняет другую половину.
Чем кольцевой режим DMA отличается от двойного буфера?
В кольцевом режиме один буфер, и программа сама делит его на половины по флагам. В режиме двойного буфера у потока два адреса памяти, и DMA переключается между ними в конце каждой передачи; адрес незанятого буфера можно менять на лету. В STM32F4 двойной буфер автоматически включает и кольцевой режим.
Можно ли использовать кольцевой режим для копирования память — память?
Нет. RM0090 прямо указывает, что режим память — память с кольцевым режимом несовместим. Кольцевой режим предназначен для потоков от периферии или к ней: АЦП, ЦАП, UART, SPI, I²S.
Источники
- 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, ошибка прямого режима
- 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
Нашли ошибку?
Смотрите также
- DMAПрямой доступ к памяти без участия ядра
- Двойной буфер DMAРежим DMA с двумя адресами памяти, которые меняются местами в конце каждой передачи
- Пакетная передача DMA (burst)Несколько обменов DMA подряд по одному запросу без отдачи шины другим ведущим
- Кольцевой буферОчередь фиксированного размера с индексами головы и хвоста, замкнутая в кольцо
- Режим сканирования АЦПРежим АЦП STM32, в котором он сам обходит заданный список каналов
- Кольцевой буфер UARTБуфер SPSC с маской, ISR приёма и передачи на AVR и STM32, ORE и DOR, размер
- DMA STM32Каналы и потоки, запросы периферии, кольцо, двойной буфер, FIFO, флаги, примеры