Confiabilidad STM32 UART con alta tasa de baudios

Estoy usando STM32F4 (bare metal con biblioteca HAL) como servidor HTTP. No implemento la capa TCP, porque eso lo hace el módulo WiFi232 D2: todo lo que recibo en el uC a través de UART es una cadena con una solicitud HTML pura (y todo lo que envío es una cadena con una respuesta HTML pura). El requisito de la aplicación es enviar una respuesta grande con la página web SPA (casi 300k caracteres) y varias respuestas pequeñas como AJAX (~200 caracteres). Con 57600 bps todo funciona bien, pero la gran respuesta tarda 50 s en cargarse en el cliente, por lo que obviamente tengo que aumentar la velocidad en baudios.

Esa fue la introducción del escenario, ahora la jugada principal, donde comienza el problema: con todo por encima de 57600bps, pierdo caracteres de mensaje en el camino al navegador. Los pierdo al azar, generalmente es una fila de caracteres contiguos; a veces varios, a veces más de cien de ellos. Inicialmente jugué con el bloqueo del transceptor UART. Cuando noté el problema, cambié por DMA y no hizo absolutamente ningún cambio. Probé ambos casos enviando a través de UART a FTDA -> USB -> Termite terminal en lugar del módulo WiFi y vi los mismos síntomas. Dado que cada simulación conduce a las secuelas de la pérdida de datos, llegué al extremo de incluso cruzar STM Tx con Rx y verificar si todo funciona bien en el circuito más corto posible y... por supuesto, funcionó perfectamente :) Así que el uC se excluye de los sospechosos.

Entonces, ¿es posible lograr una transmisión UART confiable? ¿Tiene alguna pista sobre cómo enviar mensajes HTTP por UART a altas velocidades de transmisión? Siento que agoté todas las posibilidades, pero parece poco probable que 115kbps sea demasiado, sin mencionar los Mbps... ¿Quizás me estoy perdiendo algo simple? La aplicación de control de flujo de hardware corrige la transmisión solo un poco, todavía obtengo errores en 115 kbps (aunque con menos frecuencia que sin él).

* Tenga en cuenta que sigo hablando de mensajes HTTP, debido a su naturaleza particular: no puedo implementar ningún algoritmo de control de flujo de software o marcos, porque no tengo poder en el lado del navegador de esta cadena de comunicación.


EDITAR: Algunas observaciones más:

  • Con el control de flujo RST/CST puedo ver un patrón en la transmisión (@230kbps): ~45056 O ~28672 caracteres contiguos se envían correctamente, luego pierdo un par de caracteres, y luego otra vez - ~45056 O ~28672, luego un par suelto de caracteres, etc. Tenga en cuenta que el número de caracteres correctos contiguos es siempre uno de los dos mencionados (+/- un par).
  • Sin control de flujo, obtengo (como se anticipó) el siguiente patrón: transmitir EXACTAMENTE 8191 a 115 kbps o 4095 a 230 kbps de caracteres correctos contiguos y luego perder alrededor de 90 a 115 kbps o 110 a 230 kbps de caracteres. Sin embargo, lo extraño es que no pierdo personajes en ningún otro lugar...

De acuerdo con esas observaciones, prefiero no usar hwfc y simplemente agregar algo de retraso en los puntos conocidos (después de cada 8191 o 4095 caracteres, dependiendo de la velocidad en baudios). Sin embargo, esto es muy complicado , odio esta solución y espero que todavía haya una mejor manera de resolver ese problema.

Consulte la tabla 133 del manual de referencia y pruebe con una tasa de baudios UART que tenga un bajo porcentaje de error. Además, ¿verificó si el módulo UART en el uC está ingresando en alguna condición de error, como un error de saturación o de encuadre?
Un UART requiere que el emisor y el receptor utilicen relojes coincidentes. A velocidades de transmisión más altas, los relojes se vuelven menos precisos porque el error relativo es mayor. ¿Qué fuente de reloj estás usando?
No lo he probado con el F401 que uso actualmente, pero el F051 funcionaba bien con hasta 512 kbps (no he probado más porque era lo suficientemente rápido). Aunque el UART difiere un poco, diría que debería ser totalmente posible lograr altas velocidades de transmisión de manera confiable.
Adán, cuanto mayor sea la tasa de baudios, mayor será el porcentaje, por lo que elegir el error relativo más bajo lucha con mi objetivo inicial de aumentar bps :) En cuanto a ORE y FE, en realidad no suceden en tx, ¿verdad? @CL. Lo estoy probando en la placa Discovery, por lo que son 8 MHz externos con PLL elevándolos a 168. Arsenal UART en el lado de uC funciona bien; como escribí, lo probé cruzando Tx con Rx. Es el módulo WiFi el que pierde caracteres.

Respuestas (1)

Suena como un problema de control de flujo para mí. Un módulo Wifi requiere esto a velocidades de transmisión más altas, porque no puede enviar paquetes a toda velocidad: los búferes internos se llenan. Si su MCU lo admite, debe usar un UART con señales de control de flujo de hardware (generalmente llamadas RTS y CTS).

Mencioné en mi publicación que desafortunadamente no puedo hacer eso (porque se toman los pines en el tablero).
El control de flujo RTS/CTS se puede implementar mediante interrupciones GPIO. Si no tiene ningún pin libre, debe rediseñar su tablero.
Me temo que el rediseño es necesario en este caso, aunque es una maniobra costosa. Esta implementación de GPIO hfc es una idea interesante, aunque no se me ocurrió. ¡Gracias por eso!
Estoy usando el control de flujo incorporado en STM32F4 hw, pero después de muchos experimentos, la confiabilidad aumentó solo un poco (ahora puedo enviar 115200 bps, pero aún así se pierden algunos caracteres cada ~5 mensajes). ¿No debería RTS/CTS virtualmente descartar cualquier pérdida de personajes? Estoy realmente confundido en este momento ... Lo configuré huart3.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS, verifico los indicadores TC y TXE antes de que comience cada transmisión, siempre espero en un bucle cuando HAL_BUSYno obtengo ningún error durante la transmisión y se supone que el módulo receptor funciona incluso con 460800... ¿Debería hacerse algo más?
¿Recordaste configurar el módulo Wifi para usar también el control de flujo RTS/CTS? Esta no suele ser la configuración predeterminada.
Sí, lo hice. Tenga en cuenta que la comunicación funciona para velocidades de transmisión más bajas (creo que no funcionaría si el módulo no estuviera configurado para control de flujo hw).
No, el módulo funcionaría a velocidades de transmisión más bajas y perdería datos cuando la velocidad de datos más alta agotara sus búferes, tal como observó.
¿Está seguro? Pensé que: si no hay HWFC en el lado del destinatario, si el transceptor envió una señal RTS, entonces el destinatario no respondería con CTS, por lo que los datos no se enviarían en absoluto. De todos modos, la configuración es la misma en ambos lados, así que ese no es el caso. También he observado que en bps altos obtengo un error de trama justo con el primer carácter. Para resumir: funciona bien para bps <115k; trabajando, pero perdiendo bytes en 115k y 230k; error de trama inmediatamente con el primer carácter a una velocidad de transmisión de 460k. Esto me parece una inconsistencia en la tasa de baudios o un ruido de señal, pero ¿podría haber alguna otra razón?
Hay una observación potencialmente interesante que hice: cuando no uso control de flujo, recibo datos en una especie de "marcos" de precisamente: (para 115k bps): 8191 caracteres correctos, y luego alrededor de ~90 caracteres perdidos; (para 230k bps): 4095 caracteres correctos y ~110 perdidos [en ambos casos, el primer cuadro siempre es dos veces más corto]. Obviamente, esto tiene que ver con el almacenamiento en búfer. NO pierdo ningún personaje en lugares aleatorios. Sin embargo, con hwfc, no obtengo datos tan precisos, pero también hay un patrón: las cadenas de caracteres contiguas correctas tienen una longitud de ~ 45056 o ~ 28672 ...
Una pregunta muy obvia, pero está utilizando un cristal en su STM32F4 (con condensadores NP0 ) y ha confirmado que las velocidades de transmisión y recepción en baudios están dentro del 1% entre sí, incluso cuando la placa se calienta debido al consumo de WiFi> 50 mA, ¿verdad? También vuelva a comprobar lo que dijo Adam sobre la tabla 133.