MSP430 wie man konfigurierbare ISRs in einem Modul erstellt (Code Composer Studio C)

Ich habe eine Frage, auf die ich denke, dass die Antwort ganz einfach ist. Aber ich konnte keine klare Antwort darauf finden.

Wenn ich diese Serviceroutine in einem Modul foo.c habe

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

wenn ich in meiner Hauptsache habe.

#include "foo.h"

Dann scheint es, dass fooISR()tatsächlich in den SOME_VECTOR geladen wird und der ISR immer dann ausgelöst wird, wenn der entsprechende IFG gesetzt ist.

Ich wollte fragen, ob dies der richtige Weg ist, Module zu schreiben, die Interrupts verwenden. Denn bei diesem Ansatz fooISR()befindet sich der immer dann im SOME_VECTOR, wenn ich foo.h einfüge, dies lässt nicht wirklich viel Konfiguration für die Person zu, die in main arbeitet.

Wenn main.cich zum Beispiel auf einige Funktionen von foo.c zugreifen wollte, aber eine separate ISR für SOME_VECTOR schreiben wollte, hätte ich mit dieser Methode kein Glück, oder?

Antworten (2)

Die Sorge, die Sie im letzten Absatz äußern, ist richtig. Es scheint keine gute Idee zu sein, eine ISR mit anderen Funktionen zu bündeln, die Sie möglicherweise getrennt von der ISR wiederverwenden möchten.

Normalerweise mache ich eines der 3 Dinge:

  • Legen Sie die ISRs und main in dieselbe Datei wie main(). ISRs sind kurz, damit sie nicht main.czu sehr überladen werden.
  • Fassen Sie alle ISRs in einem separaten Modul zusammen. Keine andere Funktionalität in diesem Modul. Keine Absicht, dieses ISRs-Modul wiederverwendbar zu machen.
  • Setzen Sie jede ISR in ein eigenes Modul. Keine andere Funktionalität in diesen Modulen.

Sie können den ISR in einen #ifdefBlock stecken, wenn dies in Ihrer speziellen Situation sinnvoll ist.

Alle Ansätze sind sehr vernünftig. Es hängt auch davon ab, welche MCU Sie verwenden. Für MSP430 scheint der erste Ansatz der beste zu sein, da er normalerweise kurze ISRs hat, aber zum Beispiel für C2000 könnte es besser sein, den dritten Ansatz zu verwenden, da Sie normalerweise die meisten Steuerfunktionen in ADC/PWM/CAP-Interrupts haben.
Der normale Weg besteht ansonsten darin, die ISR mit verwandten Funktionen zu bündeln, die Sie zusammen mit der ISR verwenden möchten .
ISRs befinden sich also normalerweise in main.c? aber mit etwas #ifdef könnten wir es etwas konfigurierbarer machen? Ja, das macht sehr viel Sinn, danke Mann, das hat geholfen.

Zunächst einmal ist es nicht sinnvoll, diese Dinge zu diskutieren, es sei denn, Sie haben eine Art Programmdesign. Wenn Sie ein einfaches Programm mit weniger als 1.000 LOC oder so haben, brauchen Sie möglicherweise kein Design, es könnte ausreichen, einfach ziellos herumzuhacken.

Für größere, professionelle Programme benötigen Sie Programmdesign:

Sie sollten ISRs in derselben Datei platzieren wie den Rest des Treibers, der diese bestimmte Hardware steuert, da eine ISR Teil des Hardwaretreibers ist . Sie sollten nicht in main() sein, sie sollten nicht in einer nicht verwandten Datei sein.

Sie sollten sich nicht in einer „hier sind alle meine ISRs“-Datei befinden, es sei denn, Sie sind aufgrund von Hardware- oder Toolbeschränkungen gezwungen, sie zusammenzufassen. Möglicherweise müssen Sie die Vektortabelle jedoch in einer eigenen Datei aufbewahren, es sei denn, ihr Speicherort wird vom Linker verwaltet.

main() sollte nicht mit ISRs herumspielen. Sie haben eine Abstraktionsschicht über den Treibern und main wird die Abstraktionsschicht aufrufen. Das bedeutet, dass Sie keine enge Kopplung zwischen dem Algorithmus und der Hardware haben und dass Sie den Treiber einfach ersetzen können, ohne das gesamte Programm von Grund auf neu schreiben zu müssen.

Sie haben zu 100% Recht, dass es auf das Programmdesign ankommt. Die vollständige Entkopplung von ISRs von main.c kann auch einige Nachteile haben. Sie können ungefähr 20 ISRs-Handler in Ihrer main.c mit einer Codemenge von weniger als 1.000 Zeilen haben, mit nur Flag-Settern + etwas ADC-Ende der Konvertierungsergebnisse. Auf diese Weise kann ein anderer Ingenieur sehr schnell die gesamte Programmarchitektur nur aus der Hauptdatei bewerten. Darüber hinaus könnte man für einige MCUs (MSP430 ist ein sehr gutes Beispiel) dieselbe ISR (basierend auf Argumenten) für verschiedene Zwecke verwenden (ein gutes Beispiel sind mehrere Zeitbasen auf einem einzigen MSP430-Zeitgebermodul).
@GAttuso Die gesamte Programmarchitektur sollte extern dokumentiert werden, ein einfaches Diagramm oder eine Grafik reicht in den meisten Fällen aus. Sie sollten Ihr Programmdesign nicht ändern, um die Notwendigkeit einer Dokumentation zu umgehen. Wie für Allzweck-ISRs schreiben Sie einen Treiber wie für jede andere Hardware, der für die Zuweisung/Aufhebung der Zuweisung von Interrupts verantwortlich ist. Allzweck-Timer sind das Schulbuchbeispiel für eine solche Hardware-Abstraktion: Ihr Programm könnte 10 verschiedene Timer haben, die alle dieselbe ISR verwenden, aber mit individuellen Rückruffunktionen, die alle vom Allzweck-Timer-Treiber verwaltet werden.
Nun, ich stimme Ihnen zu. Generell sollte es so sein. Ich persönlich finde es bequemer/kompakter/lesbarer, ISRs hauptsächlich für die MSP430-Familie zu belassen, aber für komplexere MCUs (C2000, ARMs) gehe ich mit Ihrem Ansatz. Obwohl es wahrscheinlich eine sehr schlechte Praxis ist, Ihre Codearchitektur abhängig von der MCU-Plattform zu ändern :)