gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Excpetions on ARM9

#76403 - Mighty Max - Tue Mar 21, 2006 11:03 am

Heya,

i've worked with exceptions of different kind and how they could be catched on the CPU the last week.

I intend to use this for implementing soft & hardcoded breakpoints. Together with the multithreading there could be a live-debugger thread that lets you look what went wrong on the hardware & changes memory to resolve the problem & return the execution.

I've created a version of the Multithreader that does a breakpoint (before it even starts the multithreading) via an undefined instruction. It also would stall the system with a message when reading from/writing to invalid locations.

Sorce & .nds:
http://mightymax.org/MultiThreading.rar

The handling is pretty easy and works allmost like the IRQ handling:

At 0x27FFD9C is the pointer to the custom exception handler. If there is a 0 stored there, the bios just ignores the exception and jumps back to the execution.

it prepares the call with storing some information in the RAM just below the pointer:
Causing location at 0x027FFD98
Saved stack at 0x027FFD94
Old ARM mode at 0x027FFD90
Old cp15 status at 0x027FFD8C

additionally it disables the MPU & sets the FIQ & IRQ bit in CPSR to disable all interrupts.

When the exception handler is called, it does not get a valid value in LR to return to. Therefor we either have to rebuild the LR, or just do the same as would happen without us beeing called.

This is done in the EnterException in the .s:
Code:

EnterException:
            // store context
            LDR r12,=ExceptionLocalStorage
            STMIA r12,{r0-r11,r13}
            
            // assign a stack
            LDR r12,=ExceptionStack
            LDR r13,[r12]
            
            // Get C function & call it
            LDR r12,=ExceptionC
            LDR r12,[r12,#0]
            ADD r14,r15,#0
            BXNE r12
         
            // restore context
            LDR r12,=ExceptionLocalStorage
            LDMIA r12,{r0-r11,r13}
            
            // do the bios code
            .word 0xE8BD5000
            .word 0xEE01CF10
            .word 0xE16FF00E
            .word 0xE8BD5000
            .word 0xE25EF004
                           
ExceptionC:
            .word            0x00000000
ExceptionStack:
            .word            0x00000000
ExceptionLocalStorage:
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000
            .word            0x00000000


There is one last obstackle still to use it. Whenever you are in the C routine to handle this exception. It will crash on the call to console functions. The solution: enable the MPU again before calling them, and it works fine again.

If you don't want it enabled & still need to print out, you will need to reinitialize the console.

I've commented the example code, it should explain the things done

Now,
have fun with exception handling.
_________________
GBAMP Multiboot

#76798 - HyperHacker - Fri Mar 24, 2006 10:27 pm

Waitwaitwait... these CPUs have exception handling? Or is it just the undefined instruction handler? (Like can you have it break on access to whatever memory area?

#76842 - Mighty Max - Sat Mar 25, 2006 7:59 am

They will break on Data Abort too, yes

Basically every other verctor beside IRQ & SWI will jump to this address.
_________________
GBAMP Multiboot

#76862 - caitsith2 - Sat Mar 25, 2006 3:45 pm

You have a bug in function GetR12. Shouldn't the code be
Code:

GetR12:
            MOVS r0,r12
            BX r14


instead of

Code:

GetR12:
            MOVS r0,r14
            BX r14

#76865 - Mighty Max - Sat Mar 25, 2006 4:27 pm

Oups, thanks for that. That's what one get when copy&pasting while beeing half asleep.



Btw, the exception vector for the ARM7 is located at 0x380FFDC and works the same (beside it doesn't disable the cp15 - the arm7 has none - and doesn't store it's status)

So that there are only 3 words saved below 0x380FFDC
_________________
GBAMP Multiboot

#76892 - HyperHacker - Sat Mar 25, 2006 10:54 pm

Mighty Max wrote:
They will break on Data Abort too, yes

Basically every other verctor beside IRQ & SWI will jump to this address.

Oh? So any access to invalid memory triggers this? I didn't know ARM could do that. Can I set the memory ranges myself, or are they hardcoded?

#76896 - Mighty Max - Sat Mar 25, 2006 11:12 pm

It's the CoProcessor 15 which manages the memory protection regions. There are 8 region (programable) descriptors available, but i suggest reading through the arm documentation about the cp15 & the MRC/MCR mnemonics.

You can invoke such an exception by trying to write into the bios range, which is defined as not writeable on the default region set:
Code:

*(unsigned short *)0xFFFF0000 = 0 ;

_________________
GBAMP Multiboot