rt-thread/libcpu/arm/lpc214x/startup_gcc.S

351 lines
11 KiB
ArmAsm
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

.extern main /* ÒýÈëÍⲿCÈë¿Ú */
.extern __bss_beg__
.extern __bss_end__
.extern __stack_end__
.extern __data_beg__
.extern __data_end__
.extern __data+beg_src__
.extern rt_interrupt_enter
.extern rt_interrupt_leave
.extern rt_thread_switch_interrput_flag
.extern rt_interrupt_from_thread
.extern rt_interrupt_to_thread
.extern rt_hw_trap_irq
.global start
.global endless_loop
.global rt_hw_context_switch_interrupt_do
/************* Ä¿±êÅäÖà *************/
.set UND_STACK_SIZE, 0x00000004
.set ABT_STACK_SIZE, 0x00000004
.set FIQ_STACK_SIZE, 0x00000004
.set IRQ_STACK_SIZE, 0x00000400
.set SVC_STACK_SIZE, 0x00000400
.set UND_Stack_Size, 0x00000004
.set ABT_Stack_Size, 0x00000004
.set FIQ_Stack_Size, 0x00000004
.set IRQ_Stack_Size, 0x00000400
.set SVC_Stack_Size, 0x00000400
/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
.set MODE_USR, 0x10 /* User Mode */
.set MODE_FIQ, 0x11 /* FIQ Mode */
.set MODE_IRQ, 0x12 /* IRQ Mode */
.set MODE_SVC, 0x13 /* Supervisor Mode */
.set MODE_ABT, 0x17 /* Abort Mode */
.set MODE_UND, 0x1B /* Undefined Mode */
.set MODE_SYS, 0x1F /* System Mode */
.set MODE_USR, 0x10 /* User Mode */
.set Mode_FIQ, 0x11 /* FIQ Mode */
.set Mode_IRQ, 0x12 /* IRQ Mode */
.set Mode_SVC, 0x13 /* Supervisor Mode */
.set Mode_ABT, 0x17 /* Abort Mode */
.set Mode_UND, 0x1B /* Undefined Mode */
.set Mode_SYS, 0x1F /* System Mode */
.equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */
.equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */
.equ I_Bit, 0x80 /* when I bit is set, IRQ is disabled */
.equ F_Bit, 0x40 /* when F bit is set, FIQ is disabled */
/* VPBDIV definitions*/
.equ VPBDIV, 0xE01FC100
.set VPBDIV_VALUE, 0x00000000
/* Phase Locked Loop (PLL) definitions*/
.equ PLL_BASE, 0xE01FC080
.equ PLLCON_OFS, 0x00
.equ PLLCFG_OFS, 0x04
.equ PLLSTAT_OFS, 0x08
.equ PLLFEED_OFS, 0x0C
.equ PLLCON_PLLE, (1<<0) /* PLL Enable */
.equ PLLCON_PLLC, (1<<1) /* PLL Connect */
.equ PLLSTAT_LOCK, (1<<10) /* PLL Lock Status */
.equ PLLCFG_MSEL, ((PLL_MUL - 1) << 0)
.equ PLLCFG_PSEL, (0x02 << 5)
.equ PLLCFG_Val, (PLLCFG_MSEL|PLLCFG_PSEL)
.equ MEMMAP, 0xE01FC040 /*Memory Mapping Control*/
/* Memory Accelerator Module (MAM) definitions*/
.equ MAM_BASE, 0xE01FC000
.equ MAMCR_OFS, 0x00
.equ MAMTIM_OFS, 0x04
.equ MAMCR_Val, 0x00000002
.equ MAMTIM_Val, 0x00000004
.equ VICIntEnClr, 0xFFFFF014
.equ VICIntSelect, 0xFFFFF00C
/************* Ä¿±êÅäÖýáÊø *************/
/* Setup the operating mode & stack.*/
/* --------------------------------- */
.global _start, start, _reset, reset,
.func _start,
_start:
start:
_reset:
reset:
.code 32
.align 0
/************************* PLL_SETUP **********************************/
#if (PLL_MUL>1)
ldr r0, =PLL_BASE
mov r1, #0xAA
mov r2, #0x55
/* Configure and Enable PLL */
mov r3, #PLLCFG_Val
str r3, [r0, #PLLCFG_OFS]
mov r3, #PLLCON_PLLE
str r3, [r0, #PLLCON_OFS]
str r1, [r0, #PLLFEED_OFS]
str r2, [r0, #PLLFEED_OFS]
/* Wait until PLL Locked */
PLL_Locked_loop:
ldr r3, [r0, #PLLSTAT_OFS]
ands r3, r3, #PLLSTAT_LOCK
beq PLL_Locked_loop
/* Switch to PLL Clock */
mov r3, #(PLLCON_PLLE|PLLCON_PLLC)
str r3, [r0, #PLLCON_OFS]
str r1, [r0, #PLLFEED_OFS]
str R2, [r0, #PLLFEED_OFS]
#endif
/************************* PLL_SETUP **********************************/
/************************ Setup VPBDIV ********************************/
ldr r0, =VPBDIV
ldr r1, =VPBDIV_VALUE
str r1, [r0]
/************************ Setup VPBDIV ********************************/
/************** Setup MAM **************/
ldr r0, =MAM_BASE
mov r1, #MAMTIM_Val
str r1, [r0, #MAMTIM_OFS]
mov r1, #MAMCR_Val
str r1, [r0, #MAMCR_OFS]
/************** Setup MAM **************/
/************************ setup stack *********************************/
ldr r0, .LC6 /* LC6:__stack_end__ */
msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */
mov sp, r0
sub r0, r0, #UND_STACK_SIZE
msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
mov sp, r0
sub r0, r0, #ABT_STACK_SIZE
msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
mov sp, r0
sub r0, r0, #FIQ_STACK_SIZE
msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
mov sp, r0
sub r0, r0, #IRQ_STACK_SIZE
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */
mov sp, r0
/************************ setup stack ********************************/
/************************ Clear BSS ********************************/
/* Clear BSS. */
mov a2, #0 /* Fill value */
mov fp, a2 /* Null frame pointer */
mov r7, a2 /* Null frame pointer for Thumb */
ldr r1, .LC1 /* Start of memory block */
ldr r3, .LC2 /* End of memory block */
subs r3, r3, r1 /* Length of block */
beq .end_clear_loop
mov r2, #0
.clear_loop:
strb r2, [r1], #1
subs r3, r3, #1
bgt .clear_loop
.end_clear_loop:
/* Initialise data. */
ldr r1, .LC3 /* Start of memory block */
ldr r2, .LC4 /* End of memory block */
ldr r3, .LC5
subs r3, r3, r1 /* Length of block */
beq .end_set_loop
.set_loop:
ldrb r4, [r2], #1
strb r4, [r1], #1
subs r3, r3, #1
bgt .set_loop
.end_set_loop:
mov r0, #0 /* no arguments */
mov r1, #0 /* no argv either */
bl main
endless_loop:
b endless_loop
.align 0
.LC1:
.word __bss_beg__
.LC2:
.word __bss_end__
.LC3:
.word __data_beg__
.LC4:
.word __data_beg_src__
.LC5:
.word __data_end__
.LC6:
.word __stack_end__
/*********************** END Clear BSS ******************************/
/******************** Ìøתµ½ main() ********************/
LDR R0, =main /* »ñµÃmain()Èë¿ÚµØÖ· */
BX R0 /* ³¤Ìøתµ½main() */
/******************** Ìøתµ½ main() ********************/
/* ±¾¶ÎΪ.startup¶Î ÔÚÁ´½Ó½Å±¾Öб»Á´½Óµ½³ÌÐò×ͷ */
.section .startup,"ax"
.code 32
.align 0
ldr pc, __start /* reset - _start */
ldr pc, _undf /* undefined - _undf */
ldr pc, _swi /* SWI - _swi */
ldr pc, _pabt /* program abort - _pabt */
ldr pc, _dabt /* data abort - _dabt */
//.word 0xB9205F80 /* ĬÈÏ 0xB9205F80 */
.word 0xB8A06F58 /* 0xB8A06F58 ȫΪ */
ldr pc, __IRQ_Handler /* IRQ - read the VIC */
ldr pc, _fiq /* FIQ - _fiq */
__start:.word _start
_undf: .word __undf /* undefined */
_swi: .word __swi /* SWI */
_pabt: .word __pabt /* program abort */
_dabt: .word __dabt /* data abort */
temp1: .word 0
__IRQ_Handler: .word IRQ_Handler
_fiq: .word __fiq /* FIQ */
__undf: b . /* undefined */
__swi : b .
__pabt: b . /* program abort */
__dabt: b . /* data abort */
__fiq : b . /* FIQ */
/* IRQÈë¿Ú */
IRQ_Handler :
stmfd sp!, {r0-r12,lr} /* ÔR0 ¨C R12£¬LR¼Ä´æÆ÷ѹջ */
bl rt_interrupt_enter /* ֪ͨRT-Thread½øÈëÖÐÏģʽ */
bl rt_hw_trap_irq /* ÏàÓ¦ÖÐÏ·þÎñÀý³Ì´¦Àí */
bl rt_interrupt_leave /* ; ֪ͨRT-ThreadÒªÀ뿪ÖжÏģʽ */
/* Èç¹ûÉèÖÃÁËrt_thread_switch_interrput_flag£¬½øÐÐÖжÏÖеÄÏß³ÌÉÏÏÂÎÄ´¦Àí */
ldr r0, =rt_thread_switch_interrput_flag
ldr r1, [r0]
cmp r1, #1
beq rt_hw_context_switch_interrupt_do /* ÖÐÏÖÐÇл»·¢Éú */
/* Èç¹ûÌøתÁË£¬½«²»»á»ØÀ´ */
ldmfd sp!, {r0-r12,lr} /* »Ö¸´Õ» */
subs pc, lr, #4 /* ´ÓIRQÖзµ»Ø */
/*
* void rt_hw_context_switch_interrupt_do(rt_base_t flag)
* ÖÐϽáÊøºóµÄÉÏÏÂÎÄÇл»
*/
rt_hw_context_switch_interrupt_do:
mov r1, #0 /* clear flag */
/* Çå³þÖжÏÖÐÇл»±êÖ¾ */
str r1, [r0] /* */
ldmfd sp!, {r0-r12,lr}/* reload saved registers */
/* ÏȻָ´±»ÖжÏÏ̵߳ÄÉÏÏÂÎÄ */
stmfd sp!, {r0-r3} /* save r0-r3 */
/* ¶ÔR0 ¨C R3ѹջ£¬ÒòΪºóÃæ»áÓõ½ */
mov r1, sp /* °Ñ´Ë´¦µÄÕ»Öµ±£´æµ½R1 */
add sp, sp, #16 /* restore sp */
/* »Ö¸´IRQµÄÕ»£¬ºóÃæ»áÌø³öIRQģʽ */
sub r2, lr, #4 /* save old task's pc to r2 */
/* ±£´æÇл»³öÏ̵߳ÄPCµ½R2 */
mrs r3, spsr /* disable interrupt ±£´æÖÐÏÇ°µÄCPSRµ½R3¼Ä´æÆ÷ */
/* »ñµÃSPSR¼Ä´æÆ÷Öµ */
orr r0, r3, #I_BIT|F_BIT
msr spsr_c, r0 /* ¹Ø±ÕSPSRÖеÄIRQ/FIQÖÐÏ */
ldr r0, =.+8 /* °Ñµ±Ç°µØÖ·+8ÔØÈëµ½R0¼Ä´æÆ÷ÖÐ switch to interrupted task's stack */
movs pc, r0 /* Í˳öIRQģʽ£¬ÓÉÓÚSPSR±»ÉèÖóɹØÖÐÏģʽ */
/* ËùÒÔ´ÓIRQ·µ»Øºó£¬ÖÐϲ¢Ã»Óдò¿ª
; R0¼Ä´æÆ÷ÖеÄλÖÃʵ¼Ê¾ÍÊÇÏÂÒ»ÌõÖ¸Á
; ¼´PC¼ÌÐøÍùÏÂ×ß
; ´Ëʱ
; ģʽÒѾ­»»³ÉÖжÏÇ°µÄSVCģʽ£¬
; SP¼Ä´æÆ÷Ò²ÊÇSVCģʽϵÄÕ»¼Ä´æÆ÷
; R1±£´æIRQģʽϵÄÕ»Ö¸Õë
; R2±£´æÇл»³öÏ̵߳ÄPC
; R3±£´æÇл»³öÏ̵߳ÄCPSR */
stmfd sp!, {r2} /* push old task's pc */
/* ±£´æÇл»³öÈÎÎñµÄPC */
stmfd sp!, {r4-r12,lr}/* push old task's lr,r12-r4 */
/* ±£´æR4 ¨C R12£¬LR¼Ä´æÆ÷ */
mov r4, r1 /* Special optimised code below */
/* R1±£´æÓÐѹջR0 ¨C R3´¦µÄջλÖà */
mov r5, r3 /* R3Çл»³öÏ̵߳ÄCPSR */
ldmfd r4!, {r0-r3} /* »Ö¸´R0 ¨C R3 */
stmfd sp!, {r0-r3} /* push old task's r3-r0 */
/* R0 ¨C R3ѹջµ½Çл»³öÏß³Ì */
stmfd sp!, {r5} /* push old task's psr */
/* Çл»³öÏß³ÌCPSRѹջ */
mrs r4, spsr
stmfd sp!, {r4} /* push old task's spsr */
/* Çл»³öÏß³ÌSPSRѹջ */
ldr r4, =rt_interrupt_from_thread
ldr r5, [r4]
str sp, [r5] /* store sp in preempted tasks's TCB */
/* ±£´æÇл»³öÏ̵߳ÄSPÖ¸Õë */
ldr r6, =rt_interrupt_to_thread
ldr r6, [r6]
ldr sp, [r6] /* get new task's stack pointer */
/* »ñµÃÇл»µ½Ï̵߳ÄÕ» */
ldmfd sp!, {r4} /* pop new task's spsr */
/* »Ö¸´SPSR */
msr SPSR_cxsf, r4
ldmfd sp!, {r4} /* pop new task's psr */
/* »Ö¸´CPSR */
msr CPSR_cxsf, r4
ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
/* »Ö¸´R0 ¨C R12£¬LR¼°PC¼Ä´æÆ÷ */
/* ´úÂë¼ÓÃܹ¦ÄÜ */
#if defined(CODE_PROTECTION)
.org 0x01FC
.word 0x87654321
#endif