Guten Abend,
ich hab da ein Problem den Interupt Service auf dem ARM zu verstehen.
Ausgangslage ist das ich mir erstmal Beispielcode aus dem Internet
gezogen hab
https://github.com/dwelch67/raspberrypi
mit dem spiele ich jetzt rum
ARM Manual sagt wenn ein FIQ ausgelöst wird 0xqc angesprungen?
Auslöser des Interupts ist der Timer
Code der läuft
1
.globl_start
2
_start:
3
ldrpc,reset_handler
4
ldrpc,undefined_handler
5
ldrpc,swi_handler
6
ldrpc,prefetch_handler
7
ldrpc,data_handler
8
ldrpc,unused_handler
9
ldrpc,irq_handler
10
ldrpc,fiq_handler
11
12
/*
13
push {r0,r1,r2,r3,r4,r5,r6,r7,lr}
14
bl c_irq_handler
15
pop {r0,r1,r2,r3,r4,r5,r6,r7,lr}
16
subs pc,lr,#4
17
*/
18
19
reset_handler:.wordreset
20
undefined_handler:.wordhang
21
swi_handler:.wordhang
22
prefetch_handler:.wordhang
23
data_handler:.wordhang
24
unused_handler:.wordhang
25
irq_handler:.wordhang
26
fiq_handler:.wordirq
27
28
reset:
29
movr0,#0x8000
30
.
31
.
32
.
33
34
blnotmain
35
hang:bhang
36
37
38
irq:
39
push{r0,r1,r2,r3,r4,r5,r6,r7,lr}
40
blc_irq_handler
41
pop{r0,r1,r2,r3,r4,r5,r6,r7,lr}
42
subspc,lr,#4
jetzt kommentier ich die Zeile
ldr pc,fiq_handler
aus
und benutz den oben auskommentierten Code
Ergebnis ist ein Reset im Timertakt
Überseh ich da was?
Muss noch sagen dass ich ein Noob bin was ARM angeht
Gruss
Heinz
ok - dann beantworte ich meine Frage mal selbst
Beim Raspberry wird das Image ab 0x8000 geladen.
Folgt dass ich meinen FIQ handler auf 0x801c geladen hab der IRQ aber
0x1c anspringt.
Bei der source von dwelch wird der Bereich der ersten 16 Doppelwörter
nach 0x0 am Label RESET verschoben (hab ich dummerweise ausgepunktet)
Bleibt für mich aber trotzdem eine Frage
steht an
0x001c b mein_handler ; geht nicht
0x001c ldr pc,mein_handler ; geht einwandfrei
kann mir jemand sagen wieso? Für mich ist das das gleiche.
Gruss
Heinz
Sagt der CPU sie soll den Inhalt an der Adresse 'mein_handler' in PC
laden und an die geladene Adresse springen. 'mein_handler' darf also
nicht die Adresse deines wirklichen hanlders sein, sondern nur ein Word
im RAM wo die tatsächliche, volle Adresse deines Handlers steht.
Also genau so, wie du das in deinem ersten Beispiel mit fiq_handler
gemacht hast.
Deshalb kannst du das nicht einfach mit
1
b mein_handler
ersetzen, weil der branch Befehl die Adresse des handlers erwartet, und
nicht die Adresse eines Words an dem die eigentliche Adresse steht.
Möglicherweise ist dir dieser Unterschied aber schon bewusst, und du
hast nur dein Beispiel bei der Frage schlecht gewählt?
Angenommen du hättest in deinem Versuch mit dem branch Befehl das
richtige Symbol verwendet, würde es noch immer nicht funktionieren: Der
branch befehl verwendet PC relative adressierung. Der Assembler
berechnet das offset zu 'mein_handler' vom aktuellen PC in deinem code,
und generiert einen branch Befehl mit diesem Offset. Dein
Assembler/Linker glaubt jetzt aber dein Code befindet sich auf 0x801c.
Wenn du den branch Befehl jetzt nach 0x1c kopierst, ist auch der PC zum
Zeitpunkt der exception 0x1c. Das Offset das der Assembler berechnet hat
stimmt also nicht mehr, und du springst 0x8000 bytes zu kurz.
Danke.
Das Problem ist dass der Assembler/Linker den Sprung von 0x801c zum
Label berechnet und ich dann den Branch Befehl um die 0x8000 verschiebe.
Hätte ich im Dump auch sehen können (wenn ich dann geschaut hätte).
Gruss
Heinz