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 > ARM7 exceptions and debugging

#145025 - simonjhall - Sat Nov 10, 2007 5:31 pm

Yo.

I'm trying to extend my debugger by adding support for ARM7 debugging. All the infrastructure's in place to 'just add a second processor', but I can't actually seem to stop the thing from running in the usual way!

With the ARM9 debugger after trying many breakpoint schemes (each with varying success) I settled on the complicated CPU exception method, as it provided the most advantages. To summarise, you point 0x27ffd9c at your carefully hand-crafted function and once you set this address to this function, the exception handling system starts to work. eg if have a data/prefetch abort, illegal or breakpoint instructions will all get relayed through this function.

Gbatek says that the ARM7 has the same setup in that you can use 0x380ffdc as the exception vector, but I can't get it to do anything. I write the address of my dummy handler to this address and go nuts, but I just can't seem to get it to get called! Neither data aborts, breakpoint instructions or illegal instructions trip this function up. However, doing stuff with CP15 (which apparently causes exceptions) does crash the CPU with or without the handler installed. Err...

Anyone done anything with exceptions on the ARM7? Wanna share :-)
_________________
Big thanks to everyone who donated for Quake2

#145026 - Mighty Max - Sat Nov 10, 2007 5:38 pm

The arm7 only calls it on undefined instructions or calls to the bios (undefined swi vector, softreset) afaik.

Due to the missing cp15, it doesn't fire on data/code aborts & such. The stack is most likely looking different on the arm7 too (i.e. no cp15 state saves)
_________________
GBAMP Multiboot

#145027 - simonjhall - Sat Nov 10, 2007 5:43 pm

Wow that was fast :-)
Undefined instructions didn't seem to give me anything (I've tried 0x0 and 0xffffffff), I'm not surprised about data aborts tbh but wouldn't the CPU 'know' that it was getting data from an address that doesn't exist? Also is there anyway to command an undefined swi call? Swi's designed for user-mode code to call an operating system, right? So it's got to be overridable, I'd imagine...

/ot: I've noticed that on the ARM9 even though GBA slot RAM has it's own section defined in the PU, reads/writes to those addresses will cause data aborts. But as soon as you plug in slot-2 RAM those aborts go away. Cool huh?
_________________
Big thanks to everyone who donated for Quake2

#145028 - Mighty Max - Sat Nov 10, 2007 5:51 pm

The undefined instruction is not really anny not defined instruction.

It should work for 0x#6000010
with # beeing the condition to execute the undef
_________________
GBAMP Multiboot

#145029 - simonjhall - Sat Nov 10, 2007 6:15 pm

Yar, thar be crashes!

Well 0x6000010 seems to do the trick! 0xf6000010 won't do it (even though f is an invalid condition code), but 0 and e are fine :-)

Also didn't help that the thing I was doing inside the actual exception function was a bit too heavyweight so it was actually happing - but I couldn't tell! Score...

Ok, to summarise:
- bkpt doesn't work
- *(int *)0 = 0 doesn't work
- mcr 15,0,r0,c0,c0,0 does work
- .word 0xe6000010 does work

...shame when exceptions do happen they don't seem to stop! One step at a time I guess :-)

Ta :-D
_________________
Big thanks to everyone who donated for Quake2

#145053 - simonjhall - Sun Nov 11, 2007 1:23 am

Yo, just a quick update - yeah, despite what I originally thought using in exception vector sufficient to make a debugger. Stuff IS different to the ARM9, but not dramatically so.
In case this can help anyone out, here's the result of a wasted Saturday afternoon!

Code:
ARM7EnterException:
      bic r13, r13, #3
      ldr r14,=MyReg
      stmia r14,{r0-r7}
      
      ldr r0,=OrigSP
      str sp,[r0]
      
      ldr r0,=CurrCPSR
      mrs r1,cpsr
      str r1,[r0]
      
      ldmia   sp!, {lr}
      msr     CPSR_fsxc, lr
      
      ldr r0,=MyReg+32
      stmia r0,{r8-r15}
      
      LDR r12,=ExceptionStack
      LDR r13,[r12]
      bl Exception

      ldr r0,=ProperCPSR
      ldr r1,[r0]
      mrs r1,cpsr
      
      ldr r0,=MyReg
      ldm r0,{r0-r15}
It's a heavily-modified version of the version I pinched (and then modified) from Mighty Max back when I did the ARM9 version.

MyReg is an array of sixteen 32-bit words, and this is where the registers from the 'calling code' will live.
OrigSP is the stack pointer that the exception handler gives you when you start this function. Note: it's not always aligned!
Once aligned, the CPSR of the original function is at $sp, the original $r12 is at $sp+4 and the return program counter (not the link register) is at $sp+8.

I get back the banked registers by picking out the saved CPSR and moving it to the current CPSR, exposing the original r8,9,10,11,13,14.

ExceptionStack is set to a malloc'd bit of memory, to be used by the breakpoint function (Exception). The final ldm will restore the code to the original execution position and state.

The original version had a bit of code (in .word format, not assembly) which used CP15. Obv this ain't gonna work! Also it loaded the original CPSR back into SPSR_fsxc, but this didn't seem to do anything in the ARM7 version. CPSR_fsxc luckily did though!

EDIT: this one restores the CPSR properly
_________________
Big thanks to everyone who donated for Quake2