Hallo, heißt das (siehe Anhang), dass der Cortex M3 die Prozessorregister in Hardware pusht (innerhalb wievieler Taktzyklen?) oder muss ich das in Software noch machen? Grüße
Das ARM v7-M Architecture Reference Manual (DDI 0403E.d) sagt dazu: "B1.5.6 Exception entry behavior [...] When pushing context to the stack, the hardware saves eight 32-bit words, comprising xPSR, ReturnAddress, LR (R14), R12, R3, R2, R1, and R0."
Beitrag #5794282 wurde vom Autor gelöscht.
Leopold N. schrieb: > innerhalb wievieler Taktzyklen? Im Cortex-M3 Technical Reference Manual (s.u.) steht auf S. 3-45: To reduce interrupt latency, the processor implements both interrupt late-arrival and interrupt tail-chaining mechanisms, as defined by the ARMv7-M architecture: - There is a maximum of a twelve cycle latency from asserting the interrupt to execution of the firstinstruction of the ISR when the memory being accessed has no wait states being applied. The firstinstruction to be executed is fetched in parallel to the stack push. - Returns from interrupts similarly take twelve cycles where the instruction being returned to is fetchedin parallel to the stack pop. - Tail chaining requires six cycles when using zero wait state memory. No stack pushes or pops areperformed and only the instruction for the next ISR is fetched. https://developer.arm.com/docs/100165/0201
Aber konkret heißt das, dass ich in der ISR (bzw. der Compiler) keine push oder pop Anweisungen zum Sichern der Prozessorregister einfügen muss oder?
Leopold N. schrieb: > Aber konkret heißt das, dass ich in der ISR (bzw. der Compiler) keine > push oder pop Anweisungen zum Sichern der Prozessorregister einfügen > muss oder? Doch, wenn du mehr als die 5 Register r0-r4, r12 nutzt oder weitere Funktionen aufrufst (LR / r14).
Niklas G. schrieb: > Leopold N. schrieb: >> Aber konkret heißt das, dass ich in der ISR (bzw. der Compiler) keine >> push oder pop Anweisungen zum Sichern der Prozessorregister einfügen >> muss oder? > > Doch, wenn du mehr als die 5 Register r0-r4, r12 nutzt oder weitere > Funktionen aufrufst (LR / r14). Ok, aber die Register R0, R1, R2, R3, R12, R14, R15 und PSR pusht der Prozessor selbst automatisch richtig? Ich muss mich also um R4, R5, R6, R7, R8, R9, R10, R11, R13 und R14 (sofern ich weitere Funktionen aufrufe) kümmern.
r13 (SP) nicht unbedingt, wenn du damit nicht spezielles machst kannst du den auch ganz normal verwenden. Man kann auch separate Stacks für ISRs und mainloop nutzen (PSP vs. MSP). Ansonsten stimmts.
Noch eine Frage, beim Eintritt in eine ISR pusht der Cortex M3 in Hardware ja 8 Register. Wie lange dauert der gesamte Eintritt in Zyklen? Dasselbe für den Austritt. Außerdem: Wieviele Zyklen nimmt ein push / pop Befehl in Anspruch? Hab dazu nur das hier gefunden, bin mir aber nicht sicher, ob ich N = 1 oder N = 0 gilt. Edit: Sry 2mal das gleiche angehängt. Hab ich vom ARM Information Center Grüße
:
Bearbeitet durch User
Wie am 2.4. schon geschrieben: 12 Takte. N=1, weil jede Load/Store Instruktion mind. 2 Takte braucht. Es kommt aber ggf. noch Latenz für Flash Zugriff drauf.
Leopold N. schrieb: > Noch eine Frage, > > beim Eintritt in eine ISR pusht der Cortex M3 in Hardware ja 8 Register. > Wie lange dauert der gesamte Eintritt in Zyklen? > Dasselbe für den Austritt. > > Außerdem: Wieviele Zyklen nimmt ein push / pop Befehl in Anspruch? > Hab dazu nur das hier gefunden, bin mir aber nicht sicher, ob ich N = 1 > oder N = 0 gilt. > > Edit: Sry 2mal das gleiche angehängt. Hab ich vom ARM Information Center > > Grüße Kannst Du nicht zumindestens den pop mit Hilfe des DWT cycle Counters selbst ausmessen (viele IDEs haben da sogar plugins, die für Dich zählen)? Ich habe gerade mal einen Test gemacht: Im Laufenden Betrieb einen bp auf eine pop instruction gesetzt und den DWT cycle Counter (0xe0001004) vorher und nachher ausgelesen (natürlich mit Vorsicht zu geniessen, da das Auslesen selber nach dem step vermutlich auch noch Zklaen verbrät; ich kenne die IDE nicht gut genug um zu wissen ob das in den Zähler mit einfliesst). Delta 6 in meinem Fall. Am genauesten wäre natürlich ein zyklengenauer trace.
Gemäß dem Buch von Joseph Yiu, sind es mindestens 12 Takte (inclusive vector fetch und register stacking). Häufig ist es aber mehr, wegen diverser Wait States/Flash Latency (auch von der vorherigen Operation). Für die FPU bei Cortex M4 kommen weitere 12 Takte dazu, um Speicherplatz für das lazy-stacking der FPU Register zu reservieren. Wirklich gesichert werden sie erst später, falls sie tatsächlich verwendet werden, was innerhalb der ISR weitere Takte in Anspruch nimmt. Das Buch gibt es hier kostenlos: https://www.eecs.umich.edu/courses/eecs373/labs/refs/M3%20Guide.pdf
Das schöne am NVIC-"Stacking" ist, daß die Hardware genau das macht, was nach ARM-Calling-Convention auch beim Aufruf einer Funktion gemacht werden müßte, d.h. eine ISR ist genau so zu "bauen", wie jede andere C-Funktion. Es sind keine Spezialattribute wie "ISR", etc. notwendig.
Ok danke, ich habe inzwischen herausgefunden, dass mein Debugger einen Cyclecounter hat... push, bzw pop benötigen zwei Takte. Niklas G. schrieb: > Darf man fragen, was du entwickelst, das so super zeitkritisch > ist? RTOS, der Kontextswitch sollte möglichst schlank sein.
Leopold N. schrieb: > RTOS, der Kontextswitch sollte möglichst schlank sein. Ach! Dann musst du aber sowieso alle Register sichern, egal wie lange es dauert. Die FPU-Register kann man ggf. "lazy" sichern.
Der Cortex M3 hat keine FPU, sorry falls ich diesbezüglich Verwirrung gestiftet habe.
Niklas G. schrieb: > Leopold N. schrieb: >> RTOS, der Kontextswitch sollte möglichst schlank sein. > > Ach! Dann musst du aber sowieso alle Register sichern, egal wie lange es > dauert. Die FPU-Register kann man ggf. "lazy" sichern. Ja ist mir schon klar, läuft auch alles schon...wollte nur mal grob nachrechnen, wieviele Zyklen das Ganze in Anspruch nimmt. Stefanus F. schrieb: > Der Cortex M3 hat keine FPU, sorry falls ich diesbezüglich > Verwirrung > gestiftet habe. Nicht schlimm, dass wusste ich schon :) Noch eine Frage: Ich habe in Inline Assembler eine Berechnung ausgeführt, deren Ergebnis in R0 steht. An diesem Punkt würde ich gerne mit C weitermachen unter Verwendung des Inline Assembler Rechenergebnisses in R0, also eine Variable deklarieren, deren Inhalt in R0 (und somit dem Rechenergebnis) steht. Das geht doch mit dem Keyword "register" oder? Aber wie mach ich dem IAR Compiler klar, dass der "Speicherort" R0 ist?
Leopold N. schrieb: > Ja ist mir schon klar, läuft auch alles schon...wollte nur mal grob > nachrechnen, wieviele Zyklen das Ganze in Anspruch nimmt. Messen hilft! Am Besten mit Pins die man toggelt, das kann man dann präzise in Echtzeit mit Oszilloskop oder LA messen. Leopold N. schrieb: > Das geht doch mit dem Keyword "register" oder? Das ist eigentlich für was anderes und wird nicht mehr verwendet. Leopold N. schrieb: > Aber wie mach ich dem IAR Compiler klar, dass der "Speicherort" R0 ist? Beim GCC ist das so, dass man sich vom Compiler ein Register geben lässt und dieses im Inline Assembler nutzt. Für den IAR musst du in dessen Doku nachsehen wie das geht... Für den GCC könnte ich empfehlen: https://hardwarebug.org/2010/07/06/arm-inline-asm-secrets/ http://www.ethernut.de/en/documents/arm-inline-asm.html
Leopold N. schrieb: > Ok danke, > > ich habe inzwischen herausgefunden, dass mein Debugger einen > Cyclecounter hat... push, bzw pop benötigen zwei Takte. > > Niklas G. schrieb: >> Darf man fragen, was du entwickelst, das so super zeitkritisch >> ist? > > RTOS, der Kontextswitch sollte möglichst schlank sein. Dann such mal nach "M3 pendsv Contextswitch". Die Dinger haben noch mehr Support für so was.
Leopold N. schrieb: > > > Noch eine Frage: > Ich habe in Inline Assembler eine Berechnung ausgeführt, deren Ergebnis > in R0 steht. > An diesem Punkt würde ich gerne mit C weitermachen unter Verwendung des > Inline Assembler Rechenergebnisses in R0, also eine Variable > deklarieren, deren Inhalt in R0 (und somit dem Rechenergebnis) steht. > Das geht doch mit dem Keyword "register" oder? > Aber wie mach ich dem IAR Compiler klar, dass der "Speicherort" R0 ist? Einfacher wäre es in diesem Fall, das Ganze nicht inzulinen, sondern als Funktion in Assembler zu schreiben (lt. AAPCS werden Funktionsreturns immer in R0 zurückgegeben, d.h. wenn Du in C eine Funktion aufrufst, wird die aufrufende Funktion automatisch davon ausgehen, dass das Ergebnis in R0 steht, egal ob die aufgerufen Funktion in C oder Assembler geschrieben ist). Vielleicht (!) kannst Du das Ganze dann von Hinten durch die Brust ins Auge wieder so hinbiegen, dass Du deine Assemblerfunktion zwar als eigenständige Funktion schreibst, aber mit attribute inline wieder in den Code einarbeitest. Das ist aber sehr stark Conpilerabhängig und kann je nach Optimierungsstufen oder anderen Faktoren auch mal wieder in einen tatsächlichen Funktionsaufruf übersetzt werden.
Carl D. schrieb: > Das schöne am NVIC-"Stacking" ist Ja der Cortex-M ist für sicherheitskritische ISR ganz toll: langsam und wenn der Stack ungültig wird sofort Hardfault. Daher gibt es immer noch den Cortex-R mit klassischer FIQ ISR als Alternative. Die dann in ASM realisiert werden muss. Noch besser wäre ein Cortex der wie 8051 mehrere ganze Registerbänke hätte, oder wenigstens je eine für USR und ISR
Lothar schrieb: > Carl D. schrieb: >> Das schöne am NVIC-"Stacking" ist > > Ja der Cortex-M ist für sicherheitskritische ISR ganz toll: langsam und > wenn der Stack ungültig wird sofort Hardfault. > > Daher gibt es immer noch den Cortex-R mit klassischer FIQ ISR als > Alternative. Die dann in ASM realisiert werden muss. > > Noch besser wäre ein Cortex der wie 8051 mehrere ganze Registerbänke > hätte, oder wenigstens je eine für USR und ISR Wenn der Stackpointer ungültig wird, geht sowieso nichts mehr.
Stefanus F. schrieb: > Wenn der Stackpointer ungültig wird, geht sowieso nichts mehr. Es gibt Architekturen, die auch solche Fehler überleben können. Protected mode x86 beispielsweise, via Task Gate - braucht dann aber ein paar Takte länger.
:
Bearbeitet durch User
Stefanus F. schrieb: > Wenn der Stackpointer ungültig wird, geht sowieso nichts mehr Cortex-A und Cortex-R landen dann bei FIQ ISR in einer eigenen "halben" Registerbank R8-R12 und Cortex-M landet dank Autostacking nirgends.
Lothar schrieb: >> Wenn der Stackpointer ungültig wird, geht sowieso nichts mehr > > Cortex-A und Cortex-R landen dann bei FIQ ISR in einer eigenen "halben" > Registerbank R8-R12 und Cortex-M landet dank Autostacking nirgends. Cortex M landet dann im HardFault Handler. Man sollte darin also nicht blind davon ausgehen, dass der Stack lesbar ist.
:
Bearbeitet durch User
Stefanus F. schrieb: > Das Buch gibt es hier kostenlos: > https://www.eecs.umich.edu/courses/eecs373/labs/refs/M3%20Guide.pdf Danke! Das Ding liegt bei mir auf dem Tisch und scheint wirklich gebrauchbar zu sein...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.