4 votos

MSP430: ¿cómo dejar que el ISR del temporizador interrumpa el ISR de recepción en serie?

Estoy trabajando con un MSP430 conectado al PC vía serial. El MSP430 también se comunica con algunas otras placas usando una interfaz serial de bit-bang. Estoy usando el periférico del temporizador para bit bang la serie, y estoy usando la UART para hablar con el PC.

Cuando los comandos llegan desde el PC, la interrupción USCIAB0RX_VECTOR se ejecuta, y mientras se ejecuta, bloquea otras interrupciones. Sin embargo, algunas veces mi rutina de RX en serie tarda un poco, lo que retrasa la interrupción del temporizador y desconecta la interfaz de bit-bang.

En el ISR de la RX en serie, me gustaría permitir que la interrupción del temporizador siga siendo atendida, pero me gustaría evitar que la RX en serie se interrumpa a sí misma (lo que no debería ocurrir en mi aplicación específica, pero me gustaría protegerme contra esto por si acaso)

  • ¿Debería simplemente enmascarar manualmente la interrupción RX serie en la parte superior del ISR serie, y luego habilitar las interrupciones globales?

  • ¿También tengo que desenmascarar la interrupción RX en serie al final?

  • ¿Tengo que borrar manualmente algún indicador de solicitud de interrupción?

  • Después de que el ISR del temporizador regrese, ¿continuará el ISR de la serie, y luego volverá al bucle principal?

  • ¿Hay alguna condición potencial de la carrera que deba tener en cuenta?

  • ¿Hay una solución mejor?

  • ¿Existe algún artículo sobre las interrupciones y las interrupciones? (ya he leído sobre las interrupciones anidadas en la guía del usuario)

3voto

Neil Foley Puntos 1313

No conozco este MCU en concreto, pero la pregunta es bastante genérica.

La respuesta obvia a todos los problemas de este tipo es mantener los ISR lo más reducidos posible. Como mucho, deberían meter los datos en un buffer de anillo, que luego es procesado por el programa principal. (Una MCU con DMA habría sido incluso mejor, pero no creo que tengas DMA en el MSP430).

Si el ISR sigue siendo demasiado lento después de tales optimizaciones, entonces no tienes otra opción que hacer lo que sugieres: habilitar la máscara de interrupción global en la parte superior del ISR de la UART y dejar que la interrupción de mayor prioridad tenga prioridad. Ten en cuenta, sin embargo, que cuando permites que más interrupciones se superpongan a un ISR ya en ejecución, permites una mayor profundidad de pila.

¿También tengo que desenmascarar la interrupción RX en serie al final?

Supongo que hay que hacerlo desde el ISR sin importar la naturaleza de la aplicación. Así es como funcionan la mayoría de MCUs. Y sí, si tocas la máscara de interrupción global, tendrás que borrar la interrupción específica después de que hayas terminado de servirla, es decir, después de haber copiado los datos recibidos en las variables locales.

Después de que el ISR del temporizador regrese, ¿continuará el ISR de la serie, y luego volverá al bucle principal?

Si has cambiado la máscara de interrupción global, entonces sí.

¿Hay alguna condición potencial de la carrera que deba tener en cuenta?

Siempre hay que tener en cuenta esto cuando se comparten datos entre un ISR y otra cosa. No importa si el ISR sólo escribe y el programa principal sólo lee, etc., a menos que puedas garantizar que cada acceso es atómico, lo que normalmente no puedes a menos que escribas el código en ensamblador.

En un lenguaje de alto nivel, es posible que tenga que utilizar alguna variable semáforo. La forma de implementarlo depende de la aplicación. Depende especialmente de si puedes permitirte perder algunos datos de la ISR o si tienes que capturar todos los datos.

¿Hay una solución mejor?

DMA o una MCU multinúcleo.

1 votos

En cuanto a " ¿No creo que tenga DMA en el MSP430? ": 223 de los 421 microcontroladores MSP430 diferentes que aparecen actualmente en TI.com tienen DMA, empezando por el MSP430F5131 en el extremo inferior de la gama de precios (1,20 dólares), que tiene 3 canales DMA.

0 votos

En cuanto a " cada acceso es atómico, lo que normalmente no se puede a menos que se escriba el código en ensamblador " - normalmente esto se haría con el equivalente a cli(); bloque de código atómico ; sti(); en C, por lo tanto para la familia MSP430: __enable_interrupt(); // enable all interrupts --> GIE = 1 (HIGH) __disable_interrupt(); // disable all interrupts --> GIE = 0 (LOW)

2voto

Matt Puntos 150

Mueve tus rutinas de manejo de paquetes RX del vector de interrupción. La función de interrupción debe ser lo más corta posible (en su caso, poner un byte en un buffer para su posterior procesamiento y señalar al programa principal que hay un byte pendiente). Decide las prioridades, ¿qué interfaz es más importante? ¿Periférico o PC? ¿Puede esperar uno de ellos?

0voto

Ogge Puntos 111

Una posible solución es servir a la UART desde la interrupción del temporizador, no dejando que se interrumpa por sí misma. Comprobar si ha llegado un carácter a la UART y almacenarlo en un buffer puede hacerse con unas pocas instrucciones. A continuación se da servicio a la interrupción del bit. Salir de la interrupción del temporizador permite que el código del modo de usuario se ejecute hasta la próxima interrupción del temporizador. Cuando no hay golpeo de bits, puedes elegir habilitar la interrupción de la UART y aumentar el tiempo entre las interrupciones del temporizador para garantizar más tiempo en el modo de usuario.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X