Guten Tag,
ich besitze einen STM32F031 und möchte zur Laufzeit in eine freie
Flashseite etwas programmieren bzw. diese löschen. Aufgrund der
Löschzeit von max. 40ms möchte ich aber parallel weiter meine
Main-Funktion / andere Funktionen und Interrupts abarbeiten und auf ein
Flash-Interrupt warten, also kein Busywait.
Meine Frage: Ist das so direkt umsetzbar, dass gelöscht/programmiert
wird und ich parallel andere Programmteile ausführen kann (inkl.
Interruptroutinen)?
Die Frage stelle ich, weil ich Zweifel aufgrund folgender Textzeilen im
Datenblatt habe:
1
during a program/erase operation to the Flash memory, any attempt to read the Flash memory will stall the bus. The read operation will proceed correctly once the program/erase operation has completed. This means that code or data fetches cannot be made while a program/erase operation is ongoing.
Ich verstehe darunter, dass ich KEIN Code (Code fetch) aus dem Flash
holen und ausführen darf, während Löschen/Programmieren. Ist es dann
notwendig, dass ich mein Linkerfile anpassen muss um den Code in den
SRAM zu bekommen?
Mein Linkerfile:
1
.isr_vector :
2
{
3
. = ALIGN(4);
4
KEEP(*(.isr_vector)) /* Startup code */
5
. = ALIGN(4);
6
} >FLASH
7
8
/* The program code and other data goes into FLASH */
normally you can read one page while writing/erasing another, but in STM32 the entire flash bus stalls, so no no code in flash runs - stalling execution for significant periods (tens of milliseconds)
Um waehrend des Flashzugriffes bei den Single Bank STM32 Bauteilen
weiterarbeiten zu koennen, wirst Du wie ein Fuchs darauf aufpassen
muessen , dass Dein Code im Ram nicht irgendetwas aus dem Flash braucht:
Code, Daten, Literal, Interrupt Vektoren etc.
stm32user schrieb:> Aufgrund der> Löschzeit von max. 40ms möchte ich aber parallel weiter meine> Main-Funktion / andere Funktionen und Interrupts abarbeiten und auf ein> Flash-Interrupt warten, also kein Busywait.
Dann hol Dir einen dicken µC, der entweder 2 kompltt getrennte Flash
Bereiche hat (z.B. EFM32GG) oder den kompletten Code aus dem RAM
ausführen kann.
stm32user schrieb:> Ist es dann> notwendig, dass ich mein Linkerfile anpassen muss um den Code in den> SRAM zu bekommen?
Nicht nur das Linker File. Auch den Startup Code müsstest Du dann
anpassen, denn es muss ja mindestens so etwas wie memcpy() im Flash
verbleiben zuzüglich einer Kopie der Interrupt Vektor Tabelle.
Mir gefällt die Speicheraufteilung der STM32 für nichtflüchtige Daten
generell nicht - der wohl größte Minuspunkt an diesen Controllern. Ich
verwende daher immer ein externes EEPROM, auch wenn das etwas mehr Platz
und Geld kostet.
Ansonsten ist das wichtigste gesagt. Aufpassen, dass dein Code keinen
Flashzugriff benötigt. Mit einem SPI EEPROM passiert mir sowas aber
nicht ;).
Eine Ergänzung von mir die meine Zweifel bestärkt, scheint als ob der
ganze Controller ausser Gefecht gesetzt wird:
https://community.st.com/thread/30821>wirst Du wie ein Fuchs darauf aufpassen>muessen , dass Dein Code im Ram nicht irgendetwas aus dem Flash braucht
Sprich: Mit meinem aktuellen Linkerfile (ganzer Code im Flash) kann ich
mein Vorhaben in die Tonne kloppen?
Ich hab > 5k Code im Flash, aber nur ein 4k RAM. Damit ist also dieses
"Parallele abarbeiten der main / andere Unterfunktionen" wohl
Wunschdenken und verdammt kompliziert.
Ich muss also mit sowas arbeiten, richtig?
stm32user schrieb:> Ich muss also mit sowas arbeiten, richtig?
Ich hätte die Section ".data.TIM3_IRQHandler" genannt, aber ungefähr
richtig.
Du musst aber auch zwingend die Vektor-Tabelle ins RAM schieben, und ich
weiss grade nicht ob der Cortex-M0 überhaupt das dafür notwendige VTOR
Register kennt. War das nicht ein optionales Feature...?
Jim M. schrieb:> Du musst aber auch zwingend die Vektor-Tabelle ins RAM schieben, und ich> weiss grade nicht ob der Cortex-M0 überhaupt das dafür notwendige VTOR> Register kennt. War das nicht ein optionales Feature...?
Die STM32F0 Serie hat kein VTOR. Um das zu umgehen mappe ich mit SYSCFG
das Ram an Adresse 0. Dann ist die Interrupttabelle im Ram aktiv.
stm32user schrieb:> Ich hab > 5k Code im Flash, aber nur ein 4k RAM.
Kannst du den Code, der parallel zum schreiben läuft, nicht eingrenzen
sodass nur ein "Notprogramm" in den RAM passen muss? Kannst du einfach
nach dem Abschalten des Geräts schreiben indem du einen Kondensator als
Puffer verbaust? Reduziert auch die Flash Abnutzung.
Danke, für die Antworten.
Ich wünschte ich hätte dieses Dokument früher gefunden und mir die
Sucharbeit erspart:
AN4808
Writing to non-volatile memory without disrupting code execution
on microcontrollers of the STM32L0 and STM32L1 Series
http://www.st.com/content/ccc/resource/technical/document/application_note/group0/7c/6a/88/d1/27/04/46/2f/DM00260799/files/DM00260799.pdf/jcr:content/translations/en.DM00260799.pdf
Schade das im Reference Manual dieser ganze Sachverhalt nur in paar
Sätzen kurz nebenbei erläutert wird.
>Kannst du den Code, der parallel zum schreiben läuft,>nicht eingrenzen sodass nur ein "Notprogramm" in den RAM passen muss
Das werd ich wohl machen müssen, da ich heute rausgefunden habe, dass
sogar (hochpriorisierte) Interrupts nicht bearbeitet werden während
dieser Zeit - was fatal ist ... sogar Watchdogs.
>Wäre es denn in der Zeit möglich auf die Ereignisse mit DMA zu
reagieren?
Ich hatte eher die Idee an eine komplette quasi-Multitaskanwendung
gedacht, also mit mehreren Tasks ...
Kann mir jemand noch vielleicht verraten, was der Sinn hinter der
Funktion ist, die ja im Flash ausgefuehrt wird:
stm32user schrieb:> Kann mir jemand noch vielleicht verraten, was der Sinn hinter der> Funktion ist, die ja im Flash ausgefuehrt wird:
Wenn ein Not-Programm aus dem RAM ausgeführt wird, dann muss es
irgendwie rauskriegen können, ob es seinen Zweck erfüllt hat und wieder
an das Hauptprogramm abgeben darf.
Die Löschzeit ist im Verhältnis zur Schreibzeit von zwei Byte ja recht
lang.
(ms v. µS)
Vielleicht kannst du das Löschen auf unkritische Zeitpunkte legen (z.B.
Startup)
>Wenn ein Not-Programm aus dem RAM ausgeführt wird
Diese ganzen Funktionen wie EraseFlash, ProgramHalfWord, .. SOLLTEN also
aus dem RAM aufgerufen werden. Weil ja sonst die nächste Programmzeile
nach dem Funktionsaufruf die CPU Blockade hervorrufen würde.
Schade das diese Empfehlung mit der Auslagerung in den RAM gar nicht im
Code/StdLib dokumentiert ist. Wenn ich mich irre, bitte Bescheid sagen.
Alles sehr mager beschrieben