Hi,
ich verwende ein STM32F4 Board mit FreeRTOS und ich versuche gerade,
mein Assembler etwas zu verbessern.
unsigned int my_pc = 0x08000890;
_asm __volatile_
(
"movw R1, #0x0fd0\n"
"movt R1, #0x1000\n"
"ldr r15,[r1]\n"
);
Ich speichere in my_pc einen gewünschen, neuen Program-Counter. Der Wert
0x08... ist der PC an der Stelle unsigned int my_pc. Dannach lade ich
mir diesen Wert in Register R1 - dabei ist 0x10000fd0 die Adresse im
Speicher, wo my_pc liegt. Nun möchte ich meinen tatsächlichen PC
abändern, sodass ich erneut bei unsigned int my_pc lande.
Mit gdb habe ich rausgefunden, dass ich R1 nun tatsächlich 0x10000fd0
steht. Allerdings komme ich hier in den Trap handler:
prvGetRegistersFromStack (pulFaultStackAddress=0x10000f90
Wieso stimmt die Adresse nicht überein?
Verwende ich nun diesen Code, funktioniert mein Vorhaben wie gewünscht:
unsigned int my_pc = 0x08000890;
_asm __volatile_
(
"movw R1, #0x0fd0\n"
"movt R1, #0x1000\n"
"ldr r4,[r1]\n"
"mov pc,r4\n"
);
Wo liegt hier das Problem?
Das unterste Bit der Adresse muss 1 sein, sonst weist du den Prozessor
an, in den ARM-Modus zu wechseln, was der Cortex-M4 nicht kann. Ich
würde dir empfehlen, erstmal nur mit nacktem Assembler anzufangen, weil
Inline Assembler noch eine ganze Reihe an Tücken hat und auch noch
schlecht dokumentiert ist.
PS: Direkt in den PC eine Adresse zu schreiben ist etwas unüblich und
hat gewisse Einschränkungen - normalerweise nimmt man dafür die
Branch-Anweisung "B".
Auf einem Cortex-M kann man keinen graden Wert in den PC laden =>
Thumb-Bit muss gesetzt sein, sonst Fault.
In der Version die funktionier muss also noch was anders sein.
Noch eine Kleinigkeit: Der Wert im PC selbst ist grade, wenn man den
ausliesst. Die "push PC" und BL/BLX Instruktionen handhaben das mit dem
Thumb Bit korrekt AFAIK (so das man den Wert hinterher einlesen kann,
Bit 0 hat den Wert 1).
Jim M. schrieb:> In der Version die funktionier muss also noch was anders sein.
Bei manchen Schreib-Operationen auf den PC wird das Thumb Bit ignoriert,
und der aktuelle Modus beibehalten. Welche das sind kann ich mir aber
auch nicht merken :)
"B" schaltet nicht um, "BX" schon, und nur letzteres kann man mit
Registern als Ziel nutzen.
kilaz schrieb:> unsigned int my_pc = 0x08000890;> _asm __volatile_> (> "movw R1, #0x0fd0\n"> "movt R1, #0x1000\n"> "ldr r15,[r1]\n"> );
Das kann (neben dem schon erwähnten Thumb-Bit) gut gehen oder auch nicht
(je nachdem, was sonst noch an C-Code aussenrum ist).
Wenn Du dem C-Compiler Register klaust, ohne ihm das mitzuteilen, geht
das früher oder später schief. Lies' dir das Kapitel "extended asm" im
gcc-Handbuch aufmerksam durch.
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang