MSP430 cómo hacer ISR configurables en un módulo (Code composer studio C)

Tengo una pregunta que creo que la respuesta es bastante simple. Pero no he podido encontrar una respuesta directa a.

Si tengo esta rutina de servicio en algún módulo foo.c

#pragma vector = SOME_VECTOR
interrupt void fooISR(){
    dosomething;
    IFG = 0;
}

si tengo en mi main.

#include "foo.h"

Entonces parece que fooISR()sí se carga en SOME_VECTOR y el ISR se activará cada vez que se establezca el IFG correspondiente.

Quería preguntar si esta es la forma correcta de escribir módulos que utilizan interrupciones. Debido a que con este enfoque, fooISR()estará en SOME_VECTOR cada vez que incluya foo.h, esto realmente no permite mucha configuración para la persona que trabaja en main.

Por ejemplo, si main.cquisiera acceder a alguna funcionalidad de foo.c pero quisiera escribir un ISR separado para ALGUNOS_VECTORES, no tendría suerte con este método, ¿verdad?

Respuestas (2)

La preocupación que expresas en el último párrafo es correcta. No parece ser una buena idea agrupar un ISR con otra funcionalidad que quizás desee reutilizar por separado del ISR.

Yo suelo hacer una de las 3 cosas:

  • Coloque los ISR y main en el mismo archivo que main(). Los ISR son cortos, por lo que no abarrotan main.cdemasiado.
  • Ponga todos los ISR juntos en un módulo separado. No hay otra funcionalidad en ese módulo. No hay intención de hacer que este módulo ISR sea reutilizable.
  • Coloque cada ISR en su propio módulo. No hay otra funcionalidad en esos módulos.

Podría poner el ISR dentro de un #ifdefbloque, si tiene sentido en su situación particular.

Todos los enfoques son muy razonables. También depende de qué MCU esté utilizando. Para MSP430, el primer enfoque parece ser el mejor, ya que generalmente tiene ISR cortos, pero, por ejemplo, para C2000, podría ser mejor utilizar el tercer enfoque, ya que normalmente tiene la mayor parte de la funcionalidad de control en las interrupciones ADC/PWM/CAP.
La forma normal es agrupar el ISR con la funcionalidad relacionada que desea usar junto con el ISR.
Entonces, los ISR generalmente residen en main.c? pero con algo de #ifdef podríamos hacerlo un poco más configurable? Sí, eso tiene mucho sentido gracias hombre que ayudó.

En primer lugar, no tiene sentido discutir estas cosas a menos que tenga algún tipo de diseño de programa. Si tiene un programa simplista de menos de 1k LOC más o menos, entonces es posible que no necesite ningún diseño, podría ser suficiente para piratear sin rumbo fijo.

Para programas profesionales más grandes, necesitará el diseño del programa:

Debe colocar los ISR en el mismo archivo que el resto del controlador que controla esa pieza de hardware en particular, porque un ISR es parte del controlador de hardware . No deberían estar en main(), no deberían estar en algún archivo no relacionado.

No deberían estar en algún archivo "aquí están todos mis ISR" a menos que se vea obligado a agruparlos debido a restricciones de hardware o herramientas. Sin embargo, es posible que deba mantener la tabla de vectores en un archivo propio, a menos que el enlazador controle su ubicación.

main() no debería jugar con los ISR. Tendrá una capa de abstracción encima de los controladores y main llamará a la capa de abstracción. Esto significa que no tendrá un acoplamiento estrecho entre el algoritmo y el hardware, y también que puede reemplazar fácilmente el controlador sin tener que volver a escribir todo el programa desde cero.

Tienes 100% razón en que depende del diseño del programa. Desacoplar completamente los ISR de main.c también puede tener algunos inconvenientes. Puede tener alrededor de 20 controladores ISR dentro de su main.c con una cantidad de código de menos de 1k líneas, con solo establecedores de banderas + algunos ADC al final del manejo de resultados de conversión. De esta manera, otro ingeniero puede evaluar muy rápidamente la arquitectura general del programa desde solo el archivo principal. Además, para algunas MCU (MSP430 es un muy buen ejemplo) uno podría utilizar el mismo ISR (basado en argumentos) para diferentes propósitos (un buen ejemplo son múltiples bases de tiempo en un solo módulo de temporizador MSP430).
@GAttuso La arquitectura general del programa debe documentarse externamente; en la mayoría de los casos, un cuadro o gráfico simple es suficiente. No debe cambiar el diseño de su programa en un intento de eludir la necesidad de documentación. En cuanto a los ISR de uso general, escribe un controlador como lo haría con cualquier otro hardware, responsable de la asignación/desasignación de interrupciones. Los temporizadores de propósito general son el ejemplo de libro de texto de tal abstracción de hardware: su programa podría tener 10 temporizadores diferentes, todos usando el mismo ISR pero con funciones de devolución de llamada individuales, todos manejados por el controlador de temporizador de propósito general.
Bueno, estoy de acuerdo contigo. En general, debería ser así. Personalmente, me parece más conveniente/compacto/legible dejar los ISR en general para la familia MSP430, pero para MCU más complejos (C2000, ARM) sigo su enfoque. Aunque, probablemente sea una práctica muy mala cambiar la arquitectura de su código dependiendo de la plataforma MCU :)