1 //*****************************************************************************
\r
8 // +----+ Copyright (c) 2009-10 Code Red Technologies Ltd.
\r
10 // Microcontroller Startup code for use with Red Suite
\r
14 // Software License Agreement
\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
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
29 //*****************************************************************************
\r
30 #if defined (__cplusplus)
\r
32 #error Redlib does not support C++
\r
34 //*****************************************************************************
\r
36 // The entry point for the C++ library startup
\r
38 //*****************************************************************************
\r
40 extern void __libc_init_array(void);
\r
45 #define WEAK __attribute__ ((weak))
\r
46 #define ALIAS(f) __attribute__ ((weak, alias (#f)))
\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
54 //*****************************************************************************
\r
55 #if defined (__cplusplus)
\r
59 //*****************************************************************************
\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
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
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
80 //*****************************************************************************
\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
100 //*****************************************************************************
\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
106 //*****************************************************************************
\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
112 //*****************************************************************************
\r
113 #if defined (__REDLIB__)
\r
114 extern void __main(void);
\r
116 extern int main(void);
\r
117 //*****************************************************************************
\r
119 // External declaration for the pointer to the stack top from the Linker Script
\r
121 //*****************************************************************************
\r
122 extern void _vStackTop(void);
\r
124 //*****************************************************************************
\r
125 #if defined (__cplusplus)
\r
128 //*****************************************************************************
\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
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
148 SVCall_Handler, // SVCall handler
\r
151 PendSV_Handler, // The PendSV handler
\r
152 SysTick_Handler, // The SysTick handler
\r
154 // Wakeup sources for the I/O pins:
\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
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
184 ADC_IRQHandler, // ADC (A/D Converter)
\r
185 WDT_IRQHandler, // WDT (Watchdog Timer)
\r
186 BOD_IRQHandler, // BOD (Brownout Detect)
\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
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
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
205 for (loop = 0; loop < len; loop = loop + 4)
\r
206 *pulDest++ = *pulSrc++;
\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
213 for (loop = 0; loop < len; loop = loop + 4)
\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
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
249 //*****************************************************************************
\r
250 // Reset entry point for your code.
\r
251 // Sets up a simple runtime environment and initializes the C/C++
\r
253 //*****************************************************************************
\r
254 __attribute__ ((section(".after_vectors")))
\r
258 #ifndef USE_OLD_STYLE_DATA_BSS_INIT
\r
260 // Copy the data sections from flash to SRAM.
\r
262 unsigned int LoadAddr, ExeAddr, SectionLen;
\r
263 unsigned int *SectionTableAddr;
\r
265 // Load base address of Global Section Table
\r
266 SectionTableAddr = &__data_section_table;
\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
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
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
287 // Copy the data segment from flash to SRAM.
\r
288 LoadAddr = &_etext;
\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
296 SectionLen = (void*)EndAddr - (void*)ExeAddr;
\r
297 bss_init ((unsigned int)ExeAddr, SectionLen);
\r
304 #if defined (__cplusplus)
\r
306 // Call C++ library initialisation
\r
308 __libc_init_array();
\r
311 #if defined (__REDLIB__)
\r
312 // Call the Redlib library, which in turn calls main()
\r
318 // main() shouldn't return, but if it does, we'll just enter an infinite loop
\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
339 void pop_registers_from_fault_stack(unsigned int * hardfault_args)
\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
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
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
360 /* Inspect stacked_pc to locate the offending instruction. */
\r
363 __asm volatile ( "NOP" );
\r
370 __attribute__ ((section(".after_vectors")))
\r
371 void HardFault_Handler(void)
\r
385 " ldr r1, [r0, #24] \n"
\r
386 " ldr r2, handler2_address_const \n"
\r
388 " handler2_address_const: .word pop_registers_from_fault_stack \n"
\r
394 __attribute__ ((section(".after_vectors")))
\r
395 void SVCall_Handler(void)
\r
401 __attribute__ ((section(".after_vectors")))
\r
402 void PendSV_Handler(void)
\r
408 __attribute__ ((section(".after_vectors")))
\r
409 void SysTick_Handler(void)
\r
416 //*****************************************************************************
\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
421 //*****************************************************************************
\r
422 __attribute__ ((section(".after_vectors")))
\r
423 void IntDefaultHandler(void)
\r