@-----------------------------------------------------------@ @ LPC2300 startup code and asm functions @-----------------------------------------------------------@ .equ UND_Stack_Size, 0 .equ SVC_Stack_Size, 256 @ Used by ISRs and SWIs .equ ABT_Stack_Size, 0 .equ FIQ_Stack_Size, 0 @ Used by FIQ handler .equ IRQ_Stack_Size, 256 @ Requres ISR nesting level * 28 bytes .equ USR_Stack_Size, 1024 @ Used by user mode programs .equ Stack_Size, (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ FIQ_Stack_Size + IRQ_Stack_Size + USR_Stack_Size) .equ Heap_Size, 0 .equ B_Irq, 0x80 .equ B_Fiq, 0x40 .equ B_Thumb, 0x20 .equ M_USR, 0x10 .equ M_FIQ, 0x11 .equ M_IRQ, 0x12 .equ M_SVC, 0x13 .equ M_ABT, 0x17 .equ M_UND, 0x1B .equ M_SYS, 0x1F @-----------------------------------------------------------@ @ Stack area (located in RAM) @-----------------------------------------------------------@ .arm .section .STACK, "w" .align 3 Stack_Mem: .space Stack_Size .equ Stack_Top, Stack_Mem + Stack_Size @-----------------------------------------------------------@ @ Heap area (located in RAM) @-----------------------------------------------------------@ .section .HEAP, "w" .align 3 HeapMem: .if (Heap_Size > 0) .space Heap_Size .endif @-----------------------------------------------------------@ @ Exception entries (located in ROM, address 0x00000000) @-----------------------------------------------------------@ .section .VECTOR, "ax" .arm LDR PC, [PC, #24] @ Reset entry, jump to reset handler LDR PC, [PC, #24] @ Undef entry, trap LDR PC, [PC, #24] @ SWI entry, jump to SWI handler LDR PC, [PC, #24] @ PAbt entry, trap LDR PC, [PC, #24] @ DAbt entry, trap .word 0 LDR PC, [PC, #20] @ IRQ entry, jump to IRQ handler LDR PC, [PC, #20] @ FIQ entry, trap .word Reset_Handler @ Reset handler .word Trap @ Undefined Instruction handler .word SWI_Handler @ Software Interrupt handler .word Trap @ Prefetch Abort handler .word Trap @ Data Abort handler .word IRQ_Handler @ IRQ handler .word Trap @ FIQ handler Trap: B Trap @ Unused exception trap (infinite loop) @-----------------------------------------------------------@ @ Reset Handler @-----------------------------------------------------------@ .section .text, "ax" .arm Reset_Handler: @.extern TargetResetInit @ LDR SP, =Stack_Top @ Temporary stack for TargetResetInit() @ LDR R0, =TargetResetInit @ MOV LR, PC @ BX R0 @ Setup Stack for each mode LDR R0, =Stack_Top @ Enter Undefined Instruction Mode and set its Stack Pointer MSR CPSR_c, #M_UND | B_Irq | B_Fiq MOV SP, R0 SUB R0, R0, #UND_Stack_Size @ Enter Abort Mode and set its Stack Pointer MSR CPSR_c, #M_ABT | B_Irq | B_Fiq MOV SP, R0 SUB R0, R0, #ABT_Stack_Size @ Enter FIQ Mode and set its Stack Pointer MSR CPSR_c, #M_FIQ | B_Irq | B_Fiq MOV SP, R0 SUB R0, R0, #FIQ_Stack_Size @ Enter IRQ Mode and set its Stack Pointer MSR CPSR_c, #M_IRQ | B_Irq | B_Fiq MOV SP, R0 SUB R0, R0, #IRQ_Stack_Size @ Enter Supervisor Mode and set its Stack Pointer MSR CPSR_c, #M_SVC | B_Irq | B_Fiq MOV SP, R0 SUB R0, R0, #SVC_Stack_Size @ Enter User Mode and set its Stack Pointer MSR CPSR_c, #M_USR | B_Irq | B_Fiq MOV SP, R0 SUB SL, SP, #USR_Stack_Size @ Relocate .data section (Initialize with ROM data) LDR R1, =_etext LDR R2, =_data LDR R3, =_edata CMP R2, R3 BEQ DataIsEmpty LoopRel:CMP R2, R3 LDRLO R0, [R1], #4 STRLO R0, [R2], #4 BLO LoopRel DataIsEmpty: @ Clear .bss section (Initialize with 0) MOV R0, #0 LDR R1, =__bss_start__ LDR R2, =__bss_end__ CMP R1,R2 BEQ BSSIsEmpty LoopZI: CMP R1, R2 STRLO R0, [R1], #4 BLO LoopZI BSSIsEmpty: @ Start main() .extern main LDR R0, =main MOV LR, PC BX R0 MTrap: B MTrap @ Trap if main() terminated @-----------------------------------------------------------@ @ IRQ Handler @ Prologue and Epilog for all ISRs are handled here @-----------------------------------------------------------@ .equ LPC_BASE_VIC, 0xFFFFF000 .equ VIC_IntSelect, 0x00C .equ VIC_IntEnable, 0x010 .equ VIC_IntEnClear, 0x014 .equ VIC_Protection, 0x020 .equ VIC_SWPriorityMask,0x024 .equ VIC_VectAddr0, 0x100 .equ VIC_VectPriority0, 0x200 .equ VIC_VectAddr, 0xF00 .arm IRQ_Handler: SUB LR, LR, #4 @ Adjust LR_irq and push it STMFD SP!, {LR} MRS LR, SPSR @ Save SPSR need to be saved for nested interrupt STMFD SP!, {R0-R3,IP,LR} @ Push scratch/used registers and SPSR LDR R0, =LPC_BASE_VIC @ Get the ISR address pointed by VIC_VectAddr LDR R0, [R0, #VIC_VectAddr] MSR CPSR_c, #M_SVC @ Enter SVC mode and enable Irq and Fiq STMFD SP!, {LR} @ Call the ISR MOV LR, PC BX R0 LDMIA SP!, {LR} MSR CPSR_c, #M_IRQ | B_Irq @ Enter IRQ mode and disable Irq LDMIA SP!, {R0-R3,IP,LR} @ Restore scratch/used registers and SPSR MSR SPSR_cxsf, LR @ Restore SPSR_irq LDR LR, =LPC_BASE_VIC @ Issue EOI command to the VIC STR LR, [LR, #VIC_VectAddr] LDMIA SP!, {PC}^ @ Reruen from the IRQ handler @-----------------------------------------------------------@ @ SWI Service (declared in interrupt.h) @-----------------------------------------------------------@ .equ SWI_IRQ_DIS, 0 .equ SWI_IRQ_EN, 1 .equ SWI_FIQ_DIS, 2 .equ SWI_FIQ_EN, 3 .equ SWI_CLR_VECT, 4 .equ SWI_REG_VECT, 5 .equ NUM_SWI, 6 .arm SWI_Handler: LDR IP, [LR, #-4] @ Get swi instruction code (assuming ARM state) AND IP, #0xFF @ Get swi comment field (lower 8 bit) CMP IP, #NUM_SWI @ Check range LDRLO PC, [PC, IP, LSL #2] @ Jump each service function when code is valid MOVS PC, LR @ Otherwise return .word IRQDisable .word IRQEnable .word FIQDisable .word FIQEnable .word ClearVect .word RegVect IRQDisable: MRS R0, SPSR ORR R0, R0, #B_Irq MSR SPSR_c, R0 MOVS PC, LR IRQEnable: MRS R0, SPSR BIC R0, R0, #B_Irq MSR SPSR_c, R0 MOVS PC, LR FIQDisable: MRS R0, SPSR ORR R0, R0, #B_Fiq MSR SPSR_c, R0 MOVS PC, LR FIQEnable: MRS R0, SPSR BIC R0, R0, #B_Fiq MSR SPSR_c, R0 MOVS PC, LR ClearVect: LDR IP, =LPC_BASE_VIC MVN R0, #0 @ Disable all interrupts STR R0, [IP, #VIC_IntEnClear] MOV R0, R0, LSR #16 @ Unmask all interrupt levels STR R0, [IP, #VIC_SWPriorityMask] MOV R0, #1 @ Enable protection STR R0, [IP, #VIC_Protection] STR R0, [IP, #VIC_VectAddr] @ Issule EOI command MOVS PC, LR RegVect: CMP R0, #32 @ Range check MOVCSS PC, LR LDR IP, =(LPC_BASE_VIC+VIC_VectAddr0) STR R1, [IP, R0, LSL #2] @ Set VICVectVectAddr LDR IP, =(LPC_BASE_VIC+VIC_VectPriority0) STR R2, [IP, R0, LSL #2] @ Set VICVectPriority MOV R1, #1 MOV R1, R1, LSL R0 LDR IP, =LPC_BASE_VIC LDR R2, [IP, #VIC_IntSelect] @ Set corresponding bit in the VICIntSelect BIC R2, R1 CMP R3, #1 ORREQ R2, R1 STR R2, [IP, #VIC_IntSelect] STR R1, [IP, #VIC_IntEnable] @ Enable corresponding interrupt MOVS PC, LR .global IrqDisable .arm IrqDisable: SWI SWI_IRQ_DIS BX LR .global IrqEnable .arm IrqEnable: SWI SWI_IRQ_EN BX LR .global FiqDisable .arm FiqDisable: SWI SWI_FIQ_DIS BX LR .global FiqEnable .arm FiqEnable: SWI SWI_FIQ_EN BX LR .global ClearVector .arm ClearVector: SWI SWI_CLR_VECT BX LR .global RegisterVector .arm RegisterVector: SWI SWI_REG_VECT BX LR @-----------------------------------------------------------@ @ Fast Block Copy (declared in mci.c) @-----------------------------------------------------------@ .global Load_Block .arm Load_Block: STMFD SP!, {R4-R8} ANDS IP, R1, #3 BEQ lb_align BIC R1, #3 MOV IP, IP, LSL #3 RSB R8, IP, #32 LDMIA R1!, {R7} lb_l1: MOV R3, R7 LDMIA R1!, {R4-R7} MOV R3, R3, LSR IP ORR R3, R3, R4, LSL R8 MOV R4, R4, LSR IP ORR R4, R4, R5, LSL R8 MOV R5, R5, LSR IP ORR R5, R5, R6, LSL R8 MOV R6, R6, LSR IP ORR R6, R6, R7, LSL R8 SUBS R2, R2, #16 STMIA R0!, {R3-R6} BNE lb_l1 LDMFD SP!, {R4-R8} BX LR lb_align: LDMIA R1!, {R3-R6} SUBS R2, R2, #16 STMIA R0!, {R3-R6} BNE lb_align LDMFD SP!, {R4-R8} BX LR .global Store_Block .arm Store_Block: STMFD SP!, {R4-R8} ANDS IP, R0, #3 BEQ sb_align MOV IP, IP, LSL #3 RSB R8, IP, #32 LDMIA R1!, {R4-R7} sb_p1: STRB R4, [R0], #1 MOV R4, R4, LSR #8 TST R0, #3 BNE sb_p1 ORR R4, R4, R5, LSL IP MOV R5, R5, LSR R8 ORR R5, R5, R6, LSL IP MOV R6, R6, LSR R8 ORR R6, R6, R7, LSL IP SUBS R2, R2, #16 STMIA R0!, {R4-R6} sb_l1: MOV R3, R7 LDMIA R1!, {R4-R7} MOV R3, R3, LSR R8 ORR R3, R3, R4, LSL IP MOV R4, R4, LSR R8 ORR R4, R4, R5, LSL IP MOV R5, R5, LSR R8 ORR R5, R5, R6, LSL IP MOV R6, R6, LSR R8 ORR R6, R6, R7, LSL IP SUBS R2, R2, #16 STMIA R0!, {R3-R6} BNE sb_l1 MOV R7, R7, LSR R8 sb_p2: SUBS IP, IP, #8 STRB R7, [R0], #1 MOV R7, R7, LSR #8 BNE sb_p2 LDMFD SP!, {R4-R8} BX LR sb_align: LDMIA R1!, {R3-R6} SUBS R2, #16 STMIA R0!, {R3-R6} BNE sb_align LDMFD SP!, {R4-R8} BX LR .end