Hi zusammen, Ich möchte bei meinem MSP430 F1611 alle Interrupts ausschalten und zu beliebigen Zeitpunkten beliebige Interrupts zu- und wieder ausschalten können. Nachdem meine Routine durchgearbeitet wurde, sollten alle Interrupts in ihren ursprünglichen Zustand zurückgesetzt werden. Bei mir fallen folgende Probleme an: - Z.B möchte ich nur nur die Interrupts von Timer B0 (aber nicht diejenigen von TB1...7) aktiviert haben. - Wie soll ich die Interruptzustände während der Routine zwischenspeichern? Gibt es dazu eine besonders elegante Lösung? Oder ist dies nur über Flags und temporäre Variablen lösbar?
Irgendwas sagt mir, dass Du wahrscheinlich alles zu kompliziert implementierst. Warum willst Du denn bestimmte Interrupts überhaupt zur Laufzeit aus- und wieder einschalten?
Ich möchte mehrere zeitkritische Messungen durchführen. Unter Anderem eine Anstiegszeit am ADC und auch eine Time-Difference zwischen zwei Pulsen. Diese Zeitmessungen müssen möglichst exakt sein und dürfen deswegen nicht gestört werden.
OK, ich kann mein problem reduzieren: Kann ich beim Timer_B nur die Interrupts von Timer 0 aktiviert haben? Die Interrupts von Timer 2...7 sollen deaktiviert werden.
> Kann ich beim Timer_B nur die Interrupts von Timer 0 aktiviert haben? > Die Interrupts von Timer 2...7 sollen deaktiviert werden. Sieh Dir mal die Bedeutung des Bits CCIE in den Registern TBxCCTLn (n = Nummer der Capture/Compare Unit) an.
Beim GCC gibts außerdem das Attribut _critical_ oder so. Das kann man für Funktionen verwenden, da wird beim Start der Funktion der GIE ausgeschaltet, falls an, und am Ende wieder der Ausgangszustand hergestellt. Vielleicht hilft dir das auch. Prinzipiell kannst du aber bei jedem Timer-Block das CCIE löschen.
Wie funktioniert eine Lösung über Intrinsics? (IAR Embedded Workbench)
1 | __istate_t s = __get_interrupt_state(); |
2 | __disable_interrupt(); |
3 | |
4 | /* Do something */
|
5 | |
6 | __set_interrupt_state(s); |
7 | __enable_interrupt(); |
Kann ich im Abschnitt "Do something" Interrups ein- und ausschalten?
1.) Du solltest Dir mal den Unterschied zwischen den einzelnen lokalen IE-Bits der jeweiligen Peripherie-Einheit und dem globalen GIE-Bit klar machen! 2.) >Wie funktioniert eine Lösung über Intrinsics? (IAR Embedded Workbench) Genauso wie die __monitor Funktion (s. Compiler Reference Guide) 3.) Dein Code-Fragment von oben ist sinnlos, denn nach Herstellen des ursprünglichen GIE-Zustands (__set_interrupt_state(s);) setzt Du in der nächsten Zeile bedingungslos wieder das GIE-Bit! 4.) >Kann ich im Abschnitt "Do something" Interrups ein- und ausschalten? Du kannst Ein- und Ausschalten was und wann immer Du es willst... ob's Sinn macht oder funktioniert ist 'ne andere Frage. 5.) Wenn Du einzelne IRQs beliebig aktivieren und deaktivieren willst, wirst Du nicht drum herum kommen, Dir selbst den Status zu merken und ggf. wieder herzustellen! Wenn Du alle IRQs de-/aktivieren willst, dann eben mit __monitor Funktion oder per __get/__set-Interrupt_state() aber ohne __enable_interrupt()
Ich denke die durchsichtigste Variante ist immer noch das ablegen des Interrupt-enable bits in einer variablen. Da weißt du wenigstens immer genau was du tust. Dennoch führt das ein und ausschalten von interrupts gerne zu seltsamen Fehlern, die oft erst nach tagelangem Testen "zufällig" auftreten. Es ist daher ratsam, genauestens zu überlegen, was alles in der kritischen Phase passieren könnte. Grüße Gebhard
Stefan schrieb: >3.) Dein Code-Fragment von oben ist sinnlos, denn nach Herstellen des >ursprünglichen GIE-Zustands (__set_interrupt_state(s);) setzt Du in der >nächsten Zeile bedingungslos wieder das GIE-Bit! Laut Compiler Reference Guide reicht es, wenn man folgende Zeilen schreibt:
1 | __istate_t s = __get_interrupt_state(); |
2 | __disable_interrupt(); |
3 | /* Do something */
|
4 | __set_interrupt_state(s); |
Warum benutzt man __enable_interrupt() nicht? Was bedeutet es, wenn das GIE-Bit wieder gesetzt wird?
Der Sinn des ganzen ist es doch durch:
1 | __set_interrupt_state(s); |
den ursprünglichen Interruptzustand wiederherzustellen! Wenn vorher GIE gesetzt war, soll es danach auch wieder gesetzt sein. Wenn vorher GIE nicht gesetzt war, darf es hinterher auch nicht gesetzt werden... genau das würde aber __enable_interrupt(); gnadenlos tun!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.