USART over DMA on STM32G070
Jan. 7th, 2023 02:51 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Портировал и USART'овский сниппет на G0. Повозился с DMAMUX: там жесть, сколько всяких регистров, но оказалось, что для обычного применения все совершенно просто. Жаль, в интернете вообще 0 примеров. Теперь хоть один будет.
Китайцы на девборде (кстати, схемы ее я так и не нашел, на али все поголовно дают схему с девборды на F407, но там совсем другое подключение — пришлось прозванивать) почему-то вывели на отдельный разъем не USART1, как это обычно делается, а USART3. Я аж три раза прозвонил и с даташитом сверился — так и есть.
Сделал через DMA не только передачу, но и прием (не знаю, почему раньше я этого не делал): о конце строки МК узнает в прерывании character match. А если вдруг возникло прерывание DMA transfer complete, то проверяю: если последний символ - не '\n' (у усартовского прерывания приоритет ниже получается), то выставляю флаг overflow и сбрасываю буфер. При чтении передается флаг, показывающий, не было ли в прошлый раз переполнения буфера (в этом случае все данные вплоть до первой встреченной '\n' выбрасываются). Трижды ловил себя на том, что, скопипастив строчку с настройкой определенного регистра DMA Tx, я не поменял номер на канал для Rx.
Кстати, вот еще на что наткнулся (на радиокоте указали ошибку): почему-то ST'шные разработчики каналы DMA нумеруют с 1, а каналы DMAMUX — с 0. И приходится писать:
Китайцы на девборде (кстати, схемы ее я так и не нашел, на али все поголовно дают схему с девборды на F407, но там совсем другое подключение — пришлось прозванивать) почему-то вывели на отдельный разъем не USART1, как это обычно делается, а USART3. Я аж три раза прозвонил и с даташитом сверился — так и есть.
Сделал через DMA не только передачу, но и прием (не знаю, почему раньше я этого не делал): о конце строки МК узнает в прерывании character match. А если вдруг возникло прерывание DMA transfer complete, то проверяю: если последний символ - не '\n' (у усартовского прерывания приоритет ниже получается), то выставляю флаг overflow и сбрасываю буфер. При чтении передается флаг, показывающий, не было ли в прошлый раз переполнения буфера (в этом случае все данные вплоть до первой встреченной '\n' выбрасываются). Трижды ловил себя на том, что, скопипастив строчку с настройкой определенного регистра DMA Tx, я не поменял номер на канал для Rx.
Кстати, вот еще на что наткнулся (на радиокоте указали ошибку): почему-то ST'шные разработчики каналы DMA нумеруют с 1, а каналы DMAMUX — с 0. И приходится писать:
// set up DMA channels: 2 - Tx, 3 - Rx
// Tx channel: mem++, mem->periph, 8bit, compl.&err. irq
DMA1_Channel2->CCR = DMATXCCR;
DMA1_Channel2->CPAR = (uint32_t) &USART3->TDR; // peripherial address
// Rx channel: mem++, periph->mem, 8bit, compl.&err. irq
DMA1_Channel3->CCR = DMARXCCR;
DMA1_Channel3->CPAR = (uint32_t) &USART3->RDR; // peripherial address
DMA1_Channel3->CNDTR = UARTBUFSZ;
DMA1_Channel3->CMAR = (uint32_t)&rbuf[rbufno];
// set up DMAMUX channels: 55 - USART3_TX, 54 - USART3_RX
// enumeration of DMAMUX starts from 0 (DMA - from 1)!
DMAMUX1_Channel1->CCR = 55;
DMAMUX1_Channel2->CCR = 54;