]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M0_LPC1114_LPCXpresso/RTOSDemo/Source/cr_startup_lpc11.c
973bbc2a09c3ce743fe2390a8474bee6d72077da
[freertos] / FreeRTOS / Demo / CORTEX_M0_LPC1114_LPCXpresso / RTOSDemo / Source / cr_startup_lpc11.c
1 //*****************************************************************************\r
2 //   +--+\r
3 //   | ++----+\r
4 //   +-++    |\r
5 //     |     |\r
6 //   +-+--+  |\r
7 //   | +--+--+\r
8 //   +----+    Copyright (c) 2009-10 Code Red Technologies Ltd.\r
9 //\r
10 // Microcontroller Startup code for use with Red Suite\r
11 //\r
12 // Version : 101130\r
13 //\r
14 // Software License Agreement\r
15 //\r
16 // The software is owned by Code Red Technologies and/or its suppliers, and is\r
17 // protected under applicable copyright laws.  All rights are reserved.  Any\r
18 // use in violation of the foregoing restrictions may subject the user to criminal\r
19 // sanctions under applicable laws, as well as to civil liability for the breach\r
20 // of the terms and conditions of this license.\r
21 //\r
22 // THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED\r
23 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF\r
24 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.\r
25 // USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT\r
26 // TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH\r
27 // CODE RED TECHNOLOGIES LTD.\r
28 //\r
29 //*****************************************************************************\r
30 #if defined (__cplusplus)\r
31 #ifdef __REDLIB__\r
32 #error Redlib does not support C++\r
33 #else\r
34 //*****************************************************************************\r
35 //\r
36 // The entry point for the C++ library startup\r
37 //\r
38 //*****************************************************************************\r
39 extern "C" {\r
40         extern void __libc_init_array(void);\r
41 }\r
42 #endif\r
43 #endif\r
44 \r
45 #define WEAK __attribute__ ((weak))\r
46 #define ALIAS(f) __attribute__ ((weak, alias (#f)))\r
47 \r
48 // Code Red - if CMSIS is being used, then SystemInit() routine\r
49 // will be called by startup code rather than in application's main()\r
50 #if defined (__USE_CMSIS)\r
51 #include "system_LPC11xx.h"\r
52 #endif\r
53 \r
54 //*****************************************************************************\r
55 #if defined (__cplusplus)\r
56 extern "C" {\r
57 #endif\r
58 \r
59 //*****************************************************************************\r
60 //\r
61 // Forward declaration of the default handlers. These are aliased.\r
62 // When the application defines a handler (with the same name), this will\r
63 // automatically take precedence over these weak definitions\r
64 //\r
65 //*****************************************************************************\r
66      void ResetISR(void);\r
67 WEAK void NMI_Handler(void);\r
68 WEAK void HardFault_Handler(void);\r
69 WEAK void SVCall_Handler(void);\r
70 WEAK void PendSV_Handler(void);\r
71 WEAK void SysTick_Handler(void);\r
72 WEAK void IntDefaultHandler(void);\r
73 //*****************************************************************************\r
74 //\r
75 // Forward declaration of the specific IRQ handlers. These are aliased\r
76 // to the IntDefaultHandler, which is a 'forever' loop. When the application\r
77 // defines a handler (with the same name), this will automatically take\r
78 // precedence over these weak definitions\r
79 //\r
80 //*****************************************************************************\r
81 \r
82 void CAN_IRQHandler (void) ALIAS(IntDefaultHandler);\r
83 void SSP1_IRQHandler (void) ALIAS(IntDefaultHandler);\r
84 void I2C_IRQHandler (void) ALIAS(IntDefaultHandler);\r
85 void TIMER16_0_IRQHandler (void) ALIAS(IntDefaultHandler);\r
86 void TIMER16_1_IRQHandler (void) ALIAS(IntDefaultHandler);\r
87 void TIMER32_0_IRQHandler (void) ALIAS(IntDefaultHandler);\r
88 void TIMER32_1_IRQHandler (void) ALIAS(IntDefaultHandler);\r
89 void SSP0_IRQHandler (void) ALIAS(IntDefaultHandler);\r
90 void UART_IRQHandler (void) ALIAS(IntDefaultHandler);\r
91 void ADC_IRQHandler (void) ALIAS(IntDefaultHandler);\r
92 void WDT_IRQHandler (void) ALIAS(IntDefaultHandler);\r
93 void BOD_IRQHandler (void) ALIAS(IntDefaultHandler);\r
94 void PIOINT3_IRQHandler (void) ALIAS(IntDefaultHandler);\r
95 void PIOINT2_IRQHandler (void) ALIAS(IntDefaultHandler);\r
96 void PIOINT1_IRQHandler (void) ALIAS(IntDefaultHandler);\r
97 void PIOINT0_IRQHandler (void) ALIAS(IntDefaultHandler);\r
98 void WAKEUP_IRQHandler  (void) ALIAS(IntDefaultHandler);\r
99 \r
100 //*****************************************************************************\r
101 //\r
102 // The entry point for the application.\r
103 // __main() is the entry point for redlib based applications\r
104 // main() is the entry point for newlib based applications\r
105 //\r
106 //*****************************************************************************\r
107 //\r
108 // The entry point for the application.\r
109 // __main() is the entry point for Redlib based applications\r
110 // main() is the entry point for Newlib based applications\r
111 //\r
112 //*****************************************************************************\r
113 #if defined (__REDLIB__)\r
114 extern void __main(void);\r
115 #endif\r
116 extern int main(void);\r
117 //*****************************************************************************\r
118 //\r
119 // External declaration for the pointer to the stack top from the Linker Script\r
120 //\r
121 //*****************************************************************************\r
122 extern void _vStackTop(void);\r
123 \r
124 //*****************************************************************************\r
125 #if defined (__cplusplus)\r
126 } // extern "C"\r
127 #endif\r
128 //*****************************************************************************\r
129 //\r
130 // The vector table.  Note that the proper constructs must be placed on this to\r
131 // ensure that it ends up at physical address 0x0000.0000.\r
132 //\r
133 //*****************************************************************************\r
134 extern void (* const g_pfnVectors[])(void);\r
135 __attribute__ ((section(".isr_vector")))\r
136 void (* const g_pfnVectors[])(void) = {\r
137     &_vStackTop,                                                // The initial stack pointer\r
138     ResetISR,                               // The reset handler\r
139     NMI_Handler,                            // The NMI handler\r
140     HardFault_Handler,                      // The hard fault handler\r
141     0,                                                  // Reserved\r
142     0,                                                  // Reserved\r
143     0,                                                  // Reserved\r
144     0,                                      // Reserved\r
145     0,                                      // Reserved\r
146     0,                                      // Reserved\r
147     0,                                      // Reserved\r
148     SVCall_Handler,                             // SVCall handler\r
149     0,                                                  // Reserved\r
150     0,                                      // Reserved\r
151     PendSV_Handler,                             // The PendSV handler\r
152     SysTick_Handler,                            // The SysTick handler\r
153 \r
154     // Wakeup sources for the I/O pins:\r
155     //   PIO0 (0:11)\r
156     //   PIO1 (0)\r
157     WAKEUP_IRQHandler,                      // PIO0_0  Wakeup\r
158     WAKEUP_IRQHandler,                      // PIO0_1  Wakeup\r
159     WAKEUP_IRQHandler,                      // PIO0_2  Wakeup\r
160     WAKEUP_IRQHandler,                      // PIO0_3  Wakeup\r
161     WAKEUP_IRQHandler,                      // PIO0_4  Wakeup\r
162     WAKEUP_IRQHandler,                      // PIO0_5  Wakeup\r
163     WAKEUP_IRQHandler,                      // PIO0_6  Wakeup\r
164     WAKEUP_IRQHandler,                      // PIO0_7  Wakeup\r
165     WAKEUP_IRQHandler,                      // PIO0_8  Wakeup\r
166     WAKEUP_IRQHandler,                      // PIO0_9  Wakeup\r
167     WAKEUP_IRQHandler,                      // PIO0_10 Wakeup\r
168     WAKEUP_IRQHandler,                      // PIO0_11 Wakeup\r
169     WAKEUP_IRQHandler,                      // PIO1_0  Wakeup\r
170 \r
171     CAN_IRQHandler,                                                     // C_CAN Interrupt\r
172     SSP1_IRQHandler,                                            // SPI/SSP1 Interrupt\r
173     I2C_IRQHandler,                             // I2C0\r
174     TIMER16_0_IRQHandler,                   // CT16B0 (16-bit Timer 0)\r
175     TIMER16_1_IRQHandler,                   // CT16B1 (16-bit Timer 1)\r
176     TIMER32_0_IRQHandler,                   // CT32B0 (32-bit Timer 0)\r
177     TIMER32_1_IRQHandler,                   // CT32B1 (32-bit Timer 1)\r
178     SSP0_IRQHandler,                            // SPI/SSP0 Interrupt\r
179     UART_IRQHandler,                            // UART0\r
180 \r
181     0,                                                  // Reserved\r
182     0,                                                  // Reserved\r
183 \r
184     ADC_IRQHandler,                             // ADC   (A/D Converter)\r
185     WDT_IRQHandler,                             // WDT   (Watchdog Timer)\r
186     BOD_IRQHandler,                             // BOD   (Brownout Detect)\r
187     0,                                                  // Reserved\r
188     PIOINT3_IRQHandler,                     // PIO INT3\r
189     PIOINT2_IRQHandler,                     // PIO INT2\r
190     PIOINT1_IRQHandler,                     // PIO INT1\r
191     PIOINT0_IRQHandler,                     // PIO INT0\r
192 };\r
193 \r
194 //*****************************************************************************\r
195 // Functions to carry out the initialization of RW and BSS data sections. These\r
196 // are written as separate functions rather than being inlined within the\r
197 // ResetISR() function in order to cope with MCUs with multiple banks of\r
198 // memory.\r
199 //*****************************************************************************\r
200 __attribute__ ((section(".after_vectors")))\r
201 void data_init(unsigned int romstart, unsigned int start, unsigned int len) {\r
202         unsigned int *pulDest = (unsigned int*) start;\r
203         unsigned int *pulSrc = (unsigned int*) romstart;\r
204         unsigned int loop;\r
205         for (loop = 0; loop < len; loop = loop + 4)\r
206                 *pulDest++ = *pulSrc++;\r
207 }\r
208 \r
209 __attribute__ ((section(".after_vectors")))\r
210 void bss_init(unsigned int start, unsigned int len) {\r
211         unsigned int *pulDest = (unsigned int*) start;\r
212         unsigned int loop;\r
213         for (loop = 0; loop < len; loop = loop + 4)\r
214                 *pulDest++ = 0;\r
215 }\r
216 \r
217 #ifndef USE_OLD_STYLE_DATA_BSS_INIT\r
218 //*****************************************************************************\r
219 // The following symbols are constructs generated by the linker, indicating\r
220 // the location of various points in the "Global Section Table". This table is\r
221 // created by the linker via the Code Red managed linker script mechanism. It\r
222 // contains the load address, execution address and length of each RW data\r
223 // section and the execution and length of each BSS (zero initialized) section.\r
224 //*****************************************************************************\r
225 extern unsigned int __data_section_table;\r
226 extern unsigned int __data_section_table_end;\r
227 extern unsigned int __bss_section_table;\r
228 extern unsigned int __bss_section_table_end;\r
229 #else\r
230 //*****************************************************************************\r
231 // The following symbols are constructs generated by the linker, indicating\r
232 // the load address, execution address and length of the RW data section and\r
233 // the execution and length of the BSS (zero initialized) section.\r
234 // Note that these symbols are not normally used by the managed linker script\r
235 // mechanism in Red Suite/LPCXpresso 3.6 (Windows) and LPCXpresso 3.8 (Linux).\r
236 // They are provide here simply so this startup code can be used with earlier\r
237 // versions of Red Suite which do not support the more advanced managed linker\r
238 // script mechanism introduced in the above version. To enable their use,\r
239 // define "USE_OLD_STYLE_DATA_BSS_INIT".\r
240 //*****************************************************************************\r
241 extern unsigned int _etext;\r
242 extern unsigned int _data;\r
243 extern unsigned int _edata;\r
244 extern unsigned int _bss;\r
245 extern unsigned int _ebss;\r
246 #endif\r
247 \r
248 \r
249 //*****************************************************************************\r
250 // Reset entry point for your code.\r
251 // Sets up a simple runtime environment and initializes the C/C++\r
252 // library.\r
253 //*****************************************************************************\r
254 __attribute__ ((section(".after_vectors")))\r
255 void\r
256 ResetISR(void) {\r
257 \r
258 #ifndef USE_OLD_STYLE_DATA_BSS_INIT\r
259     //\r
260     // Copy the data sections from flash to SRAM.\r
261     //\r
262         unsigned int LoadAddr, ExeAddr, SectionLen;\r
263         unsigned int *SectionTableAddr;\r
264 \r
265         // Load base address of Global Section Table\r
266         SectionTableAddr = &__data_section_table;\r
267 \r
268     // Copy the data sections from flash to SRAM.\r
269         while (SectionTableAddr < &__data_section_table_end) {\r
270                 LoadAddr = *SectionTableAddr++;\r
271                 ExeAddr = *SectionTableAddr++;\r
272                 SectionLen = *SectionTableAddr++;\r
273                 data_init(LoadAddr, ExeAddr, SectionLen);\r
274         }\r
275         // At this point, SectionTableAddr = &__bss_section_table;\r
276         // Zero fill the bss segment\r
277         while (SectionTableAddr < &__bss_section_table_end) {\r
278                 ExeAddr = *SectionTableAddr++;\r
279                 SectionLen = *SectionTableAddr++;\r
280                 bss_init(ExeAddr, SectionLen);\r
281         }\r
282 #else\r
283         // Use Old Style Data and BSS section initialization.\r
284         // This will only initialize a single RAM bank.\r
285         unsigned int * LoadAddr, *ExeAddr, *EndAddr, SectionLen;\r
286 \r
287     // Copy the data segment from flash to SRAM.\r
288         LoadAddr = &_etext;\r
289         ExeAddr = &_data;\r
290         EndAddr = &_edata;\r
291         SectionLen = (void*)EndAddr - (void*)ExeAddr;\r
292         data_init((unsigned int)LoadAddr, (unsigned int)ExeAddr, SectionLen);\r
293         // Zero fill the bss segment\r
294         ExeAddr = &_bss;\r
295         EndAddr = &_ebss;\r
296         SectionLen = (void*)EndAddr - (void*)ExeAddr;\r
297         bss_init ((unsigned int)ExeAddr, SectionLen);\r
298 #endif\r
299 \r
300 #ifdef __USE_CMSIS\r
301         SystemInit();\r
302 #endif\r
303 \r
304 #if defined (__cplusplus)\r
305         //\r
306         // Call C++ library initialisation\r
307         //\r
308         __libc_init_array();\r
309 #endif\r
310 \r
311 #if defined (__REDLIB__)\r
312         // Call the Redlib library, which in turn calls main()\r
313         __main() ;\r
314 #else\r
315         main();\r
316 #endif\r
317         //\r
318         // main() shouldn't return, but if it does, we'll just enter an infinite loop\r
319         //\r
320         while (1) {\r
321                 ;\r
322         }\r
323 }\r
324 \r
325 //*****************************************************************************\r
326 // Default exception handlers. Override the ones here by defining your own\r
327 // handler routines in your application code.\r
328 //*****************************************************************************\r
329 __attribute__ ((section(".after_vectors")))\r
330 void NMI_Handler(void)\r
331 {\r
332     while(1)\r
333     {\r
334     }\r
335 }\r
336 \r
337 \r
338 \r
339 void pop_registers_from_fault_stack(unsigned int * hardfault_args)\r
340 {\r
341 volatile unsigned int stacked_r0;\r
342 volatile unsigned int stacked_r1;\r
343 volatile unsigned int stacked_r2;\r
344 volatile unsigned int stacked_r3;\r
345 volatile unsigned int stacked_r12;\r
346 volatile unsigned int stacked_lr;\r
347 volatile unsigned int stacked_pc;\r
348 volatile unsigned int stacked_psr;\r
349 \r
350         stacked_r0 = ((unsigned long) hardfault_args[0]);\r
351         stacked_r1 = ((unsigned long) hardfault_args[1]);\r
352         stacked_r2 = ((unsigned long) hardfault_args[2]);\r
353         stacked_r3 = ((unsigned long) hardfault_args[3]);\r
354 \r
355         stacked_r12 = ((unsigned long) hardfault_args[4]);\r
356         stacked_lr = ((unsigned long) hardfault_args[5]);\r
357         stacked_pc = ((unsigned long) hardfault_args[6]);\r
358         stacked_psr = ((unsigned long) hardfault_args[7]);\r
359 \r
360         /* Inspect stacked_pc to locate the offending instruction. */\r
361         for( ;; )\r
362         {\r
363                 __asm volatile ( "NOP" );\r
364         }\r
365 }\r
366 \r
367 \r
368 \r
369 \r
370 __attribute__ ((section(".after_vectors")))\r
371 void HardFault_Handler(void)\r
372 {\r
373         __asm volatile\r
374         (\r
375                 " mov r0, lr                                                                            \n"\r
376                 " mov r1, #4                                                                            \n"\r
377                 " and r1, r0                                                                            \n"\r
378                 " cmp r1, #0                                                                            \n"\r
379                 " beq is_equal                                                                          \n"\r
380                 " mrs r0, psp                                                                           \n"\r
381                 " b is_done                                                                                     \n"\r
382                 "is_equal:                                                                                      \n"\r
383                 " mrs r0, msp                                                                           \n"\r
384                 "is_done:                                                                                       \n"\r
385                 " ldr r1, [r0, #24]                                                                     \n"\r
386                 " ldr r2, handler2_address_const                                        \n"\r
387                 " bx r2                                                                                         \n"\r
388                 " handler2_address_const: .word pop_registers_from_fault_stack  \n"\r
389         );\r
390     while(1)\r
391     {\r
392     }\r
393 }\r
394 __attribute__ ((section(".after_vectors")))\r
395 void SVCall_Handler(void)\r
396 {\r
397     while(1)\r
398     {\r
399     }\r
400 }\r
401 __attribute__ ((section(".after_vectors")))\r
402 void PendSV_Handler(void)\r
403 {\r
404     while(1)\r
405     {\r
406     }\r
407 }\r
408 __attribute__ ((section(".after_vectors")))\r
409 void SysTick_Handler(void)\r
410 {\r
411     while(1)\r
412     {\r
413     }\r
414 }\r
415 \r
416 //*****************************************************************************\r
417 //\r
418 // Processor ends up here if an unexpected interrupt occurs or a specific\r
419 // handler is not present in the application code.\r
420 //\r
421 //*****************************************************************************\r
422 __attribute__ ((section(".after_vectors")))\r
423 void IntDefaultHandler(void)\r
424 {\r
425     while(1)\r
426     {\r
427     }\r
428 }\r
429 \r
430 \r