Forum: Mikrocontroller und Digitale Elektronik Problem mit Raspberry und Interupt


von heinz (Gast)


Lesenswert?

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
    ldr pc,reset_handler
4
    ldr pc,undefined_handler
5
    ldr pc,swi_handler
6
    ldr pc,prefetch_handler
7
    ldr pc,data_handler
8
    ldr pc,unused_handler
9
    ldr pc,irq_handler
10
    ldr pc,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:      .word reset
20
undefined_handler:  .word hang
21
swi_handler:        .word hang
22
prefetch_handler:   .word hang
23
data_handler:       .word hang
24
unused_handler:     .word hang
25
irq_handler:        .word hang
26
fiq_handler:        .word irq
27
28
reset:
29
    mov r0,#0x8000
30
.
31
.
32
.
33
34
    bl notmain
35
hang: b hang
36
37
38
irq:
39
    push {r0,r1,r2,r3,r4,r5,r6,r7,lr}
40
    bl c_irq_handler
41
    pop  {r0,r1,r2,r3,r4,r5,r6,r7,lr}
42
    subs pc,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

von heinz (Gast)


Lesenswert?

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

von Thomas M. (thomil)


Lesenswert?

1
ldr pc,mein_handler

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.

von heinz (Gast)


Lesenswert?

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

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.