Использование функции сопоставления символов в микросхеме STM32F7

Я пытаюсь реализовать приемник UART, который работает, находя «\ 0» в потоке данных, ИЛИ когда он получает 256 символов, после чего данные должны обрабатываться прерыванием. Суть в том, чтобы использовать DMA для приема, но если произойдет любое из этих событий, он должен прекратить заполнение текущего буфера и обрабатывать данные. Причина в том, что я использую кодировку COBS для кадрирования своих данных.

Чип STM32F7 имеет что-то под названием «Сопоставление символов» как часть спецификации Modbus, которую я заработал, установив биты в регистре конфигурации, поскольку он не поддерживается библиотеками HAL (stm32cubemx, который удалит этот код при регенерации):

MODIFY_REG(huart->Instance->CR1, UART_CR1_FIELDS, tmpreg | USART_CR1_CMIE);

И в конце обработчик прерывания UART делаю

UART8->ICR |= USART_ISR_CMF;

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

Насколько я понимаю, обработчики прерываний в STM32f7xx_it.c - это фактически первые функции

void DMA1_Stream6_IRQHandler(void) and void UART8_IRQHandler(void)

в моем случае они запускаются, когда прерывания происходят на периферийном устройстве, и из этих функций запускается обработчик (HAL_xxx_IRQHandler()), который проверяет, какое прерывание произошло, и запускает любые пользовательские функции в зависимости от флагов прерывания, например:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle) {
    //process data, this runs when DMA finishes receiving bytes
}

Проблема в том, что неясно, какая из функций прерывания выполняется, когда, например, я использую DMA и получил указанный объем данных через UART. Он запускает прерывание UART или прерывание потока DMA? Как я могу надежно оказаться в одной и той же функции обратного вызова на '\ 0' (uart?) или 256 байтах (dma?) для обработки моих данных без испорченных прерываний?

Объем передаваемых данных определяется функцией прямого доступа к памяти; если вы достигнете этого значения, будет вызван обработчик DMA. Я бы использовал простую глобальную переменную, такую ​​как «CMATCH», и установил бы ее, если установлен флаг CMF (этот флаг вызывает прерывание USART), и использовал бы его для получения надежной последовательности функций.
Вам действительно нужен ДМА? Это довольно быстрый процессор, который, вероятно, не будет беспокоить выполнение прерывания приема на обычных скоростях передачи, поэтому, хотя вы можете понять, как заставить это работать с DMA, делать все это в программном обеспечении может быть концептуально чище и быстрее в разработке и может позволить вам быстрее перейти к следующей реальной проблеме блокировки вашего проекта ... при этом оставив открытой переносимость, чтобы потенциально когда-нибудь сделать перенос со снижением стоимости на более простую цель без возможности сопоставления символов. Если вам нужна аппаратная помощь, сделайте это, но если нет, подумайте о стратегии.
@ChrisStratton Этот микроконтроллер будет работать с двумя последовательными портами со скоростью 6 Мбод, одновременно выполняя другие задачи на ЦП. Так что да, производительность, безусловно, проблема.

Ответы (2)

Регистр DMA CNDTR ведет обратный отсчет до нуля после каждой передачи и показывает, сколько элементов осталось передать. Вы можете использовать его, чтобы проверить, работает ли DMA.

Ваши прерывания UART, если они включены, всегда будут работать вместе с передачами и прерываниями DMA, поэтому прерывания UART должны будут проверять регистр CNDTR DMA, чтобы знать, действительно ли они выполняются.

Вы также можете отключить прерывания изнутри прерываний. Таким образом, ваше прерывание завершения передачи DMA может отключить прерывание приема вашего персонажа (или наоборот), и вы можете снова включить его в другом месте. Помните, что у вас также есть приоритеты прерывания для обработки, когда последняя передача DMA является символом "\0" и одновременно вызывает прерывание завершения передачи DMA и совпадения символов.

В моем коде я использую сопоставление символов, чтобы обнаружить клавишу ввода, чтобы узнать, что пользовательская команда была введена, и проанализировать сообщение в памяти, хранящееся DMA. У меня также есть прерывание приема UART для эхо-символов, которое повторяет символ непосредственно из регистра приема UART. Все они выполняются одновременно с передачей и прерываниями DMA.

Если вы используете посимвольное прерывание UART, нет особого смысла использовать DMA на приемной стороне. Использование только прерывания по совпадению символов вместе с DMA может иметь смысл как рекомендательное условие, но тогда также может иметь смысл просто опрашивать флаг в то время, когда было бы удобно иметь дело с результатом.
Если эхо включено, оно работает, но оно используется в симметричном стеке печатных плат, где конечные платы взаимодействуют с пользователем, а промежуточные платы взаимодействуют друг с другом. Все они работают с одним и тем же программным обеспечением, а эхо не включено для промежуточных плат, что избавляет ЦП от вмешательства до тех пор, пока сообщение не будет завершено. Также происходит некоторая работа с циклическим буфером, которая потребляла бы циклы ЦП, если бы выполнялась в коде прерывания, а не в аппаратном обеспечении DMA. Мне нужно сохранить прерывания для коммутации двигателя.
Мое прерывание по совпадению символов просто добавляет +1 к счетчику, чтобы ЦП знал, сколько сообщений находится в буфере для анализа, поскольку нельзя гарантировать, что сообщение может быть обработано до того, как придет другое (из-за наличия машинного преобразования). -машинные сообщения) до того, как придет другой, поэтому я не могу просто опросить. Это более эффективно, чем каждый раз искать все сообщения до конца буфера для анализа.
@Toor Что ты имеешь в виду, добавляя +1 к счетчику? Что это за регистр, потому что это очень поможет.
Это не регистр. Это просто переменная-счетчик, которую я делаю. Прерывание по совпадению символов получает значение +1 к переменной, а алгоритм синтаксического анализа, работающий в основном цикле программы (по сути, форма опроса), получает значение -1 каждый раз, когда он выполняет синтаксический анализ, пока не достигнет нуля. Таким образом, я могу буферизовать несколько сообщений перед их синтаксическим анализом, и когда я выполняю синтаксический анализ, мне не нужно искать оставшуюся часть буфера, чтобы проверить, осталось ли сообщение. Это удерживает прерывание совпадения символов коротким.
Я думаю, что бит CMF устанавливается, даже когда прерывание отключено, поэтому, если вы просто хотите использовать true/false против количества сообщений для анализа, вы можете просто оставить прерывание совпадения символов отключенным, а также опросить и сбросить флаг CMF. Сбросьте, записав 1 в CMCF.

Я не работал с STM32F7, но вы можете проверить этот репозиторий . Я поделился пошаговым руководством по использованию DMA с совпадением символов и тайм-аутом приемника для микроконтроллеров STM32L4. Как я вижу, регистры для обоих MCU выглядят одинаково.

Ссылка на репозиторий, который вы упомянули, у меня не работает. Я нашел репозиторий UART Utils, но в нем мало что есть. Я был бы очень заинтересован в вашем DMA с приложением для сопоставления символов и тайм-аута приемника. Это в другом репозитории? Спасибо
@Gene Проверьте ChibiOS STM32 HAL, который поддерживает DMA с совпадением символов. Он находится под лицензией Apache. chibios.org/dokuwiki/doku.php?id=chibios:product:hal:start