Hallo Leute! Wir sind MSP430-Anfänger und haben nun vor, Daten ins Flash zu schreiben um sie auch nach einem PowerOff noch lesen zu können. Wir haben nun eine raffinierte Routine entwickelt. Wir nutzen die Main-Routine nur, um alle Variablen zu initialisieren und schicken den Prozessor dann mit einem NOP in den Tiefschlaf. Der eigentliche Funktionsteil unserer Schaltung wird durch eine Interrupt-Routine ausgelöst. Und zwar auf Basis eines Timers, dem Timer TA0. Dieser ist so programmiert, dass er alle 0.0125 Hz einen Interrupt auslöst und dann eine von uns programmierte Interrupt-Routine abfährt. Somit ist gewiss, dass der Prozessor zwischen den Interrupts immer schön stromsparend einschläft und nur durch den Interrupt aufwacht. Beim Beackern des User-Guides steht aber wohl fest, dass es für einen Schreib- bzw. Löschvorgang eines Flash-Segmentes vonnöten ist, jegliche Interruptausführungen am Prozessor zu stoppen, dann den Flash-Vorgang auszuführen und dann gerne die Interrupts wieder einzuschalten. Das Problem ist nun, dass wir, um in den Flash-Speicher schreiben und lesen zu können (s.o.), die Interrupts generell eben nicht aus einem Interrupt heraus deaktivieren können. Wie machen wir es nun aber, wenn wie in unserem Falle die Main-Routine mit einem no_operation einschläft und alle Funktionalitäten des Programms aus dem Timer-Interrupt kommen? Können wir dann gar nicht auf den Flash schreiben/löschen/zugreifen? Es wäre echt bitter, alles wieder in eine Main-Schleife umzumodeln. Zudem läuft der Prozessor dann immer und schläft nie ein ... Was tun? Lieben Dank, Matthias
Hm, also irgendwie ist das alles bissl unklar. Der MSP430 wird doch nicht durch ein NOP in den Sleep geschickt sondern z.B. durch die Markos _BIS_SR(LPM1_bits + GIE) usw. Um den Flash zu beschreiben, kannst du sowieso nicht im LPM sein, denn du brauchst für den Flash Controller einen Takt, der üblicherweise vom SMCLK kommt (muss ja mindestens 450kHz oder sowas sein). Alles in einer Timer-ISR abzuarbeiten ist eh schlechter Programmier-Stil. Normalerweise setzt man in der ISR ein Flag, welches die Main-Schleife veranlasst, eine gewisse Funktion anzuspringen und abzuarbeiten. Am Ende der ISR muss dann das Wakup-Makro sein, damit der Prozessor nach dem Interruptm noch wach ist. Anschließen wird das Unterprogramm abgearbeitet, das Flag wieder gelöscht und wenn keine Aufgaben mehr anstehen, der Prozessor wieder in den LPM geschickt. Das ist ganz einfach und effektiv. Natürlich kannst du auch in der ISR den Flash beschreiben, wenn du in der ISR bist, ist ja auch alles aktiv, und die Interrupts erst mal aus. Da kannst du doch deine Daten schreiben.
Hallo Christian! Lieben Dank für Deine Antwort. Unsere Main-Routine hat als letztes Kommando, nachdem wir den _EINT(); ausgeführt haben, __no_operation();. Dann hält der Prozessor doch an und schläft ohne Aktion ein, oder? Der Watchdog ist aus. Als Clock nehmen wir den internen DCO mit dem Grundtakt (glaube 800 kHz waren das). Der MSP430 hat also in unserer Anwendung keinerlei externe Quarze oder sowas. Das einzige, was ihn aufweckt ist dann der Timer A0, den wir so konfiguriert haben, dass er unsere eine Interrupt-Routine abfährt. Und da ist der eigentliche Teil der auszuführenden Aktionen (ist blos das Setzen einiger IOs). Der Timer bildet sich den Aufweckzeitpunkt aus dem MCLK mit Teiler 10 und löst dann einen Interrupt aus. So kommt die Zeit von 0.0125 sec pro Interrupt zustande. Wir haben bis jetzt auch nur diesen einen Interrupt. Sonst keinen weiteren. Eventuell kommt noch einmal einer für den ADC dazu, aber die Frage ist, ob ich das per Interrupt machen wollte. Wohl eher nicht. Wir nutzen den Controller blos als Ausführelement. Er soll also auf verschiedene IOs als Eingänge geschaltet mit bestimmten Funktionen reagieren und andere IOs als Ausgänge schalten. Mehr nicht. Dafür ist er eh etwas oversized, aber die Tools und das Können sind beim MSP430 einfach genial. Du meinst also, wir sollen einfach den Flash-Vorgang aus der Interrupt-Routine heraus ausführen? Lieben Dank noch einmal für Deine Antwort. Wir lernen ja noch ;-))) Gruß, Matthias
Also der NOP Befehl stoppt den Prozessor keineswegs. Da wird nur einfach 1 Prozessorzyklus lang nix gemacht, und dann gehts mit dem nächsten Befehl weiter. NOP ist ein völlig normaler Befehl, nur dass es eben keine Interaktion stattfindet. Wenn du in einen LPM willst, musst du die entsprechenden Bits im Statusregister setzen. Das geht am einfachsten über die Makros, siehe oben. Schau dir mal die Code-Beispiele bei TI an.
Hallo Christian! Unsere Main-Routine hat keine Endlosschleife. Der letzte Befehl ist ein NOP, aber danach kommt nichts mehr. Den NOP selbst könnten wir dann nach unserem Main-Konstrukt wohl weglassen, oder? Was passiert am Ende der Main-Routine mit dem Prozessor? Tut er dann einfach nichts mehr? Was passiert bezüglich der Stromsparmodis? Aber zurück zum Problem: Im User's Guide steht, dass mit den Interrupts das Problem ist, dass der Flash-Controller den Opcode 03FFFh (JMP PC) dem Prozessor aufprägt, solange eine Flash-Operation läuft. Würde also in dieser Zeit ein Interrupt ausgelöst, ginge als Sprung-Adresse 03FFFh auf den Interrupt-Stack, was den Prozessor nach Beenden des Flash-Vorganges JMP PC ausführen ließe aber sicher nicht die ISR, die wir ja brauchen. Ist es also statthaft, dem Timer den Interrupt einfach aus der ISR selbst heraus solange zu deaktivieren, wie geflasht wird und dann einfach danach den Interrupt auf den Timer wieder einzuschalten? Dann würde ja, falls der Flash-Vorgang länger als ein Timer-Intervall dauerte, zwar der Timer entsprechend unseren Einstellungen nach wie vor überlaufen, hierdurch aber kein Interrupt ausgelöst ... Nach dem Flashen wäre dann wieder alles normal ... Liebe Grüße, Matthias
Also wenn du keine Endlosschleife in der Main hast, ist das sehr gefährlich, denn der Prozessor läuft dann irgendwo hin. Eventuell hat der Kompiler eine wie auch immer geartete Exit-Geschichte eingebaut, aber darauf kann man sich nicht verlassen. Wo lernt man denn sowas zu programmieren? Bau mal eine Endlosschleife ein, die den Prozessor in den LPM schickt. Zum Interrupt: Sobald eine ISR betreten wird, werden alle Interrupts deaktiviert. Es sei denn, du gibts bei der ISR-Deklaration ausdrücklich an, dass die Interrupts wieder aktiviert werden sollen (nested interrupt). Das sollte man aber tunlichst nur dann machen, wenn man ganz *ganau* weiß, was man programmiert. Also ihr solltet das auf keinen Fall machen. Du kannst also den Flash in der Timer-ISR beschreiben, da das GIE-Bit sowieso aus ist, und keinerlei andere Interrupts dazwischen kommen können. Im Anhang ein PDF von TI, wie man das ordentlich macht. Ach übrigens: Willst du alle 0,0125 Sekunden den Flash neu beschreiben? Das wird der nicht lange mit machen....
Hallo Christian! Nein, ich will nicht alle 0.0125 sec den Flash neu beschreiben. Das mit den Interrupts habe ich auch verstanden. Hmm, ich weiß gerade nicht ob der Timer A, der bei uns alle 0.0125 sec einen Interrupt auslöst, damit aufhört, solange wir uns in der ISR dazu befinden. Weil dann würde ja, würde die Abarbeitung der ISR länger als 0.0125 sec dauern der Stack vom Interrupt ins Nirvana laufen weil pro ISR ein neuer Interrupt dazukäme. Ich denke nicht, dass die Abarbeitung unser kleinen ISR länger dauert, also keinesfalls, denn es läuft aktuell. Aber beim Flashen bin ich mir nicht sicher. Zur Not schalte ich den Interrupt per setzen des entsprechenden Status-Bits für den Timer einfach manuell ab, sobald ich flashe und danach wieder an. Wir werden sehen! Zum Main: Nunja, habe einfach ein paar Code-Exemplare eines Bekannten beackert. Insofern ist meine Erfahrung gering. Der Compiler muss dann eine Exit-Geschichte hineinbauen, denn ein Prototyp läuft seit 2 Wochen dauernd ohne Absturz durch! Ich werde aber einmal eine While-1-Schleife hinten anbauen und mir die LPMs mal ansehen. Lieben Dank erst einmal! Viele Grüße, Matthias
Matthias Pollack schrieb: > Das mit den Interrupts habe ich auch verstanden. Hmm, ich weiß gerade > nicht ob der Timer A, der bei uns alle 0.0125 sec einen Interrupt > auslöst, damit aufhört, solange wir uns in der ISR dazu befinden. Weil > dann würde ja, würde die Abarbeitung der ISR länger als 0.0125 sec > dauern der Stack vom Interrupt ins Nirvana laufen weil pro ISR ein neuer > Interrupt dazukäme. Wie gesagt, solange du den Interrupt nicht explizit in der ISR wieder einschaltest ist der aus, und jeder weitere Interrupt wird ignoriert, solange die ISR dauert. Also läuft da überhaupt nix über. Außerdem hat der MSP430 keinen direkten Stack, sondern der geht vom oberen Ende des RAM los, bis halt die Variablen kommen. Da ist genug Platz, wenn man nicht alles voll mit Variablen gehauen hat.
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.