xref: /nrf52832-nimble/rt-thread/libcpu/arm/lpc214x/startup_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero/*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date           Author       Notes
8*10465441SEvalZero */
9*10465441SEvalZero	.extern main                               /* 引入外部C入口 */
10*10465441SEvalZero
11*10465441SEvalZero	.extern rt_interrupt_enter
12*10465441SEvalZero	.extern rt_interrupt_leave
13*10465441SEvalZero	.extern rt_thread_switch_interrupt_flag
14*10465441SEvalZero	.extern rt_interrupt_from_thread
15*10465441SEvalZero	.extern rt_interrupt_to_thread
16*10465441SEvalZero	.extern rt_hw_trap_irq
17*10465441SEvalZero
18*10465441SEvalZero	.global start
19*10465441SEvalZero	.global endless_loop
20*10465441SEvalZero    .global rt_hw_context_switch_interrupt_do
21*10465441SEvalZero
22*10465441SEvalZero	/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
23*10465441SEvalZero    .set  MODE_USR, 0x10            /* User Mode */
24*10465441SEvalZero    .set  MODE_FIQ, 0x11            /* FIQ Mode */
25*10465441SEvalZero    .set  MODE_IRQ, 0x12            /* IRQ Mode */
26*10465441SEvalZero    .set  MODE_SVC, 0x13            /* Supervisor Mode */
27*10465441SEvalZero    .set  MODE_ABT, 0x17            /* Abort Mode */
28*10465441SEvalZero    .set  MODE_UND, 0x1B            /* Undefined Mode */
29*10465441SEvalZero    .set  MODE_SYS, 0x1F            /* System Mode */
30*10465441SEvalZero
31*10465441SEvalZero    .equ  I_BIT, 0x80               /* when I bit is set, IRQ is disabled */
32*10465441SEvalZero    .equ  F_BIT, 0x40               /* when F bit is set, FIQ is disabled */
33*10465441SEvalZero    .equ  I_Bit, 0x80               /* when I bit is set, IRQ is disabled */
34*10465441SEvalZero    .equ  F_Bit, 0x40               /* when F bit is set, FIQ is disabled */
35*10465441SEvalZero
36*10465441SEvalZero    /* VPBDIV definitions*/
37*10465441SEvalZero    .equ  VPBDIV, 		0xE01FC100
38*10465441SEvalZero    .set  VPBDIV_VALUE,	0x00000000
39*10465441SEvalZero
40*10465441SEvalZero    /* Phase Locked Loop (PLL) definitions*/
41*10465441SEvalZero    .equ  PLL_BASE, 	 0xE01FC080  /* PLL Base Address */
42*10465441SEvalZero    .equ  PLLCON_OFS, 	 0x00        /* PLL Control Offset */
43*10465441SEvalZero    .equ  PLLCFG_OFS, 	 0x04        /* PLL Configuration Offset */
44*10465441SEvalZero    .equ  PLLSTAT_OFS, 	 0x08        /* PLL Status Offset */
45*10465441SEvalZero    .equ  PLLFEED_OFS,   0x0C        /* PLL Feed Offset */
46*10465441SEvalZero	.equ  PLLCON_PLLE,   (1<<0)      /* PLL Enable */
47*10465441SEvalZero	.equ  PLLCON_PLLC,   (1<<1)      /* PLL Connect */
48*10465441SEvalZero	.equ  PLLCFG_MSEL,   (0x1F<<0)   /* PLL Multiplier */
49*10465441SEvalZero	.equ  PLLCFG_PSEL,   (0x03<<5)   /* PLL Divider */
50*10465441SEvalZero	.equ  PLLSTAT_PLOCK, (1<<10)     /* PLL Lock Status */
51*10465441SEvalZero    .equ  PLLCFG_Val,	 0x00000024  /* <o1.0..4>   MSEL: PLL Multiplier Selection,<o1.5..6>   PSEL: PLL Divider Selection */
52*10465441SEvalZero
53*10465441SEvalZero    .equ  MEMMAP,		0xE01FC040     /*Memory Mapping Control*/
54*10465441SEvalZero
55*10465441SEvalZero
56*10465441SEvalZero    /* Memory Accelerator Module (MAM) definitions*/
57*10465441SEvalZero    .equ  MAM_BASE, 	0xE01FC000
58*10465441SEvalZero    .equ  MAMCR_OFS, 	0x00
59*10465441SEvalZero    .equ  MAMTIM_OFS, 	0x04
60*10465441SEvalZero    .equ  MAMCR_Val,    0x00000002
61*10465441SEvalZero    .equ  MAMTIM_Val,   0x00000004
62*10465441SEvalZero
63*10465441SEvalZero    .equ  VICIntEnClr,	0xFFFFF014
64*10465441SEvalZero    .equ  VICIntSelect,	0xFFFFF00C
65*10465441SEvalZero/************* 目标配置结束 *************/
66*10465441SEvalZero
67*10465441SEvalZero
68*10465441SEvalZero/* Setup the operating mode & stack.*/
69*10465441SEvalZero/* --------------------------------- */
70*10465441SEvalZero	.global _reset
71*10465441SEvalZero_reset:
72*10465441SEvalZero	.code 32
73*10465441SEvalZero	.align 0
74*10465441SEvalZero
75*10465441SEvalZero/************************* PLL_SETUP **********************************/
76*10465441SEvalZero		ldr     r0, =PLL_BASE
77*10465441SEvalZero		mov		r1, #0xAA
78*10465441SEvalZero		mov		r2, #0x55
79*10465441SEvalZero
80*10465441SEvalZero/* Configure and Enable PLL */
81*10465441SEvalZero		mov     r3, #PLLCFG_Val
82*10465441SEvalZero		str     r3, [r0, #PLLCFG_OFS]
83*10465441SEvalZero		mov     r3, #PLLCON_PLLE
84*10465441SEvalZero		str     r3, [r0, #PLLCON_OFS]
85*10465441SEvalZero		str     r1, [r0, #PLLFEED_OFS]
86*10465441SEvalZero		str     r2, [r0, #PLLFEED_OFS]
87*10465441SEvalZero
88*10465441SEvalZero/*  Wait until PLL Locked */
89*10465441SEvalZeroPLL_Locked_loop:
90*10465441SEvalZero		ldr     r3, [r0, #PLLSTAT_OFS]
91*10465441SEvalZero		ands    r3, r3, #PLLSTAT_PLOCK
92*10465441SEvalZero		beq     PLL_Locked_loop
93*10465441SEvalZero
94*10465441SEvalZero/*  Switch to PLL Clock */
95*10465441SEvalZero		mov     r3, #(PLLCON_PLLE|PLLCON_PLLC)
96*10465441SEvalZero		str     r3, [r0, #PLLCON_OFS]
97*10465441SEvalZero		str     r1, [r0, #PLLFEED_OFS]
98*10465441SEvalZero		str     R2, [r0, #PLLFEED_OFS]
99*10465441SEvalZero/************************* PLL_SETUP **********************************/
100*10465441SEvalZero
101*10465441SEvalZero/************************ Setup VPBDIV ********************************/
102*10465441SEvalZero		ldr		r0, =VPBDIV
103*10465441SEvalZero		ldr     r1, =VPBDIV_VALUE
104*10465441SEvalZero		str		r1, [r0]
105*10465441SEvalZero/************************ Setup VPBDIV ********************************/
106*10465441SEvalZero
107*10465441SEvalZero/************** Setup MAM **************/
108*10465441SEvalZero		ldr		r0, =MAM_BASE
109*10465441SEvalZero		mov		r1, #MAMTIM_Val
110*10465441SEvalZero		str		r1, [r0, #MAMTIM_OFS]
111*10465441SEvalZero		mov		r1, #MAMCR_Val
112*10465441SEvalZero		str		r1, [r0, #MAMCR_OFS]
113*10465441SEvalZero/************** Setup MAM **************/
114*10465441SEvalZero
115*10465441SEvalZero/************************ setup stack *********************************/
116*10465441SEvalZero    ldr   r0, .undefined_stack_top
117*10465441SEvalZero	sub   r0, r0, #4
118*10465441SEvalZero    msr   CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */
119*10465441SEvalZero    mov   sp, r0
120*10465441SEvalZero
121*10465441SEvalZero    ldr   r0, .abort_stack_top
122*10465441SEvalZero	sub   r0, r0, #4
123*10465441SEvalZero    msr   CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
124*10465441SEvalZero    mov   sp, r0
125*10465441SEvalZero
126*10465441SEvalZero    ldr   r0, .fiq_stack_top
127*10465441SEvalZero	sub   r0, r0, #4
128*10465441SEvalZero    msr   CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
129*10465441SEvalZero    mov   sp, r0
130*10465441SEvalZero
131*10465441SEvalZero    ldr   r0, .irq_stack_top
132*10465441SEvalZero	sub   r0, r0, #4
133*10465441SEvalZero    msr   CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
134*10465441SEvalZero    mov   sp, r0
135*10465441SEvalZero
136*10465441SEvalZero    ldr   r0, .svc_stack_top
137*10465441SEvalZero	sub   r0, r0, #4
138*10465441SEvalZero    msr   CPSR_c, #MODE_SVC|I_BIT|F_BIT  /* Supervisor Mode */
139*10465441SEvalZero    mov   sp, r0
140*10465441SEvalZero/************************ setup stack ********************************/
141*10465441SEvalZero
142*10465441SEvalZero    /* copy .data to SRAM */
143*10465441SEvalZero    ldr     r1, =_sidata            /* .data start in image */
144*10465441SEvalZero    ldr     r2, =_edata             /* .data end in image   */
145*10465441SEvalZero    ldr     r3, =_sdata             /* sram data start      */
146*10465441SEvalZerodata_loop:
147*10465441SEvalZero    ldr     r0, [r1, #0]
148*10465441SEvalZero    str     r0, [r3]
149*10465441SEvalZero
150*10465441SEvalZero    add     r1, r1, #4
151*10465441SEvalZero    add     r3, r3, #4
152*10465441SEvalZero
153*10465441SEvalZero    cmp     r3, r2                   /* check if data to clear */
154*10465441SEvalZero    blo     data_loop                /* loop until done        */
155*10465441SEvalZero
156*10465441SEvalZero    /* clear .bss */
157*10465441SEvalZero    mov     r0,#0                   /* get a zero */
158*10465441SEvalZero    ldr     r1,=__bss_start         /* bss start  */
159*10465441SEvalZero    ldr     r2,=__bss_end           /* bss end    */
160*10465441SEvalZero
161*10465441SEvalZerobss_loop:
162*10465441SEvalZero    cmp     r1,r2                   /* check if data to clear */
163*10465441SEvalZero    strlo   r0,[r1],#4              /* clear 4 bytes          */
164*10465441SEvalZero    blo     bss_loop                /* loop until done        */
165*10465441SEvalZero
166*10465441SEvalZero
167*10465441SEvalZero    /* call C++ constructors of global objects */
168*10465441SEvalZero    ldr     r0, =__ctors_start__
169*10465441SEvalZero    ldr     r1, =__ctors_end__
170*10465441SEvalZero
171*10465441SEvalZeroctor_loop:
172*10465441SEvalZero    cmp     r0, r1
173*10465441SEvalZero    beq     ctor_end
174*10465441SEvalZero    ldr     r2, [r0], #4
175*10465441SEvalZero    stmfd   sp!, {r0-r1}
176*10465441SEvalZero    mov     lr, pc
177*10465441SEvalZero    bx      r2
178*10465441SEvalZero    ldmfd   sp!, {r0-r1}
179*10465441SEvalZero    b       ctor_loop
180*10465441SEvalZeroctor_end:
181*10465441SEvalZero
182*10465441SEvalZero	/* enter C code */
183*10465441SEvalZero	bl		main
184*10465441SEvalZero
185*10465441SEvalZero	.align 0
186*10465441SEvalZero	.undefined_stack_top:
187*10465441SEvalZero	.word   _undefined_stack_top
188*10465441SEvalZero	.abort_stack_top:
189*10465441SEvalZero	.word   _abort_stack_top
190*10465441SEvalZero	.fiq_stack_top:
191*10465441SEvalZero	.word   _fiq_stack_top
192*10465441SEvalZero	.irq_stack_top:
193*10465441SEvalZero	.word   _irq_stack_top
194*10465441SEvalZero	.svc_stack_top:
195*10465441SEvalZero	.word   _svc_stack_top
196*10465441SEvalZero/*********************** END Clear BSS  ******************************/
197*10465441SEvalZero
198*10465441SEvalZero.section .init,"ax"
199*10465441SEvalZero.code 32
200*10465441SEvalZero.align 0
201*10465441SEvalZero.globl _start
202*10465441SEvalZero_start:
203*10465441SEvalZero
204*10465441SEvalZero	ldr   pc, __start					/* reset - _start			*/
205*10465441SEvalZero	ldr   pc, _undf						/* undefined - _undf		*/
206*10465441SEvalZero	ldr   pc, _swi			    		/* SWI - _swi				*/
207*10465441SEvalZero	ldr   pc, _pabt						/* program abort - _pabt	*/
208*10465441SEvalZero	ldr   pc, _dabt						/* data abort - _dabt		*/
209*10465441SEvalZero	.word 0xB8A06F58					/* reserved                 */
210*10465441SEvalZero	ldr   pc, __IRQ_Handler				/* IRQ - read the VIC		*/
211*10465441SEvalZero	ldr   pc, _fiq						/* FIQ - _fiq				*/
212*10465441SEvalZero
213*10465441SEvalZero__start:.word _reset
214*10465441SEvalZero_undf:  .word __undf                    /* undefined				*/
215*10465441SEvalZero_swi:   .word __swi                     /* SWI						*/
216*10465441SEvalZero_pabt:  .word __pabt                    /* program abort			*/
217*10465441SEvalZero_dabt:  .word __dabt                    /* data abort				*/
218*10465441SEvalZerotemp1:  .word 0
219*10465441SEvalZero__IRQ_Handler:  .word IRQ_Handler
220*10465441SEvalZero_fiq:   .word __fiq                     /* FIQ						*/
221*10465441SEvalZero
222*10465441SEvalZero__undf: b     .                         /* undefined				*/
223*10465441SEvalZero__swi : b     .
224*10465441SEvalZero__pabt: b     .                         /* program abort			*/
225*10465441SEvalZero__dabt: b     .                         /* data abort				*/
226*10465441SEvalZero__fiq : b     .  					    /* FIQ						*/
227*10465441SEvalZero
228*10465441SEvalZero/* IRQ入口 */
229*10465441SEvalZeroIRQ_Handler :
230*10465441SEvalZero		stmfd	sp!, {r0-r12,lr} 			   /* 对R0 – R12,LR寄存器压栈      */
231*10465441SEvalZero		bl	rt_interrupt_enter	 			   /* 通知RT-Thread进入中断模式     */
232*10465441SEvalZero		bl	rt_hw_trap_irq		 			   /* 相应中断服务例程处理  	    */
233*10465441SEvalZero		bl	rt_interrupt_leave		           /* ; 通知RT-Thread要离开中断模式 */
234*10465441SEvalZero
235*10465441SEvalZero		/* 如果设置了rt_thread_switch_interrupt_flag,进行中断中的线程上下文处理 */
236*10465441SEvalZero		ldr	r0, =rt_thread_switch_interrupt_flag
237*10465441SEvalZero		ldr	r1, [r0]
238*10465441SEvalZero		cmp	r1, #1
239*10465441SEvalZero		beq	rt_hw_context_switch_interrupt_do  /* 中断中切换发生 */
240*10465441SEvalZero											   /* 如果跳转了,将不会回来 */
241*10465441SEvalZero		ldmfd	sp!, {r0-r12,lr}			   /* 恢复栈 */
242*10465441SEvalZero		subs	pc, lr, #4					   /* 从IRQ中返回 */
243*10465441SEvalZero
244*10465441SEvalZero/*
245*10465441SEvalZero* void rt_hw_context_switch_interrupt_do(rt_base_t flag)
246*10465441SEvalZero* 中断结束后的上下文切换
247*10465441SEvalZero*/
248*10465441SEvalZerort_hw_context_switch_interrupt_do:
249*10465441SEvalZero				mov	r1,  #0				/* clear flag */
250*10465441SEvalZero										/* 清楚中断中切换标志 */
251*10465441SEvalZero				str	r1,  [r0]			/* */
252*10465441SEvalZero
253*10465441SEvalZero				ldmfd	sp!, {r0-r12,lr}/* reload saved registers */
254*10465441SEvalZero										/* 先恢复被中断线程的上下文 */
255*10465441SEvalZero				stmfd	sp!, {r0-r3}	/* save r0-r3 */
256*10465441SEvalZero										/* 对R0 – R3压栈,因为后面会用到 */
257*10465441SEvalZero				mov	r1,  sp				/* 把此处的栈值保存到R1 */
258*10465441SEvalZero				add	sp,  sp, #16		/* restore sp */
259*10465441SEvalZero										/* 恢复IRQ的栈,后面会跳出IRQ模式 */
260*10465441SEvalZero				sub	r2,  lr, #4			/* save old task's pc to r2 */
261*10465441SEvalZero										/* 保存切换出线程的PC到R2 */
262*10465441SEvalZero
263*10465441SEvalZero				mrs	r3,  spsr			/* disable interrupt 保存中断前的CPSR到R3寄存器 */
264*10465441SEvalZero										/* 获得SPSR寄存器值 */
265*10465441SEvalZero				orr	r0,  r3, #I_BIT|F_BIT
266*10465441SEvalZero				msr	spsr_c, r0			/*  关闭SPSR中的IRQ/FIQ中断 */
267*10465441SEvalZero
268*10465441SEvalZero				ldr	r0,  =.+8		    /* 把当前地址+8载入到R0寄存器中 switch to interrupted task's stack */
269*10465441SEvalZero				movs pc,  r0            /* 退出IRQ模式,由于SPSR被设置成关中断模式 */
270*10465441SEvalZero										/* 所以从IRQ返回后,中断并没有打开
271*10465441SEvalZero										; R0寄存器中的位置实际就是下一条指令,
272*10465441SEvalZero										; 即PC继续往下走
273*10465441SEvalZero										; 此时
274*10465441SEvalZero										; 模式已经换成中断前的SVC模式,
275*10465441SEvalZero										; SP寄存器也是SVC模式下的栈寄存器
276*10465441SEvalZero										; R1保存IRQ模式下的栈指针
277*10465441SEvalZero										; R2保存切换出线程的PC
278*10465441SEvalZero										; R3保存切换出线程的CPSR */
279*10465441SEvalZero				stmfd	sp!, {r2}		/* push old task's pc */
280*10465441SEvalZero										/* 保存切换出任务的PC */
281*10465441SEvalZero				stmfd	sp!, {r4-r12,lr}/* push old task's lr,r12-r4 */
282*10465441SEvalZero										/* 保存R4 – R12,LR寄存器 */
283*10465441SEvalZero				mov	r4,  r1				/* Special optimised code below */
284*10465441SEvalZero										/* R1保存有压栈R0 – R3处的栈位置 */
285*10465441SEvalZero				mov	r5,  r3				/* R3切换出线程的CPSR */
286*10465441SEvalZero				ldmfd	r4!, {r0-r3}	/* 恢复R0 – R3 */
287*10465441SEvalZero				stmfd	sp!, {r0-r3}	/* push old task's r3-r0 */
288*10465441SEvalZero										/*  R0 – R3压栈到切换出线程 */
289*10465441SEvalZero				stmfd	sp!, {r5}		/* push old task's psr */
290*10465441SEvalZero										/* 切换出线程CPSR压栈 */
291*10465441SEvalZero				mrs	r4,  spsr
292*10465441SEvalZero				stmfd	sp!, {r4}		/* push old task's spsr */
293*10465441SEvalZero										/* 切换出线程SPSR压栈 */
294*10465441SEvalZero
295*10465441SEvalZero				ldr	r4,  =rt_interrupt_from_thread
296*10465441SEvalZero				ldr	r5,  [r4]
297*10465441SEvalZero				str	sp,  [r5]			/* store sp in preempted tasks's TCB */
298*10465441SEvalZero										/* 保存切换出线程的SP指针 */
299*10465441SEvalZero
300*10465441SEvalZero				ldr	r6,  =rt_interrupt_to_thread
301*10465441SEvalZero				ldr	r6,  [r6]
302*10465441SEvalZero				ldr	sp,  [r6]			/* get new task's stack pointer */
303*10465441SEvalZero										/* 获得切换到线程的栈 */
304*10465441SEvalZero
305*10465441SEvalZero				ldmfd	sp!, {r4}		/* pop new task's spsr */
306*10465441SEvalZero										/* 恢复SPSR */
307*10465441SEvalZero				msr	SPSR_cxsf, r4
308*10465441SEvalZero				ldmfd	sp!, {r4}		/* pop new task's psr */
309*10465441SEvalZero										/* 恢复CPSR */
310*10465441SEvalZero				msr	CPSR_cxsf, r4
311*10465441SEvalZero
312*10465441SEvalZero				ldmfd	sp!, {r0-r12,lr,pc}	/* pop new task's r0-r12,lr & pc */
313*10465441SEvalZero											/* 恢复R0 – R12,LR及PC寄存器 */
314*10465441SEvalZero
315*10465441SEvalZero/* 代码加密功能 */
316*10465441SEvalZero#if defined(CODE_PROTECTION)
317*10465441SEvalZero.org 0x01FC
318*10465441SEvalZero.word 0x87654321
319*10465441SEvalZero#endif
320*10465441SEvalZero
321