vectors.s
.globl _start
_start:
ldr pc,_reset_handler
ldr pc,_undefined_handler
ldr pc,_swi_handler
b hang
b hang
b hang
b hang
b hang
_reset_handler: .word reset
_undefined_handler: .word hang
_swi_handler: .word swi
reset:
mov sp,#0xD6000000
add sp,sp,#0xC000
bl notmain
hang: b hang
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.globl GET32
GET32:
ldr r0,[r0]
bx lr
swi:
ldr r0,[lr,#-4]
mov r1,#0x00FFFFFF
and r0,r0,r1
movs pc,lr
.globl switest
switest:
stmdb r13!,{lr}
swi #0x23
ldmia r13!,{lr}
bx lr
linker script
MEMORY
{
ram : ORIGIN = 0x00000000, LENGTH = 0x4000
}
SECTIONS
{
.text : { *(.text*) } > ram
}
notmain.c
extern void uart_init ( void );
extern void uart_putc ( unsigned char );
extern unsigned int switest ( void );
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_putc(rc);
if(rb==0) break;
}
uart_putc(0x20);
}
void hexstring ( unsigned int d )
{
hexstrings(d);
uart_putc(0x0D);
uart_putc(0x0A);
}
int notmain ( void )
{
uart_init();
hexstring(0x12345678);
hexstring(switest());
return(0);
}
The above are relevant parts from a minimal swi working example. Note that this only works for svc/swi instructions in arm mode not thumb nor thumb2, if you want to make a generic works in all modes, I recommend you dont bother with the svc immediate and instead pass something in a register.
This example does not enable interrupts it just shows how to make an svc/swi call and how to implement the exception handler. This knowledge has been well documented in the arm architectural reference manuals for many many years now.