[arm-gnu] thumb code calling arm subroutine causes undefined insn exception
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[arm-gnu] thumb code calling arm subroutine causes undefined insn exception



Good afternoon, everyone,

I received a really good education on my last post regarding compiler sections 
and was able to put that knowledge to some good use, but I've run into a 
problem that I am having a real difficult time getting myself out of.

I have a little arm7tdmi board that has been the subject of all my 
experiments. I'm now playing with size optimization and have changed my 
lowlevel bootup (reset vector) code from ARM to Thumb instructions.

It works great, but I seem to be running into a problem where if I'm running 
in thumb mode and I call an ARM subroutine, the call fails.

The bootup code is in assembly, but it jumps to a C main() routine.  That 
routine executes just fine until it calls the ARM subroutine.

I'm building the code with CodeSourcery's G++ Lite 2009q3-68 (GCC 4.4.1). 

arm-none-eabi-as -o boot.o boot.s

arm-none-eabi-gcc -o irq.o -c -std=gnu99 -g -O0 -fno-builtin -nostdlib -
mcpu=arm7tdmi -mthumb-interwork -DNDEBUG -ffunction-sections -fdata-sections 
irq.c

arm-none-eabi-gcc -o main.o -c -std=gnu99 -g -O0 -fno-builtin -nostdlib -
mcpu=arm7tdmi -mthumb -mthumb-interwork -DNDEBUG -ffunction-sections -fdata-
sections main.c

As you can see, I am running with -mthumb-interwork, and I've disabled -Os for 
now. Linking is done with this command:

arm-none-eabi-gcc -o foo -std=gnu99 -g -O0 -fno-builtin -nostdlib -
mcpu=arm7tdmi -mthumb -mthumb-interwork -DNDEBUG -Trom.ld -Wl,-Map=foo.map -
Wl,--cref -Wl,--gc-sections boot.o main.o irq.o

objdumping the resultant file where the undefined instruction exception occurs 
looks ok (to me, but I'm not an expert):

000007f4 <hw_init>:
 7f4:   b580            push    {r7, lr}
 7f6:   af00            add     r7, sp, #0
 7f8:   f000 e9a4       blx     b44 <irq_setup>
 7fc:   f7ff fe1e       bl      43c <rtc_init>
 800:   f7ff ff8c       bl      71c <vibe_init>
 804:   f7ff feba       bl      57c <spiflash_init>

The undefined instruction handler shows LR at 0x7fc, which, if my math is 
correct, puts the undefined instruction at 0x7fa.

Now the irq_setup() routine lives in irq.c, which is compiled for ARM 
instructions. It too seems fine to my untrained eye:

00000b44 <irq_setup>:
 b44:   e59fc048        ldr     ip, [pc, #72]   ; b94 <irq_setup+0x50>
 b48:   e59f3048        ldr     r3, [pc, #72]   ; b98 <irq_setup+0x54>
 b4c:   e3a00000        mov     r0, #0
 b50:   e58c0000        str     r0, [ip]
 b54:   e3a0c002        mov     ip, #2
 b58:   e583c004        str     ip, [r3, #4]
 b5c:   e59fc038        ldr     ip, [pc, #56]   ; b9c <irq_setup+0x58>
 b60:   e3a01001        mov     r1, #1
 b64:   e583100c        str     r1, [r3, #12]
 b68:   e583c01c        str     ip, [r3, #28]
 b6c:   e3a0c018        mov     ip, #24
 b70:   e583c014        str     ip, [r3, #20]
 b74:   e3e02000        mvn     r2, #0
 b78:   e583003c        str     r0, [r3, #60]   ; 0x3c
 b7c:   e5831004        str     r1, [r3, #4]
 b80:   e3a03010        mov     r3, #16
 b84:   e5023fef        str     r3, [r2, #-4079]        ; 0xfef
 b88:   e59f3010        ldr     r3, [pc, #16]   ; ba0 <irq_setup+0x5c>
 b8c:   e5023fcf        str     r3, [r2, #-4047]        ; 0xfcf
 b90:   e12fff1e        bx      lr
 b94:   40000c68        .word   0x40000c68
 b98:   e0004000        .word   0xe0004000
 b9c:   00006590        .word   0x00006590
 ba0:   00000b08        .word   0x00000b08

Now irq_setup() itself not having to be in ARM instructions (only the 
interrupt handler itself), aside, why on earth would this code cause the ARM 
to abort on an undefined instruction exception?

Any hints or guidance would be very much appreciated.

Regards,
Andrew