msp430g2xxx.h definiert einige intrinsics zu den "low power modes":
1
#define LPM0_bits (CPUOFF)
2
...
3
#define LPM4_bits (SCG1+SCG0+OSCOFF+CPUOFF)
4
#define LPM0 __bis_SR_register(LPM0_bits) /* Enter Low Power Mode 0 */
5
#define LPM0_EXIT __bic_SR_register_on_exit(LPM0_bits) /* Exit Low Power Mode 0 */
6
...
7
#define LPM4 __bis_SR_register(LPM4_bits) /* Enter Low Power Mode 4 */
8
#define LPM4_EXIT __bic_SR_register_on_exit(LPM4_bits) /* Exit Low Power Mode 4 */
zum Aktivieren und Verlassen bei Rückkehr aus einer ISR.
Wie kann jedoch der Modus gewechselt werden, also z.B. von LPM4 zu
LPM1 (am Ende des pin-change Interrupts)?
Reicht evtl. ein
Mit den defines kannst du den Lpm4 nur im normalen Programm ändern. Also
ISR ohne Lpm verlassen und den neuen einstellen.
Oder du musst das SR auf dem Stack in der ISR von Hand anpassen.
Ich dachte, die _on_exit builtins machen genau dies: das auf dem Stack
gesicherte SR modifizieren.
https://gcc.gnu.org/onlinedocs/gcc/MSP430-Built-in-Functions.html> This clears the indicated bits in the saved copy of the status register
currently residing on the stack. This only works inside interrupt handlers and the
changes to the status register will only take affect once the handler returns.
http://www.rowleydownload.co.uk/msp430/documentation/__bic_SR_register_on_exit.htm> __bic_SR_register_on_exit clears the bits specified in mask in the saved status
register of an interrupt function (i.e. it bitwise ands the complement of mask
into the saved status register). This allows you to change the operating mode of
the MSP430 on return from the interrupt service routine, such as changing the low
power mode.
> __bic_SR_register_on_exit can only be used in interrupt functions—an error is
reported if it is used outside an interrupt function.
Ich brauch's aber gar nicht mehr, da ich den Code aus dem Interrupt
herausgeholt habe und daher die CPU aktiv brauche.
Maximum Security Prison 430 schrieb:> Ich brauch's aber gar nicht mehr, da ich den Code aus dem Interrupt> herausgeholt habe
Das wird empfohlen; auch, weil mit einem kürzeren Interrupt-Handler
andere Interrupts schneller behandelt werden können.
Nicht in diesem Fall (LPM4->LPM1), es müssen doch nur die
"überflüssigen" bits gelöscht werden um die entsprechende Hardware
wieder zu aktivieren.
Genau das war ja die Ausgangsfrage, ob man "LPM4_EXIT" (bits löschen)
gefolgt von "LPM1" (bits schreiben) vermeiden kann.
Probiert habe ich es aber nicht.
Anwendung ist das Aufwachen und anschließendes, timergesteuertes Pollen
(Entprellen etc.) bei Tastendruck. Man könnte so bei Bedarf fast ohne
CPU-Einsatz (im Interrupt läuft sie) durch den pin-change Interrupt den
Timer aktivieren.
wenn ich das richtig verstanden habe, willst Du nicht nach dem Verlassen
der ISR die CPU aufwecken, sondern in einem anderen Low-Power-Mode
weiterschlafen lassen. Dann darfst Du nicht die .._on_exit() intrinsics
verwenden, denn die wirken sich erst bei Verlassen der ISR aus. Ich
würde da direkt in der ISR mit dem __bic_SR_register() Befehl arbeiten:
Auszug aus der Header-Datei:
Die ISR wird in jedem Fall verlassen und das SR wiederhergestellt. D.h.
deine vorgeschlagene Manipulation auf das SR (= Active Mode in der ISR)
ändert nicht viel und wird sofort wieder überschrieben...
Maximum Security Prison 430 schrieb:> Genau das war ja die Ausgangsfrage, ob man "LPM4_EXIT" (bits löschen)> gefolgt von "LPM1" (bits schreiben) vermeiden kann.
"LPM1;" würde die CPU sofort schlafen legen. Innerhalb des
Interrupt-Handlers ist das keine gute Idee.
Ein
Im Family Data sheet steht im Abschnitt 2.2.3.1 "Interrupt Acceptance"
ganz klar, daß das SR zurückgesetzt wird; das heißt, CPUOFF=0, also
Active Mode.
Du mußt für den neuen Modus das SR aus dem Active Mode heraus
entsprechend neu setzen.
JW schrieb:> Family Data sheet
von was? TI hat diverse Family User Guides für die verschiedenen MSPs.
JW schrieb:> ganz klar, daß das SR zurückgesetzt wird
um die ISR auszuführen! Das SR wird beim Eintritt gepushed und mit dem
RETI gepopped. Nach der ISR isr vor der ISR.
@ Mikael:
Bist ein ganz schlauer, gell?
ad 1: Im Eröffnungs-Thread steht MSP430G2xxxx - also gibt's dazu einen
Family Datasheet.
ad 2: Um von einem LPM-Zustand in einen anderen zu wechseln, muß die MCU
zuerst in den AM gehen - was für ein Wunder, natürlich ist das eine ISR.
Ergänzung zum ursprünglichen Thema:
Willst Du in einer ISR den Zustand wechseln, dann könnte das z.B. so
aussehen:
add #4,SP // Korrigiere die Stackpointer-Position
// (also das, was auch bei "reti"
geschieht)
bis #SCG1+OSCOFF,SR // Wieder in den gewünschten LPM
JW schrieb:> also gibt's dazu einen> Family Datasheet
Nö, entweder Family User Guide oder Baustein Datenblatt,
aber kein Family Datenblatt. ;-)
JW schrieb:> Willst Du in einer ISR den Zustand wechseln
Was fürn Schwachsinn? Wenn du den MSP430 innerhalb der ISR Schlafen
schickst, wer soll ihn wieder wecken?
Da du den FUG nicht liest oder verstehst, schreib ich dirs noch einmal
auf:
Beim Eintritt in die ISR rettet der uC das SR auf dem Stack. Dann kannst
du deinen Kram machen. Und mit dem RETI restauriert der uC das SR (mit
dem Wert vom Stack).
-> Dein Gefummele innerhalbb der ISR ist für die (Speicher-)Tonne.
JW schrieb:> Bist ein ganz schlauer, gell?
Wenns um uns Beiden beim Thema MSP geht: JA!
Maximum Security Prison 430 schrieb:> Kinder, Zeit für den Mittagsschlaf!
Geht ja leider nicht, bei dem Blödsinn. Über Geschmack läßt sich
streiten und trotzdem sollte man jedem seine Meinung gönnen. Aber bei
dem Thema hier ...
JW schrieb:> add #4,SP // Korrigiere die Stackpointer-Position> // (also das, was auch bei "reti"> geschieht)> bis #SCG1+OSCOFF,SR // Wieder in den gewünschten LPM
Puhhh, das wird ja immer besser :'(
Probier das mal aus und berichte über deine Ergebnisse. :-P
So, hatte gerade mal das launchpad in der Hand. Mit
__bis_SR_register_on_exit läßt sich der LPM beliebig wechseln oder
auch verlassen. Getestet habe ich das mit folgendem Programm