Forum: Mikrocontroller und Digitale Elektronik MSP430x2112 Flash-Speicher schreiben und lesen


von Matthias Pollack (Gast)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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.

von Matthias Pollack (Gast)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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.

von Matthias Pollack (Gast)


Lesenswert?

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

von Christian R. (supachris)


Angehängte Dateien:

Lesenswert?

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....

von Matthias Pollack (Gast)


Lesenswert?

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

von Christian R. (supachris)


Lesenswert?

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
Noch kein Account? Hier anmelden.