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.
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.
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.
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.
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 :))
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
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.
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 ;)