Uso de la función de coincidencia de caracteres en un chip STM32F7

Estoy tratando de implementar un receptor UART que funciona al encontrar un '\ 0' en el flujo de datos, O cuando recibe 256 caracteres, momento en el que los datos deben procesarse mediante una interrupción. El objetivo es usar DMA para la recepción, pero si ocurre cualquiera de estos eventos, debería dejar de llenar el búfer actual y procesar los datos. La razón es que estoy usando la codificación COBS para enmarcar mis datos.

El chip STM32F7 tiene algo llamado Coincidencia de caracteres como parte de la especificación Modbus, que conseguí configurar los bits en el registro de configuración, ya que no es compatible con las bibliotecas HAL (stm32cubemx, que eliminaría este código al regenerarse):

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

Y al final del controlador de interrupciones UART lo hago

UART8->ICR |= USART_ISR_CMF;

Para borrar el indicador de interrupción de coincidencia de caracteres para que no vuelva a ejecutarse.

Según tengo entendido, los controladores de interrupción en STM32f7xx_it.c son, de hecho, las primeras funciones

void DMA1_Stream6_IRQHandler(void) and void UART8_IRQHandler(void)

en mi caso, que se ejecutan cuando ocurren interrupciones en un periférico, y desde estas funciones se ejecuta un controlador (HAL_xxx_IRQHandler()) que verifica qué interrupción ocurrió y ejecuta cualquier función definida por el usuario según los indicadores de interrupción, como por ejemplo:

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

El problema es que no está claro cuál de las funciones de interrupción se ejecuta cuando, por ejemplo, estoy usando DMA y he recibido la cantidad especificada de datos a través de UART. ¿Ejecuta la interrupción UART o la interrupción del flujo DMA? ¿Cómo puedo terminar de manera confiable en la misma función de devolución de llamada en '\ 0' (¿uart?) o 256 bytes (¿dma?) para procesar mis datos sin estropear las interrupciones?

La cantidad de datos a transferir es una función DMA; si alcanza ese valor, se invocará el controlador DMA. Usaría un global simple como 'CMATCH' y lo configuraría si el indicador CMF está configurado (este indicador activa la interrupción USART) y lo usaría para obtener una secuencia de función confiable.
¿Realmente necesita DMA? Ese es un procesador bastante rápido que probablemente no tenga problemas al ejecutar una interrupción de recepción a velocidades de transmisión típicas, por lo que, si bien es posible que pueda descubrir cómo hacer que esto funcione con DMA, hacerlo todo en software podría ser conceptualmente más limpio y más rápido de desarrollar y podría permitirle pasar al siguiente problema real de bloqueo de su proyecto más rápidamente... al mismo tiempo que deja abierta la portabilidad para, potencialmente, algún día hacer un puerto de reducción de costos a un objetivo más simple sin la capacidad de coincidencia de caracteres. Si necesita asistencia de hardware, hágalo, pero si no, considere la estrategia.
@ChrisStratton Este microcontrolador ejecutará 2 puertos serie a 6 Mbaud, mientras hace otras cosas en la CPU. Así que sí, el rendimiento es definitivamente un problema.

Respuestas (2)

El registro DMA CNDTR cuenta hasta cero después de cada transferencia y muestra cuántos elementos quedan por transferir. Puede usarlo para verificar si el DMA se está ejecutando o no.

Sus interrupciones de UART, si están habilitadas, siempre se ejecutarán junto con las transferencias e interrupciones de DMA, por lo que las interrupciones de UART tendrán que verificar el registro CNDTR de DMA para saber si realmente se ejecutarán o no.

También puede deshabilitar las interrupciones desde dentro de las interrupciones. Por lo tanto, la interrupción completa de la transferencia DMA puede deshabilitar la interrupción de recepción de su personaje (o viceversa) y puede volver a habilitarla en otro lugar. Recuerde que también tiene prioridades de interrupción para manejar cuando la última transferencia de DMA es el carácter "\0" y activa tanto la transferencia de DMA completa como las interrupciones de coincidencia de caracteres al mismo tiempo.

En mi código, uso la coincidencia de caracteres para detectar la tecla Intro para saber que se ha ingresado un comando de usuario y para analizar el mensaje en la memoria que está almacenando el DMA. También tengo una interrupción de recepción de UART para hacer eco de los caracteres que repite el carácter directamente desde el registro de recepción de UART. Todos estos se ejecutan al mismo tiempo junto con las transferencias e interrupciones de DMA.

Si está ejecutando una interrupción UART por carácter, no tiene mucho sentido usar DMA en el lado de recepción. Usar solo la interrupción de coincidencia de caracteres junto con DMA podría tener sentido como una condición de asesoramiento, pero también podría tener sentido sondear la bandera en momentos en que sería conveniente lidiar con el resultado.
Si el eco está habilitado, lo hace, pero se usa en una pila de PCB simétrica donde las placas finales se comunican con el usuario pero las placas intermedias se comunican entre sí. Todos ejecutan el mismo software y el eco no está habilitado para las placas intermedias, lo que evita que la CPU intervenga hasta que se complete el mensaje. También hay un negocio de búfer circular que consumiría ciclos de CPU si se realiza en código de interrupción en lugar de hardware DMA. Necesito guardar mis interrupciones para la conmutación del motor.
Mi interrupción de coincidencia de caracteres solo agrega un +1 a un contador para que la CPU sepa cuántos mensajes hay en el búfer para analizar, ya que no se puede garantizar que un mensaje se pueda tratar antes de que entre otro (debido a la presencia de máquina-a -machine-messages) antes de que entre otro, así que no puedo simplemente sondear. Es más eficiente que buscar hasta el final del búfer cada vez para analizar más mensajes.
@Toor ¿Qué quiere decir con que agrega un +1 a un contador? Qué registro es este exactamente, porque esto ayudaría inmensamente.
No es un registro. Es solo una variable de contador que hago. La interrupción de coincidencia de caracteres va +1 a la variable, y el algoritmo de análisis que se ejecuta en el bucle del programa principal (básicamente una forma de sondeo) va -1 cada vez que analiza hasta que llega a cero. De esa manera, puedo almacenar varios mensajes en el búfer antes de analizarlos y, cuando los analizo, no tengo que buscar el resto del búfer para comprobar si queda algún mensaje. Mantiene breve la interrupción de coincidencia de caracteres.
Creo que el bit CMF se establece incluso cuando la interrupción está deshabilitada, por lo que si solo desea usar verdadero / falso frente a la cantidad de mensajes para analizar, puede dejar la interrupción de coincidencia de caracteres deshabilitada y sondear y restablecer el indicador CMF. Restablezca escribiendo 1 en CMCF.

No he trabajado con STM32F7, pero puede consultar este repositorio . Compartí una guía paso a paso para usar DMA con coincidencia de caracteres y tiempo de espera del receptor para MCU STM32L4. Como puedo ver, los registros para ambos MCU son similares.

El enlace al repositorio que mencionaste no parece funcionar para mí. Encontré su repositorio UART Utils pero no tiene mucho. Estaría muy interesado en su DMA con coincidencia de caracteres y aplicación de tiempo de espera del receptor. ¿Está en un repositorio diferente? Gracias
@Gene Echa un vistazo a ChibiOS STM32 HAL, que admite DMA con coincidencia de caracteres. Está bajo la licencia Apache. chibios.org/dokuwiki/doku.php?id=chibios:producto:hal:inicio