¿Cuál puede ser la causa de una latencia excepcionalmente grande para la interrupción de la recepción de UART?

2

Recibo datos en el UART, usando una atmega de 8 bits, generalmente con alrededor de 5 bytes conectados, luego una pausa larga. El tiempo total para un byte (con bits de inicio + parada, no uso paridad) es de 160 us. Sin embargo, la interrupción de recepción se activa de 60 a 100 segundos después del bit de parada, y casi la mitad del tiempo no se dispara en absoluto. (verificada con alcance)

Hubo algunas interrupciones bastante largas, así que las culpé, pero después de desactivar todas las interrupciones, además de la UART, la situación sigue siendo la misma. Las interrupciones de UART terminan en menos de 10 us (típicamente 7us) todo el tiempo. La intensidad de la señal está bien, es de 5 V, al igual que la tensión de alimentación.

Primero, después de darme cuenta de que se perdieron muchos bytes, pensé que la frecuencia de la señal era la causa, pero la revisé dos veces: la velocidad en baudios es perfecta, la calidad de la señal se ve bien, el error de la velocidad en baudios es cercano a cero. Si ese fuera el problema, obtendría algunas interrupciones perdidas (porque se perdieron algunos bits) pero el resto debería ocurrir en el momento adecuado, ¿no es así? En mi caso, la interrupción llega muy tarde, en todo caso, e incluso cuando llega, a veces contiene basura. La señal en el pin está bien, puedo leerla y evaluarla correctamente en el alcance.

Busqué la latencia típica de la interrupción UART, pero no pude encontrar nada. Sospecho firmemente que una variación salvaje entre 60 y 100 no debería ser normal.

    
pregunta vsz

4 respuestas

1

Supongo que estás usando el mismo proceso de depuración que haría en este caso: una de las primeras instrucciones en la rutina de interrupción enciende un LED, y una de las últimas instrucciones en la rutina de interrupción apaga ese LED.

Luego usaste un osciloscopio de doble trazo con una sonda sujeta al pin apropiado para ver los bytes que ingresan al UART, y la otra sonda sujeta al pin que controla el LED.

Supongo que la rutina de interrupción del controlador UART termina con la instrucción de retorno de la interrupción (en lugar de usar la instrucción de retorno de la subrutina utilizada por las instrucciones normales).

Hay 4 cosas que pueden causar una larga latencia entre el final del último byte de un mensaje y el inicio del controlador UART:

  • Algún byte anterior en el mensaje que activa el controlador UART, y de alguna manera toma mucho tiempo antes de que se vuelvan a habilitar las interrupciones. Algunas personas estructuran sus rutinas de interrupción para que después de que el controlador UART termine de almacenar un byte en el búfer apropiado, verifique un montón de otras cosas antes de ejecutar la instrucción de retorno desde la interrupción: aumenta la fluctuación y la latencia, pero a veces esas personas sí De todos modos, porque mejora el rendimiento.

  • Algunas otras interrupciones tardan mucho tiempo en ejecutarse antes de volver a habilitar las interrupciones mediante la ejecución de la instrucción de retorno de interrupción. (Si puede hacer que todas y cada una de las interrupciones enciendan y apaguen algún otro LED, es bastante fácil ver en el visor si este es el problema o descartarlo).

  • Algunos códigos de no interrupción "temporalmente" apagando interrupciones. (Esto aumenta la inestabilidad y la latencia, pero la gente lo hace de todos modos, porque a menudo es la forma más fácil de evitar la corrupción de datos cuando tanto la interrupción como la tarea de fondo del bucle principal funcionan con la misma pieza de datos). (Si puede hacer que cada bit del código que hace esto encienda y apague algún otro LED, es bastante fácil ver en el o'scope si este es el problema o descartarlo).

  • Instrucciones que tardan mucho tiempo en ejecutarse.

La forma tradicional de averiguar exactamente qué está causando el problema es guardar la versión actual de su código (está usando TortoiseHg o algún otro sistema de control de versiones, ¿verdad?) y luego hackear y recortar deliberadamente una copia temporal de su código, apagando y eliminando completamente el código unas pocas subrutinas a la vez, volver a probar después de cada ronda de eliminaciones, hasta que tengas un pequeño, pero técnicamente "completo" y ejecutable - Programa que presenta el mismo problema.

Con demasiada frecuencia, las personas nos muestran fragmentos de un programa completo: las partes que esas personas piensan son relevantes - y no podemos ayudarlos porque una de las piezas que omitieron está causando el problema.

El proceso de reducir un programa a un caso de prueba pequeño es una habilidad muy útil, porque a menudo mientras se pasa por ese proceso, descubres rápidamente cuál es el problema real.

Una vez que tengas un programa tan pequeño, pero ejecutable, por favor publícalo aquí. Si descubres cuál es el problema durante ese proceso, Díganos eso también, para que el resto de nosotros podamos evitar ese problema.

    
respondido por el davidcary
0

En general, los UART con código no en tiempo real no son confiables. Esto significa que si tiene sub rutinas de reingreso y longitudes de ejecución de código indeterminadas, ¿puede garantizar que el firmware responderá a tiempo a una interrupción no enmascarable? Pero los deshabilitó a todos, ¿así que la duración de IRQ cumple con los requisitos mínimos de tiempo de peor caso?

Si esto se convierte en un problema difícil, es posible que tenga que usar datos de búfer con UARTs profundos de 16 niveles y detección de sobre ejecución y ejecución de búfer y usar una estrategia de sondeo para detectar si los datos se reciben en búfer. Mi primer diseño de UART en 1976 tuvo este problema al principio. Luego pasé al diseño de DMA con una respuesta de sondeo menor que la longitud del búfer con FIFO casi lleno, lo que permitió una interrupción.

    
respondido por el Tony EE rocketscientist
0

Dice que la velocidad en baudios es correcta, pero la calculo como 62500bps (160us / 10 bits = 16us por bit). Esto parece un poco extraño para una conexión en serie, y una velocidad de transmisión incorrecta causaría problemas similares a los que ve. Es decir, el UART puede estar interrumpiendo lo que cree que es el bit de parada, pero que en realidad es parte del siguiente octeto. Naturalmente, los datos también aparecerán dañados :)

Cuando recibe datos, ¿también puede leer los indicadores de error del UART? Eso te dirá por qué a la UART no le gustan los datos.

    
respondido por el dunkers
0

No estoy familiarizado con ATMega, pero algunos controladores utilizan interrupciones activadas por el borde en lugar de sensibles al nivel; en tales controladores, una rutina de servicio de interrupción debe verificar, antes de salir, si todas sus causas asociadas están "satisfechas"; si alguno no lo es, la rutina debe regresar y manejarlos en lugar de salir. Si una rutina de interrupción sale sin haber satisfecho simultáneamente todas sus causas, la interrupción puede terminar deshabilitada a menos que, o hasta que algún otro código, haga que se cumplan todas las causas de la interrupción.

Por ejemplo, si un controlador utiliza la misma rutina de servicio de interrupción para manejar los datos entrantes y salientes de un UART, y la rutina de servicio comienza al manejar los datos entrantes y luego procesar los datos salientes. Si un byte de datos entrantes llega justo antes de que la rutina de servicio de interrupción alimente un byte de datos salientes al UART, es posible que el controlador de interrupción vea un nivel estable en la señal de interrupción del UART. Antes de que se cargue el byte saliente, querría interrumpirlo porque necesitaba datos salientes. En el momento en que se cargó, el UART querría interrumpir porque tenía datos entrantes. Sin embargo, desde el punto de vista del controlador de interrupción, parece que la rutina de servicio de interrupción de UART fue simplemente ineficaz para resolver la condición de interrupción y, por lo tanto, no se manejarán más interrupciones para el UART a menos o hasta que ambos estén listos para transmisión las condiciones listas para recibir se cumplieron simultáneamente.

    
respondido por el supercat

Lea otras preguntas en las etiquetas