418 lines
8.9 KiB
ArmAsm
418 lines
8.9 KiB
ArmAsm
@-----------------------------------------------------------@
|
|
@ 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<n>
|
|
LDR IP, =(LPC_BASE_VIC+VIC_VectPriority0)
|
|
STR R2, [IP, R0, LSL #2] @ Set VICVectPriority<n>
|
|
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
|
|
|