Forum: Mikrocontroller und Digitale Elektronik STM32 : internen Flash löschen/schreiben - CPU stall mit STLINK detektieren?


von STM32-User (Gast)


Lesenswert?

In meiner Anwendung soll ein STM32F100R8T6B über SPI umprogrammiert 
werden können.
Der STM ist dabei im SPI Slave mode, das neue Programm wird zur Laufzeit 
vom Master in SPI-Paketen übertragen.
im Slave werden die Daten in einen freien Teil des int. Flash 
geschrieben,  danach umkopiert und der STM startet sich selbst.

Hierzu wurden bereits sämtliche Flash-Routinen, sowie der SPI-IRQ 
Handler ins RAM ausgelagert. Alle Routinen funktionieren nach ersten 
Tests einwandfrei, solange der Flash nicht "busy" ist.

Sobald ein Flash Sektor gelöscht oder geschrieben wird, reagiert der STM 
temporär nicht mehr auf eingehende SPI-Pakete zur 
Status-Abfrage(Polling, ob das letzte Paket korrekt geschrieben wurde)
Ich vermute, daß noch (irgendwo) ein CPU Stall auftritt und suche nun 
nach Möglichkeiten, dieses "irgendwo" zu lokalisieren.  Intensives 
Suchen im Code sowie im List-File brachte leider keine Resultate.

Ideal wäre ein Breakpoint, der aktiviert wird, sobald der STM einen 
Flashzugriff versucht.

Mir fiel auf, daß mein STLink auf Breakpoints innerhalb Flash-basierter 
ISRs reagiert und diese im korrekt anzeigt. Sobald eine Routine jedoch 
in den RAM verschoben wird, ist der Breakpoint wirkungslos bzw. wird 
ignoriert.
Gibt es hier eine Möglichkeit, auch diese zu aktivieren?

Der Versuch per Schrittbetrieb kurz vorm Löschen das Flashes zu starten 
und sich dann IRQs oder Zugriffe anzuzeigen brachte keinerlei 
Erkenntnisse - es traten schlicht keinerlei Ereignisse auf, da ja selbst 
die SPI-Interrupts ignoriert wurden.
(Auf Masterseite sah man, daß diese während des Schrittbetriebs 
erwartungsgemäß nicht abgearbeitet wurden.)

Gibt es evtl jemanden, der vor ähnlichen Rätseln stand oder mir ein paar 
konstruktive Ratschläge geben könnte, wie man in dieser Situation weiter 
vorgehen könnte?

Vielen Dank
ein ziemlich ratloser STM32-User

ps: Debugausgaben via UART sind prinzipiell zwar möglich, brachten 
jedoch aufgrund der hohen Übertragungsgeschwindigkeit des SPI-Busses und 
der kurzen Stall-Zeit bis auf einige verpaßte Daten keinen wirklichen 
Nutzen.

von Jim M. (turboj)


Lesenswert?

STM32-User schrieb im Beitrag #3355718:
> sowie der SPI-IRQ
> Handler ins RAM ausgelagert.

Auch die Interrupt Vector Table (Register VTOR)? Ohne die kann er den 
oder die Handler nicht anspringen.

von STM32-User (Gast)


Lesenswert?

Vielen Dank für die Anregung Jim.
Leider muß ich sagen - ja, sie liegt im RAM.

Das Linkerskript wurde modifiziert, sodaß .isr_vector in ">RAM AT>FLASH" 
liegt.
Da es mir nicht gelang, die Daten im RAM via Linker-Skript zu 
initialisieren, kopierte ich sie händisch.
Dies wird gleich zu beginn in der Main erledigt:

memcpy(p_ramisr,  p_flashisr, isrlen);
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);

p_flashisr (0x0000000)
p_ramisr (0x20000000)  (= NVIC_VectTab_RAM)
isrlen (0x1D0)

lt. List-File geht die ".data" section (_sdata) bei 0x200001D0 los - 
d.h. der bereich vorher wurde reserviert.
Im "nicht busy" Betrieb werden die Handler korrekt angesprungen.

===============================
Aber trotzdem ein sehr guter Einwand, im "Normalbetrieb" würde man nicht 
merken, ob er den Handler aus einer Tabelle im RAM oder Flash anspringt.

von marvin m. (Gast)


Lesenswert?

Hallo,

nutzt du die Flash-Programmierroutinen aus der STlib? Dort gibt es viele 
Warteschleifen... Evtl. das alles zu einer Art kooperativem Multitasking 
umprogrammieren, d.h. man wartet nicht darauf, dass etwas fertig wird, 
sondern arbeitet auch die anderen Programmteile noch ab.

von STM32-User (Gast)


Lesenswert?

Hallo Marvin,

genau die nutze ich, habe sie lediglich leicht modifiziert, sodaß sie im 
RAM liegend ihren Dienst verrichten.
Die Warteschleife beim Flasch löschen stört mich an dieser Stelle nicht.
Da die Applikation im Normalbetrieb (d.h. nicht während eines Updates) 
sehr strikte Echtzeitanforderungen hat, verzichte ich auf ein OS, nutze 
eine schlanke Maintask und führe das Parsen und den CRC-Check der 
eingehenden SPI-Pakete im Interrupt aus. (Paßt soweit zeitlich auch gut, 
sodaß ich im Normalbetrieb keine Daten verliere.

Zu Debugzwecken schreibt der Master in sehr kurzen Zeitabständen 
einzelne Bytes (sequentielle Werte) via SPI, die der Slave einfach 
zurückgibt.

im Normalmodus kommen die daten 1:1 zurück (genau 1 Byte verzögert,so 
wie es sein soll).
Beim Flash-Löschen sieht man nun sehr schön das Löschen der einzelnen 
Sektoren- hier wird durch Stall die SPI routine nicht aufgerufen und der 
Master bekommt immer die gleichen Daten zurück.

Daher habe ich auch kein Zweifel, daß es sich um einen CPU Stall handelt 
- das Löschen wird ja in der Main Routine angestoßen und dort auch 
erfolgreich abgearbeitet..

Die Frage, die sich mir stellt ist nur: wie (mit welcher Methode) kriege 
ich am effizientesten raus, wodurch genau der Stall verursacht wird.


Nun, ich suche und probiere weiter..  (kommt mir langsam vor wie die 
Suche nach der Nadel im Heuhaufen :))

von STM32-User (Gast)


Lesenswert?

Korrektur:  die Antwort vom Slave kommt 2 Byte danach an

Ich habe soeben einen Test gefahren: direkt nach dem Starten des 
"Flash-Löschens"  werden vom Master die Bytes 0x00 bis 0x0F periodisch 
geschrieben und die Antworten ausgewertet.
Dies kam dabei raus:

TX:
[TX+  0]:  00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,
[RX+  0]:  00,00,00,00,00,00,00,00,00,00,00,02,02,02,02,02,

[TX+ 16]: 
00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,00,01,02,03,04,05,06
[RX+ 16]: 
02,02,02,02,0B,0B,0B,0B,0B,0B,0B,0B,0B,0B,0B,04,04,04,04,04,04,04,04

[TX+ 39]:  07,08,09,0A,0B,0C,0D,0E,0F,00,01,02,03,04,05,06,
[RX+ 39]:  04,04,04,04,0F,0B,0B,0B,0B,0B,0B,0B,0B,0B,0B,0C,

...  hier der letzte flash sektor:  (versatz des "echos" ist nun wieder 
konstant 2)

[TX+234]: 
0A,0B,0C,0D,0E,0F,00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F
[RX+234]: 
06,06,06,06,06,02,02,02,02,02,02,0F,0F,05,06,07,08,09,0A,0B,0C,0D

von marvin m. (Gast)


Lesenswert?

Hallo,

hm - OK, ich hatte bislang überlesen, dass die SPI-Routinen im Interrupt 
laufen.
In PM0075 Seite 10 heißt es:
"During a write operation to the Flash memory, any attempt to read the 
Flash memory will stall the bus. The read operation will proceed 
correctly once the write operation has completed. This means that code 
or data fetches cannot be made while a write/erase operation is 
ongoing."

Für mich sieht das aus, als ob da doch noch Zugriffe ins Flash laufen.
Wenn ich dich richtig verstehe, kopierst du den Code zu Beginn der 
Aktion vom Flash in den RAM. Bist du sicher, dass der Code relozierbar 
ist bzw. tatsächlich für den RAM compiliert wurde? Wenn da ein 
Unterprogrammaufruf oder eine Konstante absolut angesprochen werden, war 
es das.
Die Aufrufe der StLib sind teilweise extrem verworren und die exzessive 
Nutzung von defines macht es nicht unbedingt leichter, wirklich alles zu 
finden. Ich würde mir die Map des compilierten Codes mal genauer 
anschauen und versuchen nachzuvollziehen, ob die Funktionsaufrufe auch 
wirklich alle ins RAM gehen. Ins Blaue geschossen tippe ich auf den 
Zugriff auf eine Konstante, die im Flash steht.

von STM32-User (Gast)


Lesenswert?

Hi Marvin,

Danke für die Ideen - wenn alle Stricke reißen bleibt mir wirklich nur 
übrig, nochmal das gesamte MapFile durchzuschauen.
Ich hatte bisher die (zu dem Zeitpunkt) aktiven RAM-Routinen auf 
branches in den Flash überprüft.
Hatte ne ganze Weile gedauert, dies alles "sauberzukriegen", deine 
Einschätzung zur ST-Lib kann ich also 100%ig teilen. :-)

Allerdings weiß ich nicht genau, wie es sich mit Flash-Konstanten 
verhält.
Dies muß ich nochmal gründlich überprüfen.

In der Lib gibts wirklich haufenweise Defines-  gut möglich, daß die ein 
oder andere Konstante mit bei ist.

Aber ich will nicht nur meckern- die ST-Lib ist ansonsten wenigstens 
strukturiert programmiert und man findet was man sucht (bei anderen 
Prozessoren sieht es da wesentlich schlimmer aus).

Für Deine Mühe Danke ich Dir von ganzem Herzen - jetzt habe ich 
zumindest einen Ansatz, wo ich weitersuchen kann.

Sollte dieser scheitern, werde ich meine "Analyse-routine" nutzen 
müssen,um zu detektieren, wann der kritische Zugriff vorbei ist - danach 
funktionieren die SPI cmds ja wieder.
Glücklicherweise gibt es keine Echtzeitanforderungen während des 
Updates, sodaß mir dieser letzte Ausweg noch bleibt.

Tausend Dank für deine Hilfe
der STM32-User, der nun ein fahles Licht am Ende des Tunnels sieht ;)

von Peter (Gast)


Lesenswert?

Hi,

habe das gleiche Probelm. Stall obwohl die Routienen zum SChreiben aus 
dem RAM aufgerufen werden.

Hast du den Fehler inzwischen gefunden?

VG

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.