Estoy tratando de recibir mensajes USART en un microcontrolador que se origina en una PC que le ordenará ejecutar ciertas pruebas. Estoy usando STM32F4, elegí usar DMA ya que los mensajes en el mismo USART que se originan en el microcontrolador deberían estar a 2000000 bps ya que no pude hacerlo funcionar con una tasa de bits más baja o sin DMA. Estoy usando binario en lugar de ASCII para ambas direcciones.
Lo que he diseñado hasta ahora "funciona" (actualiza casi en tiempo real) siempre que la tasa de mensajes que se envían sea constante, ya que cada mensaje nuevo obliga a que el anterior se elimine del registro DMA. Sin embargo, si se inicia y solo se envía una instrucción/marco USART que resulta ser menor que la cantidad de datos que se recibirán para el mensaje HAL_UART_Receive_DMA()
, el mensaje se atasca hasta que el siguiente mensaje lo expulsa.
Un escenario aún peor sería si USART_take_size
es 100 y hay un solo marco de 10 bytes en el búfer DMA. En este caso, tendría que esperar otros 9 (10 bytes) marcos antes de recibirlos todos a la vez.
Así es como se ve mi devolución de llamada actualmente.
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
// uart handle, global array, numb of bytes to trigger interrupt
HAL_UART_Receive_DMA (huart, raw_serial, USART_take_size);
// function that adds received bytes to the circular buffer
AppendSerial(raw_serial,USART_take_size);
}
Un subproceso extrae bytes del búfer circular, los recorre y, en función de los bytes SOF y EOF, extrae el mensaje dentro del marco.
Mi problema es que los cuadros que llegan tienen una longitud variada, si USART_take_size
se establece en x y llega un cuadro y su longitud es menor que x, tendrá que sentarse en la matriz de búfer en el hilo de extracción hasta que llegue otro cuadro que hace que aparezcan los bytes necesarios para que el analizador obtenga el mensaje incrustado.
Veo tres formas de resolver esto y cada una no parece correcta:
Establecido USART_take_size
en 1, que de alguna manera anula todo el punto de DMA
Tener un tamaño de cuadro fijo y rellenar el contenido con ceros antes de EOF si el contenido es menor que el USART_take_size
. Esto parece descuidado y derrochador. También tendría que activarse en cada cuadro, aunque la tasa general en esa instancia podría ser mucho más alta.
Configure el DMA para activar ISR en un número variable de bytes recibidos, siempre que haya habido una cierta cantidad de inactividad anterior.
No sé mucho sobre DMA, y si bien parece ser una compensación entre cuántos ISR se activan y qué mensaje mínimo puede leer, creo que debería haber una forma de recibir el mensaje después de un período de inactividad. Cualquier otro enfoque de cómo resolver esto sería genial. ¡Gracias!
Tuve un problema similar en uno de mis proyectos. Lo resolví creando un búfer lo suficientemente largo para almacenar el mensaje más largo posible y usando DMA para transferir desde USART. Para detectar el final del mensaje, utilicé la interrupción de detección de línea inactiva que se activa cuando el receptor USART deja de recibir datos.
El STM32 DMA no puede hacer lo que usted quiere por sí solo. Para manejar mensajes de longitud variable, tendría que ser capaz de analizar el mensaje de forma inteligente y determinar la longitud utilizando cualquier esquema de codificación que haya decidido. Esto está mucho más allá de sus capacidades.
Realmente solo puedo pensar en dos opciones para su problema:
Solo procesa cada byte en el USART recibe ISR. El STM32 tiene una sobrecarga de interrupción bastante baja. Si su aplicación puede manejarlo, a veces es mejor ir con lo simple, aunque no sea tan elegante.
Puede configurar fácilmente el DMA para que funcione como un búfer FIFO. El DMA cargará bytes en el búfer y luego configurará una interrupción de temporizador periódica para verificar el búfer en busca de datos y analizar mensajes. Este es un enfoque intermedio en comparación con la opción 1, ya que le permite reducir la sobrecarga de interrupciones a expensas de la latencia. Puede ajustar el período de sondeo del temporizador con respecto al tamaño fifo para equilibrar sus necesidades particulares de procesamiento en tiempo real. También hay trucos que puede hacer con los disparadores de nivel de DMA, aunque la utilidad de esto dependerá del formato de su mensaje.
pjc50
Pedro Smith
mega_creamery
mega_creamery
Pedro Smith
mega_creamery
DKNguyen