Forum: Compiler & IDEs Bekomme meinen ARM nicht in den Thumb-mode


von Micro M. (micromann)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche verzweifelt meinen AT91SAM7A3 in den Thumb-Mode zu zwingen.
Ich benutze den GCC 4.1.1 mit der option -mthumb-interwork.

Nun sollte doch beim bx im Startup-Code der Core in den Thumb modus 
umschalten.

Das macht er aber leider nicht.

Kann mir jemand sagen, wo mein Problem liegt ?

Ich habe mal das Starup-File angefügt.

von Unnamed (Gast)


Lesenswert?

Hi,

>  ldr  r0,=main

Hier das Bit 0 in R0 setzen (unter der Annahme
dass Dein main() bereits -mthumb-interwork'ed ist)?

>    bx  r0

von Micro M. (micromann)


Lesenswert?

So, habe es mal ausprobiert :

> ldr  r0,=main
> add  r0, # 1        // switch to Thumb-Mode
> bx  r0

Wenn ich das mache, hänge ich nach dem Sprung im undefined instruction 
oder im
Data abort Vektor.


> unter der Annahme
> dass Dein main() bereits -mthumb-interwork'ed ist

ich habe den kompletten Quelltext mit -mthumb-interwork zusammen 
kompiliert.
Dann sollte doch auch die Main bereit zum Thumb-Modus sein, richtig ?

Was läuft denn hier schief ?

von Martin Thomas (Gast)


Lesenswert?

"ich habe den kompletten Quelltext mit -mthumb-interwork zusammen
kompiliert. Dann sollte doch auch die Main bereit zum Thumb-Modus sein, 
richtig ?"
Nein, der Schalter thumb-interwork hat eine andere Funktion.

Der gezeigte Startup-Code ist in Bezug auf den Aufruf von main so o.k. 
Die Adresse der Funktion main wird in r0 geladen und dann mittels BX zu 
dieser Adresse gesprungen - egal ob diese Ziel Thumb- oder ARM-code ist, 
dies wird automatisch erkannt: das "Thumb-Bit" (LS-Bit) sagt dem 
Controller, ob das Ziel thumb- oder ARM-code enthält. Ingendwas per 
ADD#1 zu erzwingen ist falsch, wenn die Zielfunktion ARM-Code ist. Der 
Controller "schaltet" dann zwar in thumb-mode aber findet ARM-code -> 
Fehler.

Thumb-Code erzeugt man mit gcc aus C-Quellcode, indem man -mthumb als 
Option angibt. Naeheres dazu im gcc-Manual. Kurzform:

-mthumb -> erzeuge thumb-code

-mthumb-interwork -> erzeuge ARM-code aus dem thumb-code augerufen 
werden kann

-mthumb -mthumb-interwork -> erzeuge thumb-code aus dem ARM-code 
augerufen werden kann

keine Option -> erzeuge ARM-code

Vielleicht sind die makefiles aus meinen Beispielen zur Verdeutlichung 
nützlich: http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/

Hoffe, es hilft
Martin Thomas

von A.K. (Gast)


Lesenswert?

Die 1 nicht per ADD sondern per ORR erzwingen. Das stellt zumindest 
sicher, dass eine schon vorhandene 1 im LSB nicht stört.

von Martin Thomas (Gast)


Lesenswert?

Ein Bit, das gesetzt werden soll, einzuodern ist sicher besser als ein 
ADD.  Man ändert damit aber aber in diesem Anwendungsfalls nicht die Art 
des Zielcodes, sondern nur die Sprungaddrese. Die "Manipulation" der 
Addresse durch setzten von Bit 0 ist nicht nötig und darüber hinaus hier 
einfach falsch, wenn am Sprungziel  ARM-code ist (man erwingt thumb-mode 
für Anweisungen, die keine Thumb-Anweisungen sind).

Man muss nichts "herumbiegen" - zumindest musste ich das bisher dafür 
noch nie bei Verwendung der GNU-Toolchain (gcc...). Die Addresse von 
main() wird schon richtig verwaltet und gibt somit implizit bereits an, 
ob die Funktion Thumb- oder ARM-Code ist (das LS-Bit "stimmt" bereits) 
ein Sprung mit BX schaltet automatisch in den passenden Mode.

Zur Veranschaulichung (aus meinem "gamma"-Beispiel (link oben), 
Toolchain: arm-elf-gcc 4.1.1 et. al. aus meiner WinARM-Sammlung):

(1) Code von main() kompiliert mit -mthumb und -mthumb-interwork. 
Startup-Code nur mit -mthumb-interwork. Ausschnitt aus dem Disassembly:
1
[...]
2
    ldr  r0,=main
3
  1000f8:  e59f0034   ldr  r0, [pc, #52]  ; 100134 <.text+0x134>
4
    bx  r0
5
  1000fc:  e12fff10   bx  r0
6
[...]
7
 100134:  001001b5   ldreqh  r0, [r0], -r5
8
[...]
9
int main(void)
10
{
11
  1001b4:  b5b0        push  {r4, r5, r7, lr}
12
  1001b6:  4a6c        ldr  r2, [pc, #432]  (100368 <.text+0x368>)
13
  1001b8:  4b6c        ldr  r3, [pc, #432]  (10036c <.text+0x36c>)
14
[...]

Man erkennt, dass main() thumb-code ist (16-bit Anweisungen, push...) - 
wegen -mthumb. ldr, r0,=main läd die Addresse von main() als 001001b5, 
man sieht, dass Bit 0 darin gesetzt ist, somit schaltet BX den 
Controller in Thumb-Mode und springt zur Zieladdresse.

(2) Nun ein Ausschnitt, wenn alles ohne thumb/thumb-IW kompiliert wird:
1
    ldr  r0,=main
2
  1000f8:  e59f0034   ldr  r0, [pc, #52]  ; 100134 <.text+0x134>
3
    bx  r0
4
  1000fc:  e12fff10   bx  r0
5
[...]
6
  100134:  001001e0   andeqs  r0, r0, r0, ror #3
7
[...]
8
int main(void)
9
{
10
  1001e0:  e1a0c00d   mov  ip, sp
11
  1001e4:  e92dd830   stmdb  sp!, {r4, r5, fp, ip, lr, pc}
12
[...]

Hier identifiziert man den Code von main() als ARM-code (32-bit 
Anweisungen, stmdb...). Im startup-Code wird die Addresse 001001e0 
geladen, Bit 0 ist nicht gesetzt -> ARM-Mode am Sprungziel, Sprung mit 
BX schaltet in ARM-mode (oder in diesem Fall: keine Aenderung, da schon 
im ARM-Mode) und springt zu main.

Zusammenfassend: den Quellcode einfach mit der passenden Compileroption 
kompilieren (mit -mthumb oder ohen -mthumb), der Rest erledigt sich von 
alleine.

Hoffe, dies erklärt die "Angelegenheit" halbwegs verständlich.
Martin Thomas

von Micro M. (micromann)


Lesenswert?

Vielen Dank für die Antworten, besonders an Martin Thomas!

Ich denke jetzt habe ich die Sache verstanden. Leider fehlt mir nun die 
Zeit es auszuprobieren. Aber wenn es soweit ist, werde ich Ergebnisse 
melden.

Viele Grüße

von Mathias (Gast)


Lesenswert?

Nabend!

ich hätte dazu auch noch eine Frage.
Das ganze Funktioniert sehr gut mit dem Aufruf von main(). Ich konnte 
das Disassembler Listing oben bei mir nachvollziehen, tut so weit.
Allerdings kommen die folgenden Warnings: "arm-elf-ld: Warning: main.o 
does not support interworking, whereas main.elf does".

Das ist ja auch OK, aber kann ich die irgendwie unterdrücken? Mich macht 
so etwas immer nervös...
crt.s wird mit -mthumb-interwork, der Rest mit -mthumb.

Gruß
Mathias

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.