CMSIS2000  0.0.7
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
startup_LPC2xxx.S
Go to the documentation of this file.
1 /*
2  * CMSIS2000
3  * CMSIS-like sources for LPC2xxx series MCUs
4  *
5  * (C) Copyright 2011-2012, Dmitriy Cherepanov, All Rights Reserved
6  *
7  * Version: 0.0.7
8  * Date of the Last Update: 2013-03-04
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a copy
11  * of this software and associated documentation files (the "Software"), to
12  * deal in the Software without restriction, including without limitation the
13  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
14  * sell copies of the Software, and to permit persons to whom the Software is
15  * furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included in
18  * all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26  * IN THE SOFTWARE.
27  *
28  * Do not be lasy! For the latest version see http://irtos.sourceforge.net .
29  *
30  *
31 #*/
32 /*******************************************************************************
33  startup.s STARTUP ASSEMBLY CODE
34  -----------------------
35  Module includes the interrupt vectors and start-up code.
36 ***************************************************************************** */
37 #define TO_STRING_STRP2(x) #x
38 #define TO_STRING_STRP(x) TO_STRING_STRP2(x)
39 
40 #ifdef STARTUP_LPC_STACK_CFG
41  #include TO_STRING_STRP(STARTUP_LPC_STACK_CFG)
42 #else
43  #include "startup_lpc_stack_generic.h"
44 #endif
45 
46 
47 
49  .type ExitFromMain_Handler, %function
50  .extern main // int main(void)
51  .extern exit
52  .global _etext // -> .data initial values in ROM
53  .global __data_start // -> .data area in RAM
54  .global __data_end // end of .data area
55  .global __bss_start // -> .bss area in RAM
56  .global __bss_end // end of .bss area
57  .global _stack // top of stack
58  .extern __ram_code_load
59  .extern __ram_code_start
60  .extern __ram_code_end
61 /*----------------------------------------------------------------------------*/
62 /* Stack Sizes must fit in one byte */
63 #ifndef UND_STACK_SIZE
64 #define UND_STACK_SIZE 0x00000000 /*stack for "undefined instruction" interrupts is 0 bytes */
65 #endif
66 #ifndef ABT_STACK_SIZE
67 #define ABT_STACK_SIZE 0x00000000 /* stack for "abort" interrupts is 0 bytes */
68 #endif
69 #ifndef FIQ_STACK_SIZE
70 #define FIQ_STACK_SIZE 0x00000000 /* stack for "FIQ" interrupts is 0 bytes */
71 #endif
72 #ifndef IRQ_STACK_SIZE
73 #define IRQ_STACK_SIZE 0x00000100 /* stack for "IRQ" normal interrupts is 0x100 bytes */
74 #endif
75 #ifndef SVC_STACK_SIZE
76 #define SVC_STACK_SIZE 0x00000008 /* stack for "SVC" supervisor mode is 4 bytes */
77 #endif
78 /*----------------------------------------------------------------------------*/
79 /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */
80 #define I_BIT 0x80 /*when I bit is set, IRQ is disabled (program status registers)*/
81 #define F_BIT 0x40 /*when F bit is set, FIQ is disabled (program status registers)*/
82 
83 #define MODE_USR 0x10 /* Normal User Mode */
84 #define MODE_FIQ 0x11 /* FIQ Processing Fast Interrupts Mode */
85 #define MODE_IRQ 0x12 /* IRQ Processing Standard Interrupts Mode */
86 #define MODE_SVC 0x13 /* Supervisor Processing Software Interrupts Mode */
87 #define MODE_ABT 0x17 /* Abort Processing memory Faults Mode */
88 #define MODE_UND 0x1B /* Undefined Processing Undefined Instructions Mode */
89 #define MODE_SYS 0x1F /* System Running Priviledged Operating System Tasks Mode*/
90 #ifndef __PORT_ARM_MODE_MAIN__
91  #define __PORT_ARM_MODE_MAIN__ 0
92 #endif
93 #if __PORT_ARM_MODE_MAIN__ > 0
94  #if ((__PORT_ARM_MODE_MAIN__ == (MODE_SYS|I_BIT|F_BIT) ) || (__PORT_ARM_MODE_MAIN__ == (MODE_USR|I_BIT|F_BIT) ))
96  #else
98  #define PORT_ARM_MAIN_MODE2 __PORT_ARM_MODE_MAIN__
99  #endif
100 #else
102 #endif
103 /*----------------------------------------------------------------------------*/
104 /*----------DEFENITIONS FOR UNIVERSAL VECTOR TABLE -------------------------*/
105 #ifndef i_MCU_MODEL
106  #define i_MCU_MODEL 2103
107 #endif
108 
109 #ifndef port_SELF_COPY_VECTORS
110  #define port_SELF_COPY_VECTORS 0
111 #endif
112 #ifndef port_HAS_COMMON_IRQ_HANDLER
113  #define port_HAS_COMMON_IRQ_HANDLER 0
114 #endif
115 
116 #define CPU_PIPELINE_STAGES 3 /*to calculate offset*/
117 #define INSTRUCTION_SIZE 4 /*to calculate offset*/
118 /*----------------------------------------------------------------------------*/
119 .section .text.vectors,"ax"
120  .code 32
121  .arm
122  .align 0
123 
124 .global _vectors
125 .global __isr_vector
126 .global _vectors_start
127 .global _vectors_end
128 .global start
129 .func _vectors
130 
131 _vectors:
133 _vectors_start:
134 #if (port_SELF_COPY_VECTORS == 0)
135  _vectors_end: /*let size of allocatig mem in ram be zero*/
136 #endif
137 start:
138 /*-------------- Interrupt Vectors -------------------------------------------*/
139 _vectors_here:
140  B self_copy
141 #if (port_HAS_COMMON_IRQ_HANDLER > 0)
142  LDR PC, Undef_Addr /*;is LDR PC,[PC+const1]*/
143 copy_vectors_from_here:
144 #else
145 copy_vectors_from_here:
146  LDR PC, Undef_Addr /*;is LDR PC,[PC+const1]*/
147 #endif
148  LDR PC, SWI_Addr /*;is LDR PC,[PC+const2]*/
149  LDR PC, PAbt_Addr /*;is LDR PC,[PC+const3]*/
150  LDR PC, DAbt_Addr /*;is LDR PC,[PC+const4]*/
151 #if (port_HAS_COMMON_IRQ_HANDLER > 0) /* IF THERE IS ROUTINE JUMP TO TABLE*/
152  /* calculated to crc check sum*/
153  .word 0xB4405F39 /* Reserved Vector (holds Philips ISP checksum) */
154  LDR PC, IRQ_Addr /*; Vector from IRQ_Addr*/
155 #else
156  #if i_MCU_MODEL >= 2300
157  /* calculated to crc check sum*/
158 /* see page 71 of "Insiders Guide to the Philips ARM7-Based Microcontrollers" by Trevor Martin*/
159  .word 0xB4C05E63 /* Reserved Vector (holds Philips ISP checksum) */
160  LDR PC, [PC, # -0x0120] /*; Vector from VicVectAddr from PL192*/
161  #else
162  /* calculated to crc check sum*/
163  .word 0xB4C04F55 /* Reserved Vector (holds Philips ISP checksum) */
164  LDR PC, [PC, # -0x0FF0] /*; Vector from VicVectAddr from PL190*/
165  #endif
166 #endif /*port_HAS_COMMON_IRQ_HANDLER*/
167  LDR PC, FIQ_Addr
168 /** \note By the way FIQ_HANDLER can be runned right here instead of ldr PC, FIQ_Addr*/
169 /*----------------JUMP_TABLE -------------------------------------------------*/
170 /* Undefined Instruction vector Address MUST BE ONLY AFTER RESET vector Address !!!! */
171 /* SWI_Addr Instruction vector Address MUST BE ONLY
172  * AFTER Undefined vector Address --const1 MUST BE EQUAL const2 !!!!! */
173 RES_Addr: .word Reset_Handler /* defined in this module below*/
174 Undef_Addr: .word UNDEF_Handler /* defined in portISR.c */
175 SWI_Addr: .word SWI_Handler /* defined in portISR.c */
176 PAbt_Addr: .word PAbort_Handler /* defined in portISR.c */
177 DAbt_Addr: .word DAbort_Handler /* defined in portISR.c */
178 #if (port_HAS_COMMON_IRQ_HANDLER > 0)
179  IRQ_Addr: .word IRQ_Handler /* defined external */
180 #endif
181 FIQ_Addr: .word FIQ_Handler /* defined in main.c */
182 #if (port_SELF_COPY_VECTORS != 0)
183  _vectors_end:
184 #endif
185 /*----------------------------------------------------------------------------*/
186 MEMMAP_ADDR: .word 0xE01FC040
187 self_copy:
188 /** @fn void sc_here()
189  * @brief Self copy vector table function
190 ----------------RESET COPYNG TABLE FUNCTION --------------------------------*/
191 /* TABLE SIZE TO COPY IS 8 + (8-1) if port_HAS_COMMON_IRQ_HANDLER */
192 /* TABLE SIZE TO COPY IS 8 + (8-1-1) if port HAS NO IRQ ROUTINE */
193 sc_here:
194 #if (port_SELF_COPY_VECTORS != 0) /*calculate copy_vectors_from_here*/
195  SUBS R14,PC,#(sc_here-copy_vectors_from_here+(CPU_PIPELINE_STAGES-1)*INSTRUCTION_SIZE)
196  LDR R13,=0x40000000
197  /* HERE REZAULT MUST BE NOT ZERO ALL 'EQ' instuctions wil be passed by
198  * AND NE will be executed
199  */
200 #else
201  //calculate start of _vectors_here
202  SUBS R14,PC,#(sc_here-_vectors_here+(CPU_PIPELINE_STAGES-1)*INSTRUCTION_SIZE)
203  /* next is very optimized code it cmp start _vectors_here with
204  0x00000000, 0x40000000 0x80000000 */
205  BEQ STORE_MEMMAP /*do not need to copy we are at the flash */
206  LDR R13,=0x80000000 /*dst address*/
207  CMP R14,R13
208  /* if we are at the 0x800 then skip next instruction*/
209  MOVNE R13,R13,LSR #1 /*R13 = 0x4000..*/
210  CMPNE R14,R13 /* if we are at the 0x800 then skip this instruction*/
211 
212  /* NOW COMMANDS WITH NE ARE IGNORED!!!!!!
213  !!! if we are at the 0x40000000 or at the 0x80000000 */
214  ADD R14,#(copy_vectors_from_here -_vectors_here);
215 #endif
216  /* load my self and fix RESET item address */
217  LDM R14!, {R0-R12} /*;load (13)*4 bytes*/
218  /*; copy from SWI_Addr item to RESET item from vector table*/
219  STM R13!, {R0} /*;store RESET item -4 bytes*/
220 #if (port_HAS_COMMON_IRQ_HANDLER > 0)
221  /*; copy from SWI_Addr item to UNDEF item from vector table*/
222  STMNE R13!, {R0} /*;store UNDEF item -4 bytes*/
223 #endif
224  STMNE R13!, {R0-R12} /*;store (13)*4 bytes*/
225  /*here if we are copying to 0x40000000 then R14 hold this value*/
226  MOV R14,R13,LSR #30 // turn on interrupt from R14>>30+1
227 STORE_MEMMAP: /* R13 == REAL value from MEMMAP_ADDR */
228  LDR R13,[PC,#(MEMMAP_ADDR-STORE_MEMMAP-(CPU_PIPELINE_STAGES-1)*INSTRUCTION_SIZE)]
229  /*turn on interrupt vector table from source*/
230  ADD R14,#1
231  STR R14,[R13]
232 /**
233  * @fn void Reset_Handler()
234  *
235  * @brief Setup the operating modes & stack.
236 
237  - Initialize Interrupt System
238  - Set stack location for each mode
239  - Leave in System Mode with Interrupts Disabled
240 ------------------------------------------------------------------------------*/
241  .global _start, _mainCRTStartup,Reset_Handler,endless_loop
242  _start:
243  _mainCRTStartup:
244  Reset_Handler:
245 /*----------------------------------------------------------------------------*/
246  /* Disable interrupts and set Supervisor Mode */
247  MSR CPSR_c, #(MODE_SVC|I_BIT|F_BIT) /* Supervisor Mode */
248 /*----- LOAD .data, and .text.ram_code and zero .bss segment -----------------*/
249 load_table_here: /* SP == REAL _STACK_END_VALUE address */
250  ADD R0,PC,#(.PARAM_TABLE-load_table_here-(CPU_PIPELINE_STAGES-1)*INSTRUCTION_SIZE)
251  LDM R0!,{R4,R5-R7,R8,R10,R11,SP} /*load all need values*/
252 SystemInit_Calculate_here:
253  ADD R4, PC
254  MOV R14,PC /* this is equal to SystemInit()*/
255  BX R4 /*address if of SystemInit is in R4*/
256 #ifndef port_IS_LOADED_TO_RAM_BY_LOADER
257 ld_data_here: /*if we are at the flash R14 will be 0*/
258  SUBS R14, PC,#(ld_data_here-_vectors_here+(CPU_PIPELINE_STAGES-1)*INSTRUCTION_SIZE)
259 
260  ADDNE R5, R14 /* R5 has _etext*/
261  /* R6 has _data*/
262  /* R7 has _edata*/
263  CMP R5, R6 /* if (destination == source) then skip 4 instruct*/
264 .l1: CMPNE R6, R7 /*copy .data section (Copy from ROM to RAM)*/
265  LDRLO R0, [R5], #4 /*9 cyclec per loop*/
266  STRLO R0, [R6], #4 /*!! R5 is not used register!!!*/
267  BLO .l1
268 #endif
269  MOV R0, #0 /* Clear .bss section (Zero init)*/
270  /* R8 has _bss_start*/
271  /* R10 has _bss_end*/
272 .l2: CMP R8, R10 /*6 cyclec per loop*/
273  STRLO R0, [R8], #4
274  BLO .l2
275 /*----------------------------------------------------------------------------*/
276 /* ORDER OF STACKS hight_address -> SVC | FIQ | UND | ABT | IRQ | USER OR SYSTEM
277  ----------------------------------------------------------------------------*/
278 /* Setup a stack for each mode - note that this only sets up a usable stack
279 for User mode. Also each mode is setup with interrupts initially disabled.
280  */
281  /*MSR CPSR_c, #(MODE_SVC|I_BIT|F_BIT) done before !!!*/
282  SUB R0, SP, #SVC_STACK_SIZE /* SP has already _stack_end value*/
283 /*------------ FIQ Mode -------------*/
284  MSR CPSR_c, #(MODE_FIQ|I_BIT|F_BIT) /* FIQ Mode */
285  MOV SP, R0
286 #if (FIQ_STACK_SIZE != 0)
287  SUB R0, R0, #FIQ_STACK_SIZE
288 #endif
289 /*------------ UND Mode -------------*/
290  MSR CPSR_c, #(MODE_UND|I_BIT|F_BIT) /* Undefined Instruction Mode*/
291  MOV SP, R0
292 #if (UND_STACK_SIZE != 0)
293  SUB R0, R0, #UND_STACK_SIZE
294 #endif
295 /*------------ ABORT Mode -----------*/
296  MSR CPSR_c, #(MODE_ABT|I_BIT|F_BIT) /* Abort Mode */
297  MOV SP, R0
298 #if (ABT_STACK_SIZE != 0)
299  SUB R0, R0, #ABT_STACK_SIZE
300 #endif
301 /*------------ IRQ Mode -------------*/
302  MSR CPSR_c, #(MODE_IRQ|I_BIT|F_BIT) /* IRQ Mode */
303  MOV SP, R0
304 /*------------ USER Mode -------------*/
305  MSR CPSR_c, #(PORT_ARM_MAIN_MODE) /*User Mode or MODE_USR*/
306  SUB SP, R0, #IRQ_STACK_SIZE
307 #ifdef PORT_ARM_MAIN_MODE2
308  MSR CPSR_c, #(PORT_ARM_MAIN_MODE2)
309 #endif
310 /*---------- YOU CAN PUT HERE ADDITIONAL INIT CALLS---------------------------*/
311  MOV LR,PC
312  BX R11 /*value of main is in R11*/
313 ExitFromMain_Handler:/* avoid if main will return */
315 
316 .PARAM_TABLE:
317 /*---------- YOU CAN PUT HERE ADDITIONAL VALUES-------------------------------*/
318 /*but all other regs than this can be wasted in proc call accoding to AAPCS*/
319 .SYSTEMINIT_VALUIE: .word (SystemInit-SystemInit_Calculate_here-(CPU_PIPELINE_STAGES-1)*INSTRUCTION_SIZE) /*R4*/
320 .ETEXT_VALUIE: .word _etext /*R5*/
321 .DATA_VALUIE: .word __data_start /*R6*/
322 .EDATA_VALUIE: .word __data_end /*R7*/
323 .BSS_START_VALUE: .word __bss_start /*R8*/
324 .BSS_END_VALUE: .word __bss_end /*R10*/
325 .MAIN_LONG_JUMP: .word main /*R11*/
326 ._STACK_END_VALUE: .word _stack_end /*SP*/
327 .endfunc
328 .end
329 /*----------------IRQ_HANDLING ---- MUST BE ONLY IN THIS ORDER !!!! ---------*/
330 /*#if (port_HAS_COMMON_IRQ_HANDLER == 0) *//* if no routine jump to */
331 /* IRQ_Handler:
332  LDR R14, ADRESS_OF_VICVectAddr
333  LDR PC, [R14] *//*jump to IR*/
334  /*ADRESS_OF_VICVectAddr:
335  #if i_MCU_MODEL >= 2300
336  .word 0xFFFFFF00 *//*VICVectAddr for 2300 - 2478 has PL192*/
337  /*#else
338  .word 0xFFFFF030*/ /*VICVectAddr for 2000 - 2299 has PL190*/
339  /*#endif
340 #endif *//*(port_HAS_COMMON_IRQ_HANDLER == 0) if no routine*/