#122548 - SpacedCowboy - Tue Mar 20, 2007 4:45 am
Is there anything "special" about an SWI - are there any registers I have to set to enable them (can't see *why*, but it doesn't hurt to ask :-) or any other hoops to jump through ?
I've been playing around with the source of Mighty-Max's virt-16 OS. I wanted to change a few things (a single namespace of OS_(whatever); to locate it in the bottom 512k of WRAM so I have more space eg: for a wifi device-driver or proper ELF loader; to use the 'r20' FAT library so my DS-X works; and to add a pthreads layer over the threading facilities, so I can have mutexes/semaphores).
I've got some problem code, where I'm calling 'syscall' which was defined as:
... but has now turned into:
... because the code in my SWI just isn't being called. The expanded 'syscall' routine fetches (at the time just before I call 'swi') register 1 of the CP15 chip, and prints it out, then fetches the contents of the SWI vector (a branch instruction), and prints that, then fetches the contents of the memory address that branch points at, and prints that out. It then plots a blue pixel (this works) and finally calls the SWI as planned
All of the printed-out numbers seem perfectly ok...
- the CP15 register(1) has the value 0x0005107D, so the 'V' bit is clear, meaning the exception jump-table is at 0x00000000 rather than 0xffff0000. So that's good.
- the value at 0x00000008 is 0xEA000007, which is a branch-always to +7 words, and my routine (OS_codeSWI) is 9 words away from the branch instruction. Given the PC offset of 2 words, this seems pretty peachy.
- the value at 0x0000002C (= OS_codeSWI) is 0xE92D5FFF, which is the bit-vector for the "stmdb r13!, {r0-r12,r14}" instruction, which is the first statement of the code at the address OS_codeSWI.
The first thing the SWI routine does (after storing the registers on the stack) is plot a *red* pixel close to the blue one. Unfortunately the red pixel never appears :-(
So, I'm struggling to understand how (when it all seems set up ok), the code in the SWI is never jumped-to. Max was (is :-) using regions to define what addresses can be accessed, so it occured to me that maybe a fault was happening when the SWI instruction was executed, but according to Steve Furber ("Arm System-on-a-chip architecture, 2nd edition"), the SWI process is:
- save the address of the insn after the SWI in r14_svc
- save CPSR in SPSR_svc
- Enter supervisor mode, disable IRQ (not FIQ)
- Set PC to 0x08 and begin executing
... so the system mode ought to be privileged by the time it tries to read address 0x08, and the current state of the protection registers is:
... meaning that region 0 is enabled for the entire address range (0-4GB), and access is granted to system-modes. So it ought to be ok. Just in case, I modified the permissions to 0x33333333 instead, but I still had the problem.
I moved the pageAddress array of swappable pages to start at 0x02080000 instead of 0x02000000, so I have the first 512k to play with - I oughn't be being swapped out :-) It's not allocating much memory yet anyway - the 'memStatistics' call show both TCM and WRAM still have plenty of space in them...
So, Im not having much luck solving this - if anyone has a clue as to why it might not be working, I'd love to hear it :-) Full source available if that'll help...
Cheers,
Simon.
I've been playing around with the source of Mighty-Max's virt-16 OS. I wanted to change a few things (a single namespace of OS_(whatever); to locate it in the bottom 512k of WRAM so I have more space eg: for a wifi device-driver or proper ELF loader; to use the 'r20' FAT library so my DS-X works; and to add a pthreads layer over the threading facilities, so I can have mutexes/semaphores).
I've got some problem code, where I'm calling 'syscall' which was defined as:
Code: |
/******************************************************************************\ |* Generic syscall handler. Takes either 0,1,2 or 3 arguments \******************************************************************************/ OS_syscall: OS_syscall1: OS_syscall2: OS_syscall3: swi 0x00 // Call the handler set up in the BIOS BX lr // then return |
... but has now turned into:
Code: |
/******************************************************************************\ |* Generic syscall handler. Takes either 0,1,2 or 3 arguments \******************************************************************************/ OS_syscall: OS_syscall1: OS_syscall2: OS_syscall3: stmdb r13!, {r0-r3} // Store the registers bl OS_cpreg mov r2, r0 // r2 <= CP15 reg value mov r0, #0 mov r1, #100 ldr r3, =OS_GFX_printX32 bl _call_via_r3 // print it mov r2, #0x08 // r2 <= SWI register value ldr r2, [r2] mov r0, #0 mov r1, #113 ldr r3, =OS_GFX_printX32 bl _call_via_r3 // print it ldr r2, =OS_codeSWI // r2 <= 1st insn in SWI routine ldr r2, [r2] mov r0, #0 mov r1, #126 ldr r3, =OS_GFX_printX32 bl _call_via_r3 // print it ldr r1, =0x06016c1E // blue dot at (15,182) ldr r2, =0xfc00 strh r2,[r1] ldmia r13!, {r0-r3} // Restore the registers swi 0x00 // Call the handler set up in the BIOS BX lr // then return |
... because the code in my SWI just isn't being called. The expanded 'syscall' routine fetches (at the time just before I call 'swi') register 1 of the CP15 chip, and prints it out, then fetches the contents of the SWI vector (a branch instruction), and prints that, then fetches the contents of the memory address that branch points at, and prints that out. It then plots a blue pixel (this works) and finally calls the SWI as planned
All of the printed-out numbers seem perfectly ok...
- the CP15 register(1) has the value 0x0005107D, so the 'V' bit is clear, meaning the exception jump-table is at 0x00000000 rather than 0xffff0000. So that's good.
- the value at 0x00000008 is 0xEA000007, which is a branch-always to +7 words, and my routine (OS_codeSWI) is 9 words away from the branch instruction. Given the PC offset of 2 words, this seems pretty peachy.
- the value at 0x0000002C (= OS_codeSWI) is 0xE92D5FFF, which is the bit-vector for the "stmdb r13!, {r0-r12,r14}" instruction, which is the first statement of the code at the address OS_codeSWI.
The first thing the SWI routine does (after storing the registers on the stack) is plot a *red* pixel close to the blue one. Unfortunately the red pixel never appears :-(
So, I'm struggling to understand how (when it all seems set up ok), the code in the SWI is never jumped-to. Max was (is :-) using regions to define what addresses can be accessed, so it occured to me that maybe a fault was happening when the SWI instruction was executed, but according to Steve Furber ("Arm System-on-a-chip architecture, 2nd edition"), the SWI process is:
- save the address of the insn after the SWI in r14_svc
- save CPSR in SPSR_svc
- Enter supervisor mode, disable IRQ (not FIQ)
- Set PC to 0x08 and begin executing
... so the system mode ought to be privileged by the time it tries to read address 0x08, and the current state of the protection registers is:
Code: |
OS_MPU_writeProtectionBase0(0x0000003F) ; OS_MPU_writeDataPermissions(0x33333331) ; OS_MPU_writeCodePermissions(0x33333331) ; |
... meaning that region 0 is enabled for the entire address range (0-4GB), and access is granted to system-modes. So it ought to be ok. Just in case, I modified the permissions to 0x33333333 instead, but I still had the problem.
I moved the pageAddress array of swappable pages to start at 0x02080000 instead of 0x02000000, so I have the first 512k to play with - I oughn't be being swapped out :-) It's not allocating much memory yet anyway - the 'memStatistics' call show both TCM and WRAM still have plenty of space in them...
So, Im not having much luck solving this - if anyone has a clue as to why it might not be working, I'd love to hear it :-) Full source available if that'll help...
Cheers,
Simon.