Hallo,
ich möchte gerne eine Interrupt Service Routine während der Laufzeit
ändern (also die aufgerufene Funktion dafür). Leider finde ich keine
Beispiele wie das gemacht wird. Ein ehemaliger Arbeitskollege hat mir
das mal erzählt, dass das bei den STM32F4 kein Problem ist. Kann mir
jemand helfen was ich dazu machen muss?
Wenn ich mich recht entsinne, kann die Interrupt-Vector-Table bei den
Teilen irgendwo im Speicher liegen und man gibt beim Setup im NVIC an,
wo die Addresse der Tabelle liegt. Wenn man also dafür sorgt, dass die
Tabeele im Ram liegt, dann müsste man auch die Vektoren zur Laufzeit
anpassen können.
Spontan hab ich zum legen der Tabelle in den RAM folgendes Beispiel
gefunden:
Beitrag "Re: STM32 -> NVIC-Setup -> Vector Table".
Grüße Oliver
Das ist mein aktueller Code, die Idee hab ich von hier
https://www.keil.com/pack/doc/CMSIS/Core/html/using_VTOR_pg.html.
Problem: Es geht nicht. Ich ändere zwar die Tabellenaddresse, aber es
scheint als hätte irgendwas nicht funktioniert.
Ich möchte folgende Interrupts verbiegen:
Systick_handler
PendSV_Handler
SVC_Handler
hat noch jemand nen Tipp?
Warum nicht über die "normale" ROM Isr einfach über function pointer und
jump table in die jeweilige gewünschte Funktion springen? Sind max. ein
paar Befehle mehr aber man kann zB Probleme leichter debuggen ;)
Das sieht alles richtig aus, bis auf die Adresse der ROM Vektortabelle:
uint32_t *vectorTable_ROM = (uint32_t)0x00000000;
Das sollte meiner Meinung nach 0x08000000 sein.
Ach ja, und die RAM-Vektortabelle muss an einer 512-Byte-Grenze liegen,
weil die unteren 9 Bit von VTOR hardwaremässig 0 sind.
Gruß, Stefan
Ruediger A. schrieb:> Du musst Bit 29 im VTOR setzen, wo codiert ist, dass die Tabelle> im SRAM> ist (sh. ARM docs).
Das geschieht automatisch, da das RAM auf Adresse 0x2000 0000 liegt.
Wichtig ist auch, dass man das entsprechende Alignment einhält.
"When setting TBLOFF, you must align the offset to the number of
exception entries in the vector table. The minimum alignment is 32
words, enough for up to 16 interrupts. For more interrupts, adjust the
alignment by rounding up to the next power of two. For example, if you
require 21 interrupts, the alignment must be on a 64-word boundary
because the required table size is 37 words, and the next power of two
is 64. See your vendor documentation for the alignment details of your
device."
Rein rechnerisch entspricht das nötige Alignment somit quasi:
1
pow2(log2(anzahl_an_vektoren))*4
Bevor man ins RAM wechselt sollte man sicher stellen, dass entweder
- alle Interrupts global abgedreht sind
oder
- alle potentiellen Vektoren bereits angelegt wurden
Springst du munter ins RAM und es ist etwa der SysTick aktiv, ohne dass
du einen entsprechenden Vektor gesetzt hast, dann krachts natürlich.
Nico W. schrieb:> Mal eine ernste Frage. Warum macht man sowas? Lerne ja gerne dazu.
Man braucht es, wenn man dynamisch andere Programme/Funktionen z.B. von
einer Speicherkarte nachladen und ausführen möchte. Beim STM32 ist das
durchaus möglich.
Bei einem älteren µC mit wenig internem RAM hatte ich die Vektoren im
RAM zu liegen. Bei der Initialisierung packten sich ISRs automatisch ins
RAM, solange Platz vorhanden war. Der Rest blieb im ROM und konnte daher
nicht so schnell laufen. Je nach verwendeter Bibliothek wurde das RAM
unterschiedlich belegt, wobei die 1. installierte ISR mit höchster
Priorität ins interne RAM kam.
Nico W. schrieb:> Mal eine ernste Frage. Warum macht man sowas? Lerne ja gerne dazu.
Wenn man einen Bootloader programmieren möchte, der komplett im RAM
laufen soll, um gleichzeitig den Flash beschreiben und andere Dinge (zB
kommunizieren) tun soll.
Danke für die Antworten. Irgendwas scheint noch nicht zu funktionieren,
aber das krieg ich jetzt auch noch hin...
Zum Einsatz: Ich muss Third-Party Code integrieren (OS). Der nutzt den
Systicker (inkl. eigener Interruptfunktion), ich habe aber in meinen
Initialisierungen Delays drinnen. Da ich nicht meinen ganzen Code
umstellen will und die Timer shcon alle in Benutzung sind, will ich zum
während des startups den Systick Interrupt umbiegen. Da ich den Third
Party Code nicht ändern darf/will/kann, ist mir das als Lösung
eingefallen.
ui schrieb:> Danke für die Antworten. Irgendwas scheint noch nicht zu funktionieren,> aber das krieg ich jetzt auch noch hin...>> Zum Einsatz: Ich muss Third-Party Code integrieren (OS). Der nutzt den> Systicker (inkl. eigener Interruptfunktion), ich habe aber in meinen> Initialisierungen Delays drinnen. Da ich nicht meinen ganzen Code> umstellen will und die Timer shcon alle in Benutzung sind, will ich zum> während des startups den Systick Interrupt umbiegen. Da ich den Third> Party Code nicht ändern darf/will/kann, ist mir das als Lösung> eingefallen.
Mit dem Umlegen der IVT ins RAM gibt es eigentlich keine Probleme, und
der Code ist recht straightforward. Warum es trotzdem nicht klappt, ist
zweifellos ein Detailproblem. Sieh mal auf
http://www.springer.com/de/book/9783658148492 - Zusatzmaterial, da sind
gezippt und für Jedermann/frau kostenlos downloadbar Codebeispiele drauf
(Kapitel 9/Bootloader benutzt genau diesen Mechanismus).
Für deine Problemstellung kannst Du auch mal zum Stichwort FBP gockeln.
Der Cortex Core hat nämlich einen Patchmechanismus bereits integriert.
Wenn Du die Möglichkeit hast, direkt an der main() anzusetzen, kannst Du
da ansetzen und den Code patchen, bevor der SysTick Handler anfängt zu
laufen.
ui schrieb:> Danke für die Antworten. Irgendwas scheint noch nicht zu funktionieren,> aber das krieg ich jetzt auch noch hin...>> Zum Einsatz: Ich muss Third-Party Code integrieren (OS). Der nutzt den> Systicker (inkl. eigener Interruptfunktion), ich habe aber in meinen> Initialisierungen Delays drinnen. Da ich nicht meinen ganzen Code> umstellen will und die Timer shcon alle in Benutzung sind, will ich zum> während des startups den Systick Interrupt umbiegen. Da ich den Third> Party Code nicht ändern darf/will/kann, ist mir das als Lösung> eingefallen.
Der SysTick(ISR) des OS muss in deiner Vektortabelle festgelegt. D.H. du
könntest auch weiterhin deinen SysTick aufrufen und von dort auch
entsprechend steuern, was wann und wie aufgerufen wird. Das wäre die
quick & dirty Lösung.
Alternativ könntest du es auch sauber machen und das OS zuerst
hochstarten und die ganzen Initialisierungen dort in Tasks durchführen,
wodurch die Delays vom OS sauber gemanaged werden ohne das System zu
blockieren.
Aber Softwaredesign scheint heute niemanden mehr zu interessieren, da
sucht man sich lieber grässliche Workarounds die nicht mal wie gewünscht
funktionieren und nur Probleme machen...
mfg
> #define VECTORTABLE_ALIGN (0x100ul)
Tendenziell würde ich auf 0x200 tippen. Kommt natürlich af das jeweilige
Derivat drauf an.
> Das ist mein aktueller Code, die Idee hab ich von hier> https://www.keil.com/pack/doc/CMSIS/Core/html/using_VTOR_pg.html.> Problem: Es geht nicht. Ich ändere zwar die Tabellenaddresse, aber es> scheint als hätte irgendwas nicht funktioniert.> Ich möchte folgende Interrupts verbiegen:> Systick_handler> PendSV_Handler> SVC_Handler
Falls du die CMSIS nutzt, prüfe am besten, ob sie tut, was du erwartest.
Hier wird teilweise zwischen Trap und Interrupt unterschieden.
Teilweise wird im startup code speziell OS Thrd Party Code auch an der
vector table Adresse herumgeschraubt. Insofern wäre zu prüfen, ob deine
Änderungen erhalten bleiben.
> hat noch jemand nen Tipp?
Wenn du konkreter beschreiben würdest, was nicht geht...
Hatte gestern keine Zeit mehr zu antworten:
Es funktioniert jetzt alles, ich hatte gestern noch ein paar krude
Probleme mit dem Debugger...
Aber jetzt macht er genau das was ich will :)
Danke an alle hilfreichen Antworten, man kriegt ja doch (wenn es auch
immer nur ein Teil der Antworten ist) vernünftige Antworten.
Felix F. schrieb:> Der SysTick(ISR) des OS muss in deiner Vektortabelle festgelegt. D.H. du> könntest auch weiterhin deinen SysTick aufrufen und von dort auch> entsprechend steuern, was wann und wie aufgerufen wird. Das wäre die> quick & dirty Lösung.>> Alternativ könntest du es auch sauber machen und das OS zuerst> hochstarten und die ganzen Initialisierungen dort in Tasks durchführen,> wodurch die Delays vom OS sauber gemanaged werden ohne das System zu> blockieren.>> Aber Softwaredesign scheint heute niemanden mehr zu interessieren, da> sucht man sich lieber grässliche Workarounds die nicht mal wie gewünscht> funktionieren und nur Probleme machen...
Ich finde es vom Softwaredesign überhaupt nicht schön das OS zu starten
bevor die Hardware (alles) richtig funktioniert. Auch ist die
Fehlerbehandlung dann einfacher.
Ich finde den Workaround überhaupt nicht grässlich. Auch Kollegen von
mir finden das nicht grässlich, und die müssen das pflegen wenn ich
nicht mehr da bin.
Zu guter letzt ist es auch so, dass Softwaredesign im gesamten Kontext
betrachtet werden muss. Da ich den aber nicht offenlegen kann/darf,
kannst du überhaupt nicht beurteilen ob das in diesem Szenario gut so
ist. (Das war einer der Kommentare, auf die man getrost verzichten
kann!)