2023-01-07

eddy_em: (Default)
2023-01-07 02:51 pm
Entry tags:

USART over DMA on STM32G070

Портировал и USART'овский сниппет на G0. Повозился с 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;
eddy_em: (Default)
2023-01-07 08:39 pm
Entry tags:

I2C on STM32G070

Добавил и I2C. В простейшем случае (без DMA) все решилось элементарным переносом с F0. Дольше провозился, разгребая все по разным файлам и переделывая proto.c.
Проверял на недавно купленном датчике SHT30 (у старых я всех подтяжки поотпаивал, чтобы к "апельсинке" присоединить, а новых аж 4 разных, но у остальных трех нужно гребенки паять — лень). Правда, у SHT30 зачем-то регистры 16-битные сделали (хоть там тех регистров и на 4 бита за глаза), так что пришлось еще добавить возможность чтения регистров с 16-битными адресами. Статусные регистры показывает, грелку включает/выключает, в однократном или непрерывном режиме температуру и влажность показывает. Температура плавает в районе ±0.05℃, влажность — в районе ±2%. По-хорошему, конечно, надо будет всю эту кучу датчиков потом в эдакий термостат засунуть, да посмотреть по калиброванному термометру, насколько врут. Еще бы чем-нибудь их показания влажности измерить… Ах, да: врет он по температуре безобразно: кажет аж 26℃ в квартире (все китайские домашние термометры 24 показывают). Если менять параметр "repeatability" (точность, видать), вообще ничего не меняется. Хотя точность обещали ±0.3℃, ну, обещанного три года ждут (а уж с китайскими датчиками, похоже, все очень плохо).
Завтра в 8 утра на работу вставать, надо долго не засиживаться, но чуть-чуть хочется еще потыкать палочкой возможность запуска I2C через DMA.