I am trying to get interrupts to work on an ARM processor using QEMU. I have tried Google and various attempts to solve it, but I cannot get my IRQ handler to be called.
I also tried keyboard interrupts, which did not work either. I think the book I have may have a few mistakes, as the UART driver ended up being slightly different than described.
My assembly code:
.code 32
.global start, vectors_start, vectors_end, lock, unlock
start:
LDR sp, =stack_top
BL copy_vector
MSR cpsr, #0x92
LDR sp, =irq_stack_top
MSR cpsr, #0x13
bl unlock
BL main
B .
irq_handler:
sub lr, lr, #4
stmfd sp!, {r0-r12, lr}
bl IRQ_handler
ldmfd sp!, {r0-r12, pc}^
vectors_start:
LDR PC, reset_handler_addr
LDR PC, undef_handler_addr
LDR PC, swi_handler_addr
LDR PC, prefetch_abort_handler_addr
LDR PC, data_abort_handler_addr
B .
LDR PC, irq_handler_addr
LDR PC, fiq_handler_addr
reset_handler_addr: .word start
undef_handler_addr: .word undef_handler
swi_handler_addr: .word swi_handler
prefetch_abort_handler_addr: .word prefetch_abort_handler
data_abort_handler_addr: .word data_abort_handler
irq_handler_addr: .word irq_handler
fiq_handler_addr: .word fiq_handler
vectors_end:
lock:
MRS r0, CPSR
ORR r0,r0,#0x80
MSR CPSR, r0
mov PC, lr
unlock:
MRS r0,CPSR
BIC r0,r0,#0x80
MSR CPSR, r0
mov PC, lr
Relevant C functions:
void copy_vector(void){
extern u32 vectors_start, vectors_end;
u32 *vectors_src = &vectors_start;
u32 *vectors_dst = (u32 *) 0;
while (vectors_src<&vectors_end){
*vectors_dst++ = *vectors_src++;
}
}
// this function has been modified somewhat because the book was incomplete
// the print statement never prints
void IRQ_handler(void){
int vicstatus = 0;
uprints(uarts,"in interupt");
// int vicstatus = 0;
if(1){
if(*(tp[0]->base+TVALUE)==0){
timer_handler(0);
}
if(*(tp[1]->base+TVALUE)==0){
timer_handler(1);
}
}
if( 1){
if(*(tp[2]->base+TVALUE)==0){
timer_handler(2);
}
if(*(tp[3]->base+TVALUE)==0){
timer_handler(3);
}
}
}
void timer_init()
{
// timers[0].base = (u32*) 0x101E2000;
// timers[1].base = (u32*) 0x101E2020;
// timers[2].base = (u32*) 0x101E3000;
// timers[3].base = (u32*) 0x101E3020;
int i; TIMER * tp;
for (i = 0; i<4; ++i){
tp = &timers[i];
if(i==0) tp->base = (u32*) 0x101E2000;
if(i==1) tp->base = (u32*) 0x101E2020;
if (i == 2) tp->base = (u32*) 0x101E3000;
if (i == 3) tp->base = (u32*) 0x101E3020;
*(tp->base+TLOAD) = 0x0;
*(tp->base+TVALUE) = 0xFFFFFFFF;
*(tp->base+TRIS) = 0x0;
*(tp->base+TMIS) = 0x0;
*(tp->base+TLOAD) = 0x100;
*(tp->base+TCNTL) = 0x66;
*(tp->base+TBGLOAD) = 0x1C00;
*(tp->base ) |= (unsigned int)(1<<6);
tp->tick = 0;
///uprints(uarts,"timer init");
}
}
When I reset the machine in QEMU I get the message Timer with delta zero disabling.
I can get the message to disappear by changing: *(tp->base+TLOAD) = 0x0;
to *(tp->base+TLOAD) = 0x1; but the timer still doesn't work.
Lastly, my build script is:
arm-none-eabi-as -o start3.o start3.s
arm-none-eabi-gcc -c main3.c
arm-none-eabi-ld -T t.ld -o start3.elf start3.o main3.o
arm-none-eabi-nm start3.elf
arm-none-eabi-objcopy -O binary start3.elf start3.bin
qemu-system-arm -M versatilepb -m 128M -kernel start3.bin
edit: in addition here is the disassembled code from my main.c file (which includes a few other c files for the drivers)
the board is the versatilepb which according to the docs emulates the following:
ARM926E, ARM1136 or Cortex-A8 CPU
00000000 <uart_init>:
0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4: e28db000 add fp, sp, #0
8: e24dd00c sub sp, sp, #12
c: e3a03000 mov r3, #0
10: e50b3008 str r3, [fp, #-8]
14: ea000011 b 60 <uart_init+0x60>
18: e51b3008 ldr r3, [fp, #-8]
1c: e1a03183 lsl r3, r3, #3
20: e59f2064 ldr r2, [pc, #100] ; 8c <uart_init+0x8c>
24: e0833002 add r3, r3, r2
28: e50b300c str r3, [fp, #-12]
2c: e51b2008 ldr r2, [fp, #-8]
30: e59f3058 ldr r3, [pc, #88] ; 90 <uart_init+0x90>
34: e0823003 add r3, r2, r3
38: e1a03603 lsl r3, r3, #12
3c: e1a02003 mov r2, r3
40: e51b300c ldr r3, [fp, #-12]
44: e5832000 str r2, [r3]
48: e51b300c ldr r3, [fp, #-12]
4c: e51b2008 ldr r2, [fp, #-8]
50: e5832004 str r2, [r3, #4]
54: e51b3008 ldr r3, [fp, #-8]
58: e2833001 add r3, r3, #1
5c: e50b3008 str r3, [fp, #-8]
60: e51b3008 ldr r3, [fp, #-8]
64: e3530003 cmp r3, #3
68: daffffea ble 18 <uart_init+0x18>
6c: e59f3018 ldr r3, [pc, #24] ; 8c <uart_init+0x8c>
70: e59f201c ldr r2, [pc, #28] ; 94 <uart_init+0x94>
74: e5832018 str r2, [r3, #24]
78: e1a00000 nop ; (mov r0, r0)
7c: e1a00003 mov r0, r3
80: e28bd000 add sp, fp, #0
84: e49db004 pop {fp} ; (ldr fp, [sp], #4)
88: e12fff1e bx lr
8c: 00000000 .word 0x00000000
90: 000101f1 .word 0x000101f1
94: 10009000 .word 0x10009000
00000098 <ugetc>:
98: e52db004 push {fp} ; (str fp, [sp, #-4]!)
9c: e28db000 add fp, sp, #0
a0: e24dd00c sub sp, sp, #12
a4: e50b0008 str r0, [fp, #-8]
a8: e1a00000 nop ; (mov r0, r0)
ac: e51b3008 ldr r3, [fp, #-8]
b0: e5933000 ldr r3, [r3]
b4: e2833018 add r3, r3, #24
b8: e5d33000 ldrb r3, [r3]
bc: e2033010 and r3, r3, #16
c0: e3530000 cmp r3, #0
c4: 1afffff8 bne ac <ugetc+0x14>
c8: e51b3008 ldr r3, [fp, #-8]
cc: e5933000 ldr r3, [r3]
d0: e5d33000 ldrb r3, [r3]
d4: e1a00003 mov r0, r3
d8: e28bd000 add sp, fp, #0
dc: e49db004 pop {fp} ; (ldr fp, [sp], #4)
e0: e12fff1e bx lr
000000e4 <uputc>:
e4: e52db004 push {fp} ; (str fp, [sp, #-4]!)
e8: e28db000 add fp, sp, #0
ec: e24dd00c sub sp, sp, #12
f0: e50b0008 str r0, [fp, #-8]
f4: e1a03001 mov r3, r1
f8: e54b3009 strb r3, [fp, #-9]
fc: e1a00000 nop ; (mov r0, r0)
100: e51b3008 ldr r3, [fp, #-8]
104: e5933000 ldr r3, [r3]
108: e2833018 add r3, r3, #24
10c: e5d33000 ldrb r3, [r3]
110: e2033020 and r3, r3, #32
114: e3530000 cmp r3, #0
118: 1afffff8 bne 100 <uputc+0x1c>
11c: e51b3008 ldr r3, [fp, #-8]
120: e5933000 ldr r3, [r3]
124: e55b2009 ldrb r2, [fp, #-9]
128: e5c32000 strb r2, [r3]
12c: e1a00000 nop ; (mov r0, r0)
130: e1a00003 mov r0, r3
134: e28bd000 add sp, fp, #0
138: e49db004 pop {fp} ; (ldr fp, [sp], #4)
13c: e12fff1e bx lr
00000140 <ugets>:
140: e92d4800 push {fp, lr}
144: e28db004 add fp, sp, #4
148: e24dd008 sub sp, sp, #8
14c: e50b0008 str r0, [fp, #-8]
150: e50b100c str r1, [fp, #-12]
154: ea000007 b 178 <ugets+0x38>
158: e51b300c ldr r3, [fp, #-12]
15c: e5d33000 ldrb r3, [r3]
160: e1a01003 mov r1, r3
164: e51b0008 ldr r0, [fp, #-8]
168: ebfffffe bl e4 <uputc>
16c: e51b300c ldr r3, [fp, #-12]
170: e2833001 add r3, r3, #1
174: e50b300c str r3, [fp, #-12]
178: e51b0008 ldr r0, [fp, #-8]
17c: ebfffffe bl 98 <ugetc>
180: e1a03000 mov r3, r0
184: e20320ff and r2, r3, #255 ; 0xff
188: e51b300c ldr r3, [fp, #-12]
18c: e5c32000 strb r2, [r3]
190: e51b300c ldr r3, [fp, #-12]
194: e5d33000 ldrb r3, [r3]
198: e353000d cmp r3, #13
19c: 1affffed bne 158 <ugets+0x18>
1a0: e51b300c ldr r3, [fp, #-12]
1a4: e3a02000 mov r2, #0
1a8: e5c32000 strb r2, [r3]
1ac: e1a00000 nop ; (mov r0, r0)
1b0: e1a00003 mov r0, r3
1b4: e24bd004 sub sp, fp, #4
1b8: e8bd4800 pop {fp, lr}
1bc: e12fff1e bx lr
000001c0 <uprints>:
1c0: e92d4800 push {fp, lr}
1c4: e28db004 add fp, sp, #4
1c8: e24dd008 sub sp, sp, #8
1cc: e50b0008 str r0, [fp, #-8]
1d0: e50b100c str r1, [fp, #-12]
1d4: ea000006 b 1f4 <uprints+0x34>
1d8: e51b300c ldr r3, [fp, #-12]
1dc: e2832001 add r2, r3, #1
1e0: e50b200c str r2, [fp, #-12]
1e4: e5d33000 ldrb r3, [r3]
1e8: e1a01003 mov r1, r3
1ec: e51b0008 ldr r0, [fp, #-8]
1f0: ebfffffe bl e4 <uputc>
1f4: e51b300c ldr r3, [fp, #-12]
1f8: e5d33000 ldrb r3, [r3]
1fc: e3530000 cmp r3, #0
200: 1afffff4 bne 1d8 <uprints+0x18>
204: e1a00000 nop ; (mov r0, r0)
208: e1a00003 mov r0, r3
20c: e24bd004 sub sp, fp, #4
210: e8bd4800 pop {fp, lr}
214: e12fff1e bx lr
00000218 <fbuf_init>:
218: e52db004 push {fp} ; (str fp, [sp, #-4]!)
21c: e28db000 add fp, sp, #0
220: e59f3060 ldr r3, [pc, #96] ; 288 <fbuf_init+0x70>
224: e3a02602 mov r2, #2097152 ; 0x200000
228: e5832000 str r2, [r3]
22c: e59f3058 ldr r3, [pc, #88] ; 28c <fbuf_init+0x74>
230: e59f2058 ldr r2, [pc, #88] ; 290 <fbuf_init+0x78>
234: e5832000 str r2, [r3]
238: e59f3054 ldr r3, [pc, #84] ; 294 <fbuf_init+0x7c>
23c: e59f2054 ldr r2, [pc, #84] ; 298 <fbuf_init+0x80>
240: e5832000 str r2, [r3]
244: e59f3050 ldr r3, [pc, #80] ; 29c <fbuf_init+0x84>
248: e59f2050 ldr r2, [pc, #80] ; 2a0 <fbuf_init+0x88>
24c: e5832000 str r2, [r3]
250: e59f304c ldr r3, [pc, #76] ; 2a4 <fbuf_init+0x8c>
254: e59f204c ldr r2, [pc, #76] ; 2a8 <fbuf_init+0x90>
258: e5832000 str r2, [r3]
25c: e59f3048 ldr r3, [pc, #72] ; 2ac <fbuf_init+0x94>
260: e3a02602 mov r2, #2097152 ; 0x200000
264: e5832000 str r2, [r3]
268: e59f3040 ldr r3, [pc, #64] ; 2b0 <fbuf_init+0x98>
26c: e59f2040 ldr r2, [pc, #64] ; 2b4 <fbuf_init+0x9c>
270: e5832000 str r2, [r3]
274: e1a00000 nop ; (mov r0, r0)
278: e1a00003 mov r0, r3
27c: e28bd000 add sp, fp, #0
280: e49db004 pop {fp} ; (ldr fp, [sp], #4)
284: e12fff1e bx lr
288: 00000000 .word 0x00000000
28c: 1000001c .word 0x1000001c
290: 00002c77 .word 0x00002c77
294: 10120000 .word 0x10120000
298: 3f1f3f9c .word 0x3f1f3f9c
29c: 10120004 .word 0x10120004
2a0: 090b61df .word 0x090b61df
2a4: 10120008 .word 0x10120008
2a8: 071f1800 .word 0x071f1800
2ac: 10120010 .word 0x10120010
2b0: 10120018 .word 0x10120018
2b4: 0000082b .word 0x0000082b
000002b8 <draw_box>:
2b8: e52db004 push {fp} ; (str fp, [sp, #-4]!)
2bc: e28db000 add fp, sp, #0
2c0: e24dd01c sub sp, sp, #28
2c4: e50b0010 str r0, [fp, #-16]
2c8: e50b1014 str r1, [fp, #-20] ; 0xffffffec
2cc: e50b2018 str r2, [fp, #-24] ; 0xffffffe8
2d0: e50b301c str r3, [fp, #-28] ; 0xffffffe4
2d4: e3a03000 mov r3, #0
2d8: e50b3008 str r3, [fp, #-8]
2dc: ea00001c b 354 <draw_box+0x9c>
2e0: e3a03000 mov r3, #0
2e4: e50b300c str r3, [fp, #-12]
2e8: ea000012 b 338 <draw_box+0x80>
2ec: e59f3084 ldr r3, [pc, #132] ; 378 <draw_box+0xc0>
2f0: e5932000 ldr r2, [r3]
2f4: e51b100c ldr r1, [fp, #-12]
2f8: e51b3014 ldr r3, [fp, #-20] ; 0xffffffec
2fc: e0813003 add r3, r1, r3
300: e59f1074 ldr r1, [pc, #116] ; 37c <draw_box+0xc4>
304: e5911000 ldr r1, [r1]
308: e0010193 mul r1, r3, r1
30c: e51b3008 ldr r3, [fp, #-8]
310: e0811003 add r1, r1, r3
314: e51b3010 ldr r3, [fp, #-16]
318: e0813003 add r3, r1, r3
31c: e1a03103 lsl r3, r3, #2
320: e0823003 add r3, r2, r3
324: e51b201c ldr r2, [fp, #-28] ; 0xffffffe4
328: e5832000 str r2, [r3]
32c: e51b300c ldr r3, [fp, #-12]
330: e2833001 add r3, r3, #1
334: e50b300c str r3, [fp, #-12]
338: e51b200c ldr r2, [fp, #-12]
33c: e51b3018 ldr r3, [fp, #-24] ; 0xffffffe8
340: e1520003 cmp r2, r3
344: baffffe8 blt 2ec <draw_box+0x34>
348: e51b3008 ldr r3, [fp, #-8]
34c: e2833001 add r3, r3, #1
350: e50b3008 str r3, [fp, #-8]
354: e51b2008 ldr r2, [fp, #-8]
358: e51b3018 ldr r3, [fp, #-24] ; 0xffffffe8
35c: e1520003 cmp r2, r3
360: baffffde blt 2e0 <draw_box+0x28>
364: e1a00000 nop ; (mov r0, r0)
368: e1a00000 nop ; (mov r0, r0)
36c: e28bd000 add sp, fp, #0
370: e49db004 pop {fp} ; (ldr fp, [sp], #4)
374: e12fff1e bx lr
...
00000380 <timer_init>:
380: e52db004 push {fp} ; (str fp, [sp, #-4]!)
384: e28db000 add fp, sp, #0
388: e24dd00c sub sp, sp, #12
38c: e3a03000 mov r3, #0
390: e50b3008 str r3, [fp, #-8]
394: ea000048 b 4bc <timer_init+0x13c>
398: e51b3008 ldr r3, [fp, #-8]
39c: e1a03183 lsl r3, r3, #3
3a0: e59f2134 ldr r2, [pc, #308] ; 4dc <timer_init+0x15c>
3a4: e0833002 add r3, r3, r2
3a8: e50b300c str r3, [fp, #-12]
3ac: e51b3008 ldr r3, [fp, #-8]
3b0: e3530000 cmp r3, #0
3b4: 1a000002 bne 3c4 <timer_init+0x44>
3b8: e51b300c ldr r3, [fp, #-12]
3bc: e59f211c ldr r2, [pc, #284] ; 4e0 <timer_init+0x160>
3c0: e5832000 str r2, [r3]
3c4: e51b3008 ldr r3, [fp, #-8]
3c8: e3530001 cmp r3, #1
3cc: 1a000002 bne 3dc <timer_init+0x5c>
3d0: e51b300c ldr r3, [fp, #-12]
3d4: e59f2108 ldr r2, [pc, #264] ; 4e4 <timer_init+0x164>
3d8: e5832000 str r2, [r3]
3dc: e51b3008 ldr r3, [fp, #-8]
3e0: e3530002 cmp r3, #2
3e4: 1a000002 bne 3f4 <timer_init+0x74>
3e8: e51b300c ldr r3, [fp, #-12]
3ec: e59f20f4 ldr r2, [pc, #244] ; 4e8 <timer_init+0x168>
3f0: e5832000 str r2, [r3]
3f4: e51b3008 ldr r3, [fp, #-8]
3f8: e3530003 cmp r3, #3
3fc: 1a000002 bne 40c <timer_init+0x8c>
400: e51b300c ldr r3, [fp, #-12]
404: e59f20e0 ldr r2, [pc, #224] ; 4ec <timer_init+0x16c>
408: e5832000 str r2, [r3]
40c: e51b300c ldr r3, [fp, #-12]
410: e5933000 ldr r3, [r3]
414: e3a02000 mov r2, #0
418: e5832000 str r2, [r3]
41c: e51b300c ldr r3, [fp, #-12]
420: e5933000 ldr r3, [r3]
424: e2833004 add r3, r3, #4
428: e3e02000 mvn r2, #0
42c: e5832000 str r2, [r3]
430: e51b300c ldr r3, [fp, #-12]
434: e5933000 ldr r3, [r3]
438: e2833010 add r3, r3, #16
43c: e3a02000 mov r2, #0
440: e5832000 str r2, [r3]
444: e51b300c ldr r3, [fp, #-12]
448: e5933000 ldr r3, [r3]
44c: e2833014 add r3, r3, #20
450: e3a02000 mov r2, #0
454: e5832000 str r2, [r3]
458: e51b300c ldr r3, [fp, #-12]
45c: e5933000 ldr r3, [r3]
460: e3a02c01 mov r2, #256 ; 0x100
464: e5832000 str r2, [r3]
468: e51b300c ldr r3, [fp, #-12]
46c: e5933000 ldr r3, [r3]
470: e2833008 add r3, r3, #8
474: e3a02066 mov r2, #102 ; 0x66
478: e5832000 str r2, [r3]
47c: e51b300c ldr r3, [fp, #-12]
480: e5933000 ldr r3, [r3]
484: e2833018 add r3, r3, #24
488: e3a02b07 mov r2, #7168 ; 0x1c00
48c: e5832000 str r2, [r3]
490: e51b300c ldr r3, [fp, #-12]
494: e5933000 ldr r3, [r3]
498: e5932000 ldr r2, [r3]
49c: e3822040 orr r2, r2, #64 ; 0x40
4a0: e5832000 str r2, [r3]
4a4: e51b300c ldr r3, [fp, #-12]
4a8: e3a02000 mov r2, #0
4ac: e5832004 str r2, [r3, #4]
4b0: e51b3008 ldr r3, [fp, #-8]
4b4: e2833001 add r3, r3, #1
4b8: e50b3008 str r3, [fp, #-8]
4bc: e51b3008 ldr r3, [fp, #-8]
4c0: e3530003 cmp r3, #3
4c4: daffffb3 ble 398 <timer_init+0x18>
4c8: e1a00000 nop ; (mov r0, r0)
4cc: e1a00000 nop ; (mov r0, r0)
4d0: e28bd000 add sp, fp, #0
4d4: e49db004 pop {fp} ; (ldr fp, [sp], #4)
4d8: e12fff1e bx lr
4dc: 00000000 .word 0x00000000
4e0: 101e2000 .word 0x101e2000
4e4: 101e2020 .word 0x101e2020
4e8: 101e3000 .word 0x101e3000
4ec: 101e3020 .word 0x101e3020
000004f0 <timer_clearInterupt>:
4f0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
4f4: e28db000 add fp, sp, #0
4f8: e24dd014 sub sp, sp, #20
4fc: e50b0010 str r0, [fp, #-16]
500: e51b3010 ldr r3, [fp, #-16]
504: e1a03183 lsl r3, r3, #3
508: e59f2028 ldr r2, [pc, #40] ; 538 <timer_clearInterupt+0x48>
50c: e0833002 add r3, r3, r2
510: e50b3008 str r3, [fp, #-8]
514: e51b3008 ldr r3, [fp, #-8]
518: e5933000 ldr r3, [r3]
51c: e283300c add r3, r3, #12
520: e3e02000 mvn r2, #0
524: e5832000 str r2, [r3]
528: e1a00000 nop ; (mov r0, r0)
52c: e28bd000 add sp, fp, #0
530: e49db004 pop {fp} ; (ldr fp, [sp], #4)
534: e12fff1e bx lr
538: 00000000 .word 0x00000000
0000053c <timer_handler>:
53c: e92d4800 push {fp, lr}
540: e28db004 add fp, sp, #4
544: e24dd010 sub sp, sp, #16
548: e50b0010 str r0, [fp, #-16]
54c: e51b3010 ldr r3, [fp, #-16]
550: e1a03183 lsl r3, r3, #3
554: e59f203c ldr r2, [pc, #60] ; 598 <timer_handler+0x5c>
558: e0833002 add r3, r3, r2
55c: e50b3008 str r3, [fp, #-8]
560: e51b3008 ldr r3, [fp, #-8]
564: e5933004 ldr r3, [r3, #4]
568: e2832001 add r2, r3, #1
56c: e51b3008 ldr r3, [fp, #-8]
570: e5832004 str r2, [r3, #4]
574: e51b0010 ldr r0, [fp, #-16]
578: ebfffffe bl 4f0 <timer_clearInterupt>
57c: e59f1018 ldr r1, [pc, #24] ; 59c <timer_handler+0x60>
580: e59f0018 ldr r0, [pc, #24] ; 5a0 <timer_handler+0x64>
584: ebfffffe bl 1c0 <uprints>
588: e1a00000 nop ; (mov r0, r0)
58c: e24bd004 sub sp, fp, #4
590: e8bd4800 pop {fp, lr}
594: e12fff1e bx lr
...
000005a4 <timer_start>:
5a4: e92d4800 push {fp, lr}
5a8: e28db004 add fp, sp, #4
5ac: e24dd010 sub sp, sp, #16
5b0: e50b0010 str r0, [fp, #-16]
5b4: e59f1044 ldr r1, [pc, #68] ; 600 <timer_start+0x5c>
5b8: e59f0044 ldr r0, [pc, #68] ; 604 <timer_start+0x60>
5bc: ebfffffe bl 1c0 <uprints>
5c0: e51b3010 ldr r3, [fp, #-16]
5c4: e1a03183 lsl r3, r3, #3
5c8: e59f2038 ldr r2, [pc, #56] ; 608 <timer_start+0x64>
5cc: e0833002 add r3, r3, r2
5d0: e50b3008 str r3, [fp, #-8]
5d4: e51b3008 ldr r3, [fp, #-8]
5d8: e5933000 ldr r3, [r3]
5dc: e2832008 add r2, r3, #8
5e0: e5922000 ldr r2, [r2]
5e4: e2833008 add r3, r3, #8
5e8: e3822080 orr r2, r2, #128 ; 0x80
5ec: e5832000 str r2, [r3]
5f0: e1a00000 nop ; (mov r0, r0)
5f4: e24bd004 sub sp, fp, #4
5f8: e8bd4800 pop {fp, lr}
5fc: e12fff1e bx lr
600: 00000010 .word 0x00000010
...
0000060c <timer_stop>:
60c: e52db004 push {fp} ; (str fp, [sp, #-4]!)
610: e28db000 add fp, sp, #0
614: e24dd014 sub sp, sp, #20
618: e50b0010 str r0, [fp, #-16]
61c: e51b3010 ldr r3, [fp, #-16]
620: e1a03183 lsl r3, r3, #3
624: e59f2028 ldr r2, [pc, #40] ; 654 <timer_stop+0x48>
628: e0833002 add r3, r3, r2
62c: e50b3008 str r3, [fp, #-8]
630: e51b3008 ldr r3, [fp, #-8]
634: e5933000 ldr r3, [r3]
638: e2833008 add r3, r3, #8
63c: e3a0207f mov r2, #127 ; 0x7f
640: e5832000 str r2, [r3]
644: e1a00000 nop ; (mov r0, r0)
648: e28bd000 add sp, fp, #0
64c: e49db004 pop {fp} ; (ldr fp, [sp], #4)
650: e12fff1e bx lr
654: 00000000 .word 0x00000000
00000658 <undef_handler>:
658: e92d4800 push {fp, lr}
65c: e28db004 add fp, sp, #4
660: e59f1014 ldr r1, [pc, #20] ; 67c <undef_handler+0x24>
664: e59f0014 ldr r0, [pc, #20] ; 680 <undef_handler+0x28>
668: ebfffffe bl 1c0 <uprints>
66c: e1a00000 nop ; (mov r0, r0)
670: e24bd004 sub sp, fp, #4
674: e8bd4800 pop {fp, lr}
678: e12fff1e bx lr
67c: 00000020 .word 0x00000020
680: 00000000 .word 0x00000000
00000684 <swi_handler>:
684: e92d4800 push {fp, lr}
688: e28db004 add fp, sp, #4
68c: e59f1014 ldr r1, [pc, #20] ; 6a8 <swi_handler+0x24>
690: e59f0014 ldr r0, [pc, #20] ; 6ac <swi_handler+0x28>
694: ebfffffe bl 1c0 <uprints>
698: e1a00000 nop ; (mov r0, r0)
69c: e24bd004 sub sp, fp, #4
6a0: e8bd4800 pop {fp, lr}
6a4: e12fff1e bx lr
6a8: 00000020 .word 0x00000020
6ac: 00000000 .word 0x00000000
000006b0 <prefetch_abort_handler>:
6b0: e92d4800 push {fp, lr}
6b4: e28db004 add fp, sp, #4
6b8: e59f1014 ldr r1, [pc, #20] ; 6d4 <prefetch_abort_handler+0x24>
6bc: e59f0014 ldr r0, [pc, #20] ; 6d8 <prefetch_abort_handler+0x28>
6c0: ebfffffe bl 1c0 <uprints>
6c4: e1a00000 nop ; (mov r0, r0)
6c8: e24bd004 sub sp, fp, #4
6cc: e8bd4800 pop {fp, lr}
6d0: e12fff1e bx lr
6d4: 00000020 .word 0x00000020
6d8: 00000000 .word 0x00000000
000006dc <data_abort_handler>:
6dc: e92d4800 push {fp, lr}
6e0: e28db004 add fp, sp, #4
6e4: e59f1014 ldr r1, [pc, #20] ; 700 <data_abort_handler+0x24>
6e8: e59f0014 ldr r0, [pc, #20] ; 704 <data_abort_handler+0x28>
6ec: ebfffffe bl 1c0 <uprints>
6f0: e1a00000 nop ; (mov r0, r0)
6f4: e24bd004 sub sp, fp, #4
6f8: e8bd4800 pop {fp, lr}
6fc: e12fff1e bx lr
700: 00000020 .word 0x00000020
704: 00000000 .word 0x00000000
00000708 <fiq_handler>:
708: e92d4800 push {fp, lr}
70c: e28db004 add fp, sp, #4
710: e59f1014 ldr r1, [pc, #20] ; 72c <fiq_handler+0x24>
714: e59f0014 ldr r0, [pc, #20] ; 730 <fiq_handler+0x28>
718: ebfffffe bl 1c0 <uprints>
71c: e1a00000 nop ; (mov r0, r0)
720: e24bd004 sub sp, fp, #4
724: e8bd4800 pop {fp, lr}
728: e12fff1e bx lr
72c: 00000020 .word 0x00000020
730: 00000000 .word 0x00000000
00000734 <copy_vector>:
734: e52db004 push {fp} ; (str fp, [sp, #-4]!)
738: e28db000 add fp, sp, #0
73c: e24dd00c sub sp, sp, #12
740: e59f3050 ldr r3, [pc, #80] ; 798 <copy_vector+0x64>
744: e50b3008 str r3, [fp, #-8]
748: e3a03000 mov r3, #0
74c: e50b300c str r3, [fp, #-12]
750: ea000007 b 774 <copy_vector+0x40>
754: e51b2008 ldr r2, [fp, #-8]
758: e2823004 add r3, r2, #4
75c: e50b3008 str r3, [fp, #-8]
760: e51b300c ldr r3, [fp, #-12]
764: e2831004 add r1, r3, #4
768: e50b100c str r1, [fp, #-12]
76c: e5922000 ldr r2, [r2]
770: e5832000 str r2, [r3]
774: e51b3008 ldr r3, [fp, #-8]
778: e59f201c ldr r2, [pc, #28] ; 79c <copy_vector+0x68>
77c: e1530002 cmp r3, r2
780: 3afffff3 bcc 754 <copy_vector+0x20>
784: e1a00000 nop ; (mov r0, r0)
788: e1a00000 nop ; (mov r0, r0)
78c: e28bd000 add sp, fp, #0
790: e49db004 pop {fp} ; (ldr fp, [sp], #4)
794: e12fff1e bx lr
...
000007a0 <kbd_init>:
7a0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
7a4: e28db000 add fp, sp, #0
7a8: e24dd00c sub sp, sp, #12
7ac: e59f302c ldr r3, [pc, #44] ; 7e0 <kbd_init+0x40>
7b0: e50b3008 str r3, [fp, #-8]
7b4: e51b3008 ldr r3, [fp, #-8]
7b8: e3a02014 mov r2, #20
7bc: e5c32000 strb r2, [r3]
7c0: e51b3008 ldr r3, [fp, #-8]
7c4: e283300c add r3, r3, #12
7c8: e3a02008 mov r2, #8
7cc: e5c32000 strb r2, [r3]
7d0: e1a00000 nop ; (mov r0, r0)
7d4: e28bd000 add sp, fp, #0
7d8: e49db004 pop {fp} ; (ldr fp, [sp], #4)
7dc: e12fff1e bx lr
7e0: 10006000 .word 0x10006000
000007e4 <IRQ_handler>:
7e4: e92d4800 push {fp, lr}
7e8: e28db004 add fp, sp, #4
7ec: e24dd008 sub sp, sp, #8
7f0: e3a03000 mov r3, #0
7f4: e50b3008 str r3, [fp, #-8]
7f8: e59f10a4 ldr r1, [pc, #164] ; 8a4 <IRQ_handler+0xc0>
7fc: e59f00a4 ldr r0, [pc, #164] ; 8a8 <IRQ_handler+0xc4>
800: ebfffffe bl 1c0 <uprints>
804: e59f30a0 ldr r3, [pc, #160] ; 8ac <IRQ_handler+0xc8>
808: e5933000 ldr r3, [r3]
80c: e5933000 ldr r3, [r3]
810: e2833004 add r3, r3, #4
814: e5933000 ldr r3, [r3]
818: e3530000 cmp r3, #0
81c: 1a000001 bne 828 <IRQ_handler+0x44>
820: e3a00000 mov r0, #0
824: ebfffffe bl 53c <timer_handler>
828: e59f307c ldr r3, [pc, #124] ; 8ac <IRQ_handler+0xc8>
82c: e5933004 ldr r3, [r3, #4]
830: e5933000 ldr r3, [r3]
834: e2833004 add r3, r3, #4
838: e5933000 ldr r3, [r3]
83c: e3530000 cmp r3, #0
840: 1a000001 bne 84c <IRQ_handler+0x68>
844: e3a00001 mov r0, #1
848: ebfffffe bl 53c <timer_handler>
84c: e59f3058 ldr r3, [pc, #88] ; 8ac <IRQ_handler+0xc8>
850: e5933008 ldr r3, [r3, #8]
854: e5933000 ldr r3, [r3]
858: e2833004 add r3, r3, #4
85c: e5933000 ldr r3, [r3]
860: e3530000 cmp r3, #0
864: 1a000001 bne 870 <IRQ_handler+0x8c>
868: e3a00002 mov r0, #2
86c: ebfffffe bl 53c <timer_handler>
870: e59f3034 ldr r3, [pc, #52] ; 8ac <IRQ_handler+0xc8>
874: e593300c ldr r3, [r3, #12]
878: e5933000 ldr r3, [r3]
87c: e2833004 add r3, r3, #4
880: e5933000 ldr r3, [r3]
884: e3530000 cmp r3, #0
888: 1a000001 bne 894 <IRQ_handler+0xb0>
88c: e3a00003 mov r0, #3
890: ebfffffe bl 53c <timer_handler>
894: e1a00000 nop ; (mov r0, r0)
898: e24bd004 sub sp, fp, #4
89c: e8bd4800 pop {fp, lr}
8a0: e12fff1e bx lr
8a4: 00000030 .word 0x00000030
...
000008b0 <main>:
8b0: e92d4800 push {fp, lr}
8b4: e28db004 add fp, sp, #4
8b8: e24dd010 sub sp, sp, #16
8bc: ebfffffe bl 218 <fbuf_init>
8c0: ebfffffe bl 0 <uart_init>
8c4: ebfffffe bl 380 <timer_init>
8c8: ebfffffe bl 7a0 <kbd_init>
8cc: e3a03000 mov r3, #0
8d0: e50b3008 str r3, [fp, #-8]
8d4: ea00000b b 908 <main+0x58>
8d8: e51b3008 ldr r3, [fp, #-8]
8dc: e1a03183 lsl r3, r3, #3
8e0: e59f20dc ldr r2, [pc, #220] ; 9c4 <main+0x114>
8e4: e0832002 add r2, r3, r2
8e8: e59f10d8 ldr r1, [pc, #216] ; 9c8 <main+0x118>
8ec: e51b3008 ldr r3, [fp, #-8]
8f0: e7812103 str r2, [r1, r3, lsl #2]
8f4: e51b0008 ldr r0, [fp, #-8]
8f8: ebfffffe bl 5a4 <timer_start>
8fc: e51b3008 ldr r3, [fp, #-8]
900: e2833001 add r3, r3, #1
904: e50b3008 str r3, [fp, #-8]
908: e51b3008 ldr r3, [fp, #-8]
90c: e3530003 cmp r3, #3
910: dafffff0 ble 8d8 <main+0x28>
914: e59f10b0 ldr r1, [pc, #176] ; 9cc <main+0x11c>
918: e59f00b0 ldr r0, [pc, #176] ; 9d0 <main+0x120>
91c: ebfffffe bl 1c0 <uprints>
920: e59f309c ldr r3, [pc, #156] ; 9c4 <main+0x114>
924: e5931004 ldr r1, [r3, #4]
928: e59f30a4 ldr r3, [pc, #164] ; 9d4 <main+0x124>
92c: e0c32391 smull r2, r3, r1, r3
930: e1a021c3 asr r2, r3, #3
934: e1a03fc1 asr r3, r1, #31
938: e0422003 sub r2, r2, r3
93c: e1a03002 mov r3, r2
940: e1a03183 lsl r3, r3, #3
944: e0433002 sub r3, r3, r2
948: e1a03183 lsl r3, r3, #3
94c: e0433002 sub r3, r3, r2
950: e1a03103 lsl r3, r3, #2
954: e0412003 sub r2, r1, r3
958: e1a03002 mov r3, r2
95c: e54b3009 strb r3, [fp, #-9]
960: e55b3009 ldrb r3, [fp, #-9]
964: e2833037 add r3, r3, #55 ; 0x37
968: e20330ff and r3, r3, #255 ; 0xff
96c: e1a01003 mov r1, r3
970: e59f0058 ldr r0, [pc, #88] ; 9d0 <main+0x120>
974: ebfffffe bl e4 <uputc>
978: e55b3009 ldrb r3, [fp, #-9]
97c: e383386e orr r3, r3, #7208960 ; 0x6e0000
980: e3833001 orr r3, r3, #1
984: e50b3010 str r3, [fp, #-16]
988: e51b3010 ldr r3, [fp, #-16]
98c: e3a02064 mov r2, #100 ; 0x64
990: e3a0100a mov r1, #10
994: e3a0000a mov r0, #10
998: ebfffffe bl 2b8 <draw_box>
99c: e59f3020 ldr r3, [pc, #32] ; 9c4 <main+0x114>
9a0: e5933004 ldr r3, [r3, #4]
9a4: e3530000 cmp r3, #0
9a8: 0affffdc beq 920 <main+0x70>
9ac: e3a03b32 mov r3, #51200 ; 0xc800
9b0: e3a02032 mov r2, #50 ; 0x32
9b4: e3a010fa mov r1, #250 ; 0xfa
9b8: e3a000c8 mov r0, #200 ; 0xc8
9bc: ebfffffe bl 2b8 <draw_box>
9c0: eaffffd6 b 920 <main+0x70>
...
9cc: 0000003c .word 0x0000003c
9d0: 00000000 .word 0x00000000
9d4: 094f2095 .word 0x094f2095
also my linker script:
ENTRY(start)
SECTIONS{
. = 0x10000;
.text : {*(.text)}
.data : {*(.data)}
.bss : {*(.bss)}
. =ALIGN(8);
. =. + 0x1000;
stack_top = .;
. = . + 0x1000;
irq_stack_top = .;
}
So I do not have a complete example but something looks wrong, really wrong that you will need to sort out. And maybe you are already through all of these basic steps to get to this point.
qemu-system-arm -M versatilepb -m 128M -kernel notmain.bin
Implies a binary memory image file as in objcopy -O binary is being used. And there is no addressing information, so some default built into that machine or simulation is being used. What is that address....
strap.s
mov sp,#0x10000
bl notmain
b .
.globl GETPC
GETPC:
mov r0,pc
bx lr
.globl PUT32
PUT32:
str r1,[r0]
bx lr
notmain.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GETPC ( void );
#define UART_BASE 0x101F1000
#define UARTDR (UART_BASE+0x000)
static void uart_send ( unsigned int x )
{
PUT32(UARTDR,x);
}
static void hexstrings ( unsigned int d )
{
unsigned int rb;
unsigned int rc;
rb=32;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_send(rc);
if(rb==0) break;
}
uart_send(0x20);
}
static void hexstring ( unsigned int d )
{
hexstrings(d);
uart_send(0x0D);
uart_send(0x0A);
}
int notmain ( void )
{
hexstring(GETPC());
return(0);
}
uart address culled from the source code to qemu. so far I find you can cheat and just write to the tx buffer, it does not actually emulate the time it takes to send out a character and overflow a fifo, etc. So I cheat.
/* memmap */
MEMORY
{
ram : ORIGIN = 0x00000000, LENGTH = 32K
}
SECTIONS
{
.text : { *(.text*) } > ram
.bss : { *(.text*) } > ram
}
build
arm-none-eabi-as --warn --fatal-warnings -march=armv4t strap.s -o strap.o
arm-none-eabi-gcc -c -Wall -O2 -ffreestanding -march=armv4t notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles strap.o notmain.o -T memmap -o notmain.elf
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf -O binary notmain.bin
examine output
Disassembly of section .text:
00000000 <GETPC-0xc>:
0: e3a0d801 mov sp, #65536 ; 0x10000
4: eb000004 bl 1c <notmain>
8: eafffffe b 8 <GETPC-0x4>
0000000c <GETPC>:
c: e1a0000f mov r0, pc
10: e12fff1e bx lr
00000014 <PUT32>:
14: e5801000 str r1, [r0]
18: e12fff1e bx lr
0000001c <notmain>:
1c: e92d4070 push {r4, r5, r6, lr}
20: ebfffff9 bl c <GETPC>
24: e3a04020 mov r4, #32
my entry point is where I want it. I am not loading an elf I am loading a binary image. If I wanted the entry point to be different and load an elf it may be possible that using ENTRY() in the linker script then having the entry point wherever might work.
qemu-system-arm -M versatilepb -m 128M -kernel notmain.bin
then view the serial0 output of 00010014 so they are loading us at 0x10000 so change memmap
ram : ORIGIN = 0x00010000, LENGTH = 32K
Now your linker script implies it should have put your code at 0x10000 but
clearly it has not based on your disassembly, so how are you running anything at all. Also your entry point using a binary image is not the bootstrap it is not the first instructions you want to be executing. maybe you disassembled an object not the final binary?
So for fun before changing the memory map to 0x10000 if I instead
qemu-system-arm -M versatilepb -m 128M -kernel notmain.elf
Then I get 00000014 on the output. it used the address defined in the elf file.
If I add this
b .
.globl _start
_start:
mov sp,#0x10000
bl notmain
b .
and this
/* memmap */
ENTRY(_start)
MEMORY
{
ram : ORIGIN = 0x00000000, LENGTH = 32K
}
SECTIONS
{
.text : { *(.text*) } > ram
.bss : { *(.text*) } > ram
}
and execute the elf I do get output of 00000018 so it is entering at the entry point not the first word of the loadable image.
run the .bin and you get no serial output as expected.
Change memmap to 0x10000 and run the elf you get 0x10018 as expected.
So that was a simple way to see how qemu loads our program.
so same build and linker script (with the 0x10000)
.globl _start
_start:
ldr pc,reset_handler
ldr pc,undefined_handler
ldr pc,swi_handler
ldr pc,prefetch_handler
ldr pc,data_handler
ldr pc,unused_handler
ldr pc,irq_handler
ldr pc,fiq_handler
reset_handler: .word reset
undefined_handler: .word hang
swi_handler: .word swi
prefetch_handler: .word hang
data_handler: .word hang
unused_handler: .word hang
irq_handler: .word hang
fiq_handler: .word hang
reset:
mov r0,#0x10000
mov r1,#0x00000
ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}
ldmia r0!,{r2,r3,r4,r5,r6,r7,r8,r9}
stmia r1!,{r2,r3,r4,r5,r6,r7,r8,r9}
;# FIQ 110 10001
msr cpsr_c,#0xD1
mov sp,#0x1000
;# IRQ 110 10010
msr cpsr_c,#0xD2
mov sp,#0x2000
;# SVC 110 10011
msr cpsr_c,#0xD3
mov sp,#0x3000
;# ABT 110 10111
msr cpsr_c,#0xD7
mov sp,#0x4000
;# UND 110 11011
msr cpsr_c,#0xDB
mov sp,#0x5000
;# SYS 110 11111
msr cpsr_c,#0xDF
mov sp,#0x6000
;# SVC 110 10011
msr cpsr_c,#0xD3
bl notmain
hang:
b hang
swi:
push {r4-r12,lr}
bl swi_main
pop {r4-r12,lr}
movs pc,lr
.globl DO_SWI
DO_SWI:
push {lr}
svc 0
pop {lr}
bx lr
.globl GO_USER
GO_USER:
;# USER 110 10000
msr cpsr_c,#0xD0
bl gouser
b .
gouser:
bx r0
.globl GETMODE
GETMODE:
mrs r0,cpsr
bx lr
.globl GETPC
GETPC:
mov r0,pc
bx lr
.globl GETSP
GETSP:
mov r0,sp
bx lr
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.globl GET32
GET32:
ldr r0,[r0]
bx lr
and
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
unsigned int GETPC ( void );
unsigned int GETSP ( void );
unsigned int GETMODE ( void );
unsigned int GO_USER ( unsigned int );
unsigned int DO_SWI ( unsigned int, unsigned int, unsigned int, unsigned int );
#define UART_BASE 0x101F1000
#define UARTDR (UART_BASE+0x000)
#define UARTFR (UART_BASE+0x018)
static void uart_send ( unsigned int x )
{
while(1)
{
if(GET32(UARTFR)&(1<<7)) break;
}
PUT32(UARTDR,x);
}
static void hexstrings ( unsigned int d )
{
unsigned int rb;
unsigned int rc;
rb=32;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_send(rc);
if(rb==0) break;
}
uart_send(0x20);
}
static void hexstring ( unsigned int d )
{
hexstrings(d);
uart_send(0x0D);
uart_send(0x0A);
}
unsigned int swi_main ( unsigned int a, unsigned int b, unsigned int c, unsigned int d )
{
hexstring(0xAABBCCDD);
switch(a)
{
case 0:
{
return(~b);
}
case 1:
{
return(GETMODE());
}
}
return(0);
}
void user_main ( void )
{
hexstring(GETMODE());
hexstring(GETSP());
hexstring(DO_SWI(0,0x1234,0,0));
hexstring(DO_SWI(1,0x1234,0,0));
}
int notmain ( void )
{
hexstring(GETMODE());
hexstring(GETSP());
GO_USER((unsigned int)user_main);
return(0);
}
get even a trivial swi in place first before attempting an interrupt. getting the exception table in place, the banked stack registers, etc. seems trivial but even with experience those things bite you and you end up chasing the wrong thing.
400001D3
00002FF8
200001D0
00005FF8
AABBCCDD
FFFFEDCB
AABBCCDD
600001D3
this was a bit overkill with mode changes and such, but it still has the swi handler in the right place. The code is linked for
notmain.elf: file format elf32-littlearm
Disassembly of section .text:
00010000 <_start>:
10000: e59ff018 ldr pc, [pc, #24] ; 10020 <reset_handler>
10004: e59ff018 ldr pc, [pc, #24] ; 10024 <undefined_handler>
10008: e59ff018 ldr pc, [pc, #24] ; 10028 <swi_handler>
1000c: e59ff018 ldr pc, [pc, #24] ; 1002c <prefetch_handler>
10010: e59ff018 ldr pc, [pc, #24] ; 10030 <data_handler>
10014: e59ff018 ldr pc, [pc, #24] ; 10034 <unused_handler>
10018: e59ff018 ldr pc, [pc, #24] ; 10038 <irq_handler>
1001c: e59ff018 ldr pc, [pc, #24] ; 1003c <fiq_handler>
00010020 <reset_handler>:
10020: 00010040 andeq r0, r1, r0, asr #32
00010024 <undefined_handler>:
10024: 00010090 muleq r1, r0, r0
packing the exception table with its pc-relative addresses and letting the toolchain do all the work of sorting out addresses for you, you can then simply copy it to 0x00000000 from 0x10000. It is probably fine but in your case I would at least put some level of alignment before your table, something makes me want to think it wants to be aligned. However you wish to copy it is your deal, I would not use C in a bootstrap, the habit creates problems from time to time that are easily avoided.
Knowing what we know of course if we linked for address 0x00000000 and used the elf file then we do not have to copy/move the exception table. It lands in the right place on load.
Newer cores have a VTOR register and you can simply choose a different exception or vector table address, but it does need to have a level of alignment that you cannot forget.
I did not go and research this timer, but I assume long before you attempted an interrupt you wrote very many throwaway programs that used polling to fully understand the timer and how to clear its interrupt, etc? Depending on the chip (not necessarily core) then there may also be arm side registers you can poll, disable interrupts into the core, poll the gvic or vpic or whatever it is called and see the interrupt hit the edge of the core, be able to turn it off, etc. Then.....enable it into the core now that you have mastered that peripheral. Sometimes leaving nothing left to work on, for some cores though there is some interrupt stuff that can only be done in an isr (how to detect and clear the interrupt source) this virtual machine predates that by a long time though, so no worries there.
so...
If that is your linker script then why is your output zero based, and why is the uart function up front and not the bootstrap entry point? If that is the disassembly of the final binary then there are all kinds of problems going on there.
I was seeing this as baremetal but forgetting qemu is loading linux-like so at some address like 0x8000, 0x10000, or 0x80000 are some examples, so yes you either need a core with a VTOR or copy the exception table over, and letting the tools build the addresses and pc-relative loads is the way to go. That copy is probably fine if you are actually booting right and executing it.
Then have you completely mastered that peripheral?
This is an emulated core so it may resemble one/some of the products from arm but remember they are not all identical some come with interrupt controllers some do not, some folks like the raspi folks disable that interrupt controller, etc. The base address of add on peripherals for real arm cores is based on the chip vendor not arm. Etc....Best to dig through the source code for the specific machine emulation and see what it is doing to truly get a qemu machine to work.
So maybe you have done all of these things and it still does not work. The question as written has some issues, the disassembly does not make sense for example. Need to resolve that. What if you try with an elf file first and an entry point then do the extra work to be able to run without the elf file and the bin file instead. Do not re-write but add more content to the question if you need further help. Unless someone else sees the issue with what has been presented.
I'm working on a context switch in ARM v6 assembly. I posted about writing the switch in C, but assembly seems to be safer and more reliable. I've spent a while checking all the offsets and being careful not to delete data from registers, but the context switch just doesn't seem to work properly. I have set up and tested timer interrupts without switching context.
Here's my code:
interrupt_asm:
//store basic interrupt stuff
sub lr, lr, #4
//call the interrupt vector
push { r0-r12 }
mov r0, lr # Pass old pc
bl interrupt_vector # C function
pop { r0-r12 }
# save_current_thread:
//remember r1 so you can use it for r0
push {r1}
mov r1, r0 //store r0 so it can be restored
push {r2, r3}
bl get_current_thread //r0 now has the address of CURRENT_THREAD
pop {r2, r3}
add r0, r0, #4 // r0 = &CURRENT_THREAD.r0
str r1, [r0] // save what the r0 was
pop {r1} // restore r1
add r0, r0, #4 // r0 = &CURRENT_THREAD.r1
str r1, [r0] // save r1
//r2
add r0, r0, #4
str r2, [r0]
//r3
add r0, r0, #4
str r3, [r0]
//r4
add r0, r0, #4
str r4, [r0]
//r5
add r0, r0, #4
str r5, [r0]
//r6
add r0, r0, #4
str r6, [r0]
//r7
add r0, r0, #4
str r7, [r0]
//r8
add r0, r0, #4
str r8, [r0]
//r9
add r0, r0, #4
str r9, [r0]
//r10
add r0, r0, #4
str r10, [r0]
//r11
add r0, r0, #4
str r11, [r0]
//r12
add r0, r0, #4
str r12, [r0]
//store SVC sp, lr, and pc
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0x13
msr cpsr_c, r1
//sp
add r0, r0, #4
str sp, [r0]
//lr
add r0, r0, #4
str lr, [r0]
//back to IRQ land
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0x12
msr cpsr_c, r1
//pc THIS NEEDS TO BE LR
add r0, r0, #4
str lr, [r0]
//cpsr
add r0, r0, #4
mrs r1, cpsr
str r1, [r0]
//spsr
add r0, r0, #4
mrs r1, spsr
str r1, [r0]
push {r2, r3}
bl increment_thread //r0 now has the address of our next thread
pop {r2, r3}
# restore_thread:
//were pushing in order, so from the bottom up our stack is: r0, ... r12, sp, lr, pc, spsr
add r0, r0, #4 //r0 = &CURRENT_THREAD.r0
ldr r1, [r0] //r1 = thread.r0
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r1
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r2
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r3
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r4
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r5
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r6
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r7
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r8
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r9
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r10
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r11
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r12
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.sp
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.lr
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.pc
push {r1}
add r0, r0, #8 //skip cpsr - agreed
ldr r1, [r0] //r1 = thread.spsr
push {r1}
//Our stack now looks like spsr, pc, lr, sp, r12, ... r0 (in order of popping)
pop {r1} //this was the spsr - SPSR
pop {lr} //this was the pc - PC (from thread)
pop {r2} //this was the lr - LR (from thread)
pop {r3} //this was the sp - SP (from thread)
//switch to SVC
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x13
msr cpsr_c, r0
msr spsr, r1 //restore spsr
mov lr, r2 //restore lr to be old lr
mov sp, r3 //restore sp
//switch to IRQ
// mrs r0, cpsr
// bic r0, r0, #0x1F
// orr r0, r0, #0x12
// msr cpsr_c, r0
cps #0x12
//our stack now just has the normal registers in it. Restore them
pop {r12}
pop {r11}
pop {r10}
pop {r9}
pop {r8}
pop {r7}
pop {r6}
pop {r5}
pop {r4}
pop {r3}
pop {r2}
pop {r2}
pop {r1}
pop {r0}
push {lr}
ldm sp!, {pc}^
A thread looks like this:
typedef struct __attribute__((packed, aligned(8))) {
void (*run)();
unsigned r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, sp, lr, pc;
unsigned cpsr, spsr;
unsigned id;
unsigned priority;
thread_status status;
wait_event wait_status;
} thread_t;
Do you have any advice about what's going on? An interrupt occurs and it never goes back to a new thread. I've debugged with GDB simulator but can't seem to nail down the issue.
The C function interrupt_vector just does this:
void interrupt_vector(unsigned pc) {
CURRENT_THREAD.pc = pc;
printf(" interrupt vector (pc = 0x%08x | thread.r0 = 0x%08x)\n", pc, CURRENT_THREAD.r0);
armtimer_clear_interrupt();
}
My other C functions are literally one line, and I've looked at their disassembly:
void increment_thread(){
// Not trying to actually increment yet
__asm__ volatile("mov r0, %0" : : "r" ((unsigned) &CURRENT_THREAD));
}
void get_current_thread(){
__asm__ volatile("mov r0, %0" : : "r" ((unsigned) &CURRENT_THREAD));
}