1 // *****************************************************************************
\r
8 // +----+ Copyright (c) 2011-12 Code Red Technologies Ltd.
\r
10 // LPC43xx 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
33 #if defined(__cplusplus)
\r
35 #error Redlib does not support C++
\r
37 // *****************************************************************************
\r
39 // The entry point for the C++ library startup
\r
41 // *****************************************************************************
\r
43 extern void __libc_init_array(void);
\r
49 #define WEAK __attribute__ ((weak))
\r
50 #define ALIAS(f) __attribute__ ((weak, alias(# f)))
\r
52 // Code Red - if CMSIS is being used, then SystemInit() routine
\r
53 // will be called by startup code rather than in application's main()
\r
54 extern void SystemInit(void);
\r
56 // *****************************************************************************
\r
57 #if defined(__cplusplus)
\r
61 // *****************************************************************************
\r
63 // Forward declaration of the default handlers. These are aliased.
\r
64 // When the application defines a handler (with the same name), this will
\r
65 // automatically take precedence over these weak definitions
\r
67 // *****************************************************************************
\r
68 void ResetISR(void);
\r
69 WEAK void NMI_Handler(void);
\r
70 WEAK void HardFault_Handler(void);
\r
71 WEAK void MemManage_Handler(void);
\r
72 WEAK void BusFault_Handler(void);
\r
73 WEAK void UsageFault_Handler(void);
\r
74 WEAK void SVC_Handler(void);
\r
75 WEAK void DebugMon_Handler(void);
\r
76 WEAK void PendSV_Handler(void);
\r
77 WEAK void SysTick_Handler(void);
\r
78 WEAK void IntDefaultHandler(void);
\r
80 //*****************************************************************************
\r
82 // Forward declaration of the specific IRQ handlers. These are aliased
\r
83 // to the IntDefaultHandler, which is a 'forever' loop. When the application
\r
84 // defines a handler (with the same name), this will automatically take
\r
85 // precedence over these weak definitions
\r
87 //*****************************************************************************
\r
88 void DAC_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
89 void MX_CORE_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
90 void DMA_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
91 void FLASHEEPROM_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
92 void ETH_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
93 void SDIO_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
94 void LCD_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
95 void USB0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
96 void USB1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
97 void SCT_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
98 void RIT_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
99 void TIMER0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
100 void TIMER1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
101 void TIMER2_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
102 void TIMER3_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
103 void MCPWM_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
104 void ADC0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
105 void I2C0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
106 void I2C1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
107 void SPI_IRQHandler (void) ALIAS(IntDefaultHandler);
\r
108 void ADC1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
109 void SSP0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
110 void SSP1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
111 void UART0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
112 void UART1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
113 void UART2_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
114 void UART3_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
115 void I2S0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
116 void I2S1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
117 void SPIFI_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
118 void SGPIO_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
119 void GPIO0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
120 void GPIO1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
121 void GPIO2_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
122 void GPIO3_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
123 void GPIO4_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
124 void GPIO5_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
125 void GPIO6_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
126 void GPIO7_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
127 void GINT0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
128 void GINT1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
129 void EVRT_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
130 void CAN1_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
131 void ATIMER_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
132 void RTC_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
133 void WDT_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
134 void CAN0_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
135 void QEI_IRQHandler(void) ALIAS(IntDefaultHandler);
\r
137 //*****************************************************************************
\r
139 // The entry point for the application.
\r
140 // __main() is the entry point for Redlib based applications
\r
141 // main() is the entry point for Newlib based applications
\r
143 //*****************************************************************************
\r
144 #if defined (__REDLIB__)
\r
145 extern void __main(void);
\r
147 extern int main(void);
\r
148 //*****************************************************************************
\r
150 // External declaration for the pointer to the stack top from the Linker Script
\r
152 //*****************************************************************************
\r
153 extern void _vStackTop(void);
\r
155 //*****************************************************************************
\r
156 #if defined (__cplusplus)
\r
159 //*****************************************************************************
\r
161 // The vector table.
\r
162 // This relies on the linker script to place at correct location in memory.
\r
164 // *****************************************************************************
\r
165 extern void(*const g_pfnVectors[]) (void);
\r
166 __attribute__ ((section(".isr_vector")))
\r
167 void(*const g_pfnVectors[]) (void) = {
\r
168 // Core Level - CM4/CM3
\r
169 &_vStackTop, // The initial stack pointer
\r
170 ResetISR, // The reset handler
\r
171 NMI_Handler, // The NMI handler
\r
172 HardFault_Handler, // The hard fault handler
\r
173 MemManage_Handler, // The MPU fault handler
\r
174 BusFault_Handler, // The bus fault handler
\r
175 UsageFault_Handler, // The usage fault handler
\r
180 SVC_Handler, // SVCall handler
\r
181 DebugMon_Handler, // Debug monitor handler
\r
183 PendSV_Handler, // The PendSV handler
\r
184 SysTick_Handler, // The SysTick handler
\r
186 // Chip Level - LPC18xx/43xx
\r
187 DAC_IRQHandler, // 16 D/A Converter
\r
188 MX_CORE_IRQHandler, // 17 CortexM4/M0 (LPC43XX ONLY)
\r
189 DMA_IRQHandler, // 18 General Purpose DMA
\r
191 FLASHEEPROM_IRQHandler, // 20 ORed flash Bank A, flash Bank B, EEPROM interrupts
\r
192 ETH_IRQHandler, // 21 Ethernet
\r
193 SDIO_IRQHandler, // 22 SD/MMC
\r
194 LCD_IRQHandler, // 23 LCD
\r
195 USB0_IRQHandler, // 24 USB0
\r
196 USB1_IRQHandler, // 25 USB1
\r
197 SCT_IRQHandler, // 26 State Configurable Timer
\r
198 RIT_IRQHandler, // 27 Repetitive Interrupt Timer
\r
199 TIMER0_IRQHandler, // 28 Timer0
\r
200 TIMER1_IRQHandler, // 29 Timer 1
\r
201 TIMER2_IRQHandler, // 30 Timer 2
\r
202 TIMER3_IRQHandler, // 31 Timer 3
\r
203 MCPWM_IRQHandler, // 32 Motor Control PWM
\r
204 ADC0_IRQHandler, // 33 A/D Converter 0
\r
205 I2C0_IRQHandler, // 34 I2C0
\r
206 I2C1_IRQHandler, // 35 I2C1
\r
207 SPI_IRQHandler, // 36 SPI (LPC43XX ONLY)
\r
208 ADC1_IRQHandler, // 37 A/D Converter 1
\r
209 SSP0_IRQHandler, // 38 SSP0
\r
210 SSP1_IRQHandler, // 39 SSP1
\r
211 UART0_IRQHandler, // 40 UART0
\r
212 UART1_IRQHandler, // 41 UART1
\r
213 UART2_IRQHandler, // 42 UART2
\r
214 UART3_IRQHandler, // 43 USRT3
\r
215 I2S0_IRQHandler, // 44 I2S0
\r
216 I2S1_IRQHandler, // 45 I2S1
\r
217 SPIFI_IRQHandler, // 46 SPI Flash Interface
\r
218 SGPIO_IRQHandler, // 47 SGPIO (LPC43XX ONLY)
\r
219 GPIO0_IRQHandler, // 48 GPIO0
\r
220 GPIO1_IRQHandler, // 49 GPIO1
\r
221 GPIO2_IRQHandler, // 50 GPIO2
\r
222 GPIO3_IRQHandler, // 51 GPIO3
\r
223 GPIO4_IRQHandler, // 52 GPIO4
\r
224 GPIO5_IRQHandler, // 53 GPIO5
\r
225 GPIO6_IRQHandler, // 54 GPIO6
\r
226 GPIO7_IRQHandler, // 55 GPIO7
\r
227 GINT0_IRQHandler, // 56 GINT0
\r
228 GINT1_IRQHandler, // 57 GINT1
\r
229 EVRT_IRQHandler, // 58 Event Router
\r
230 CAN1_IRQHandler, // 59 C_CAN1
\r
233 ATIMER_IRQHandler, // 62 ATIMER
\r
234 RTC_IRQHandler, // 63 RTC
\r
236 WDT_IRQHandler, // 65 WDT
\r
238 CAN0_IRQHandler, // 67 C_CAN0
\r
239 QEI_IRQHandler, // 68 QEI
\r
242 //*****************************************************************************
\r
243 // Functions to carry out the initialization of RW and BSS data sections. These
\r
244 // are written as separate functions rather than being inlined within the
\r
245 // ResetISR() function in order to cope with MCUs with multiple banks of
\r
247 //*****************************************************************************
\r
248 __attribute__ ((section(".after_vectors")))
\r
249 void data_init(unsigned int romstart, unsigned int start, unsigned int len) {
\r
250 unsigned int *pulDest = (unsigned int*) start;
\r
251 unsigned int *pulSrc = (unsigned int*) romstart;
\r
253 for (loop = 0; loop < len; loop = loop + 4)
\r
254 *pulDest++ = *pulSrc++;
\r
257 __attribute__ ((section(".after_vectors")))
\r
258 void bss_init(unsigned int start, unsigned int len) {
\r
259 unsigned int *pulDest = (unsigned int*) start;
\r
261 for (loop = 0; loop < len; loop = loop + 4)
\r
265 //*****************************************************************************
\r
266 // The following symbols are constructs generated by the linker, indicating
\r
267 // the location of various points in the "Global Section Table". This table is
\r
268 // created by the linker via the Code Red managed linker script mechanism. It
\r
269 // contains the load address, execution address and length of each RW data
\r
270 // section and the execution and length of each BSS (zero initialized) section.
\r
271 //*****************************************************************************
\r
272 extern unsigned int __data_section_table;
\r
273 extern unsigned int __data_section_table_end;
\r
274 extern unsigned int __bss_section_table;
\r
275 extern unsigned int __bss_section_table_end;
\r
277 //*****************************************************************************
\r
278 // Reset entry point for your code.
\r
279 // Sets up a simple runtime environment and initializes the C/C++
\r
282 //*****************************************************************************
\r
286 // *************************************************************
\r
287 // The following conditional block of code manually resets as
\r
288 // much of the peripheral set of the LPC18 as possible. This is
\r
289 // done because the LPC18 does not provide a means of triggering
\r
290 // a full system reset under debugger control, which can cause
\r
291 // problems in certain circumstances when debugging.
\r
293 // You can prevent this code block being included if you require
\r
294 // (for example when creating a final executable which you will
\r
295 // not debug) by setting the define 'DONT_RESET_ON_RESTART'.
\r
297 #ifndef DONT_RESET_ON_RESTART
\r
299 // Disable interrupts
\r
300 __asm volatile ("cpsid i");
\r
301 // equivalent to CMSIS '__disable_irq()' function
\r
303 unsigned int *RESET_CONTROL = (unsigned int *) 0x40053100;
\r
304 // LPC_RGU->RESET_CTRL0 @ 0x40053100
\r
305 // LPC_RGU->RESET_CTRL1 @ 0x40053104
\r
306 // Note that we do not use the CMSIS register access mechanism,
\r
307 // as there is no guarantee that the project has been configured
\r
310 // Write to LPC_RGU->RESET_CTRL0
\r
311 *(RESET_CONTROL+0) = 0x10DF0000;
\r
312 // GPIO_RST|AES_RST|ETHERNET_RST|SDIO_RST|DMA_RST|
\r
313 // USB1_RST|USB0_RST|LCD_RST
\r
315 // Write to LPC_RGU->RESET_CTRL1
\r
316 *(RESET_CONTROL+1) = 0x00DFF7FF;
\r
317 // CAN0_RST|CAN1_RST|I2S_RST|SSP1_RST|SSP0_RST|
\r
318 // I2C1_RST|I2C0_RST|UART3_RST|UART1_RST|UART1_RST|UART0_RST|
\r
319 // DAC_RST|ADC1_RST|ADC0_RST|QEI_RST|MOTOCONPWM_RST|SCT_RST|
\r
320 // RITIMER_RST|TIMER3_RST|TIMER2_RST|TIMER1_RST|TIMER0_RST
\r
322 // Clear all pending interrupts in the NVIC
\r
323 volatile unsigned int *NVIC_ICPR = (unsigned int *) 0xE000E280;
\r
324 unsigned int irqpendloop;
\r
325 for (irqpendloop = 0; irqpendloop < 8; irqpendloop++) {
\r
326 *(NVIC_ICPR+irqpendloop)= 0xFFFFFFFF;
\r
329 // Reenable interrupts
\r
330 __asm volatile ("cpsie i");
\r
331 // equivalent to CMSIS '__enable_irq()' function
\r
333 #endif // ifndef DONT_RESET_ON_RESTART
\r
334 // *************************************************************
\r
338 // Copy the data sections from flash to SRAM.
\r
340 unsigned int LoadAddr, ExeAddr, SectionLen;
\r
341 unsigned int *SectionTableAddr;
\r
343 // Load base address of Global Section Table
\r
344 SectionTableAddr = &__data_section_table;
\r
346 // Copy the data sections from flash to SRAM.
\r
347 while (SectionTableAddr < &__data_section_table_end) {
\r
348 LoadAddr = *SectionTableAddr++;
\r
349 ExeAddr = *SectionTableAddr++;
\r
350 SectionLen = *SectionTableAddr++;
\r
351 data_init(LoadAddr, ExeAddr, SectionLen);
\r
353 // At this point, SectionTableAddr = &__bss_section_table;
\r
354 // Zero fill the bss segment
\r
355 while (SectionTableAddr < &__bss_section_table_end) {
\r
356 ExeAddr = *SectionTableAddr++;
\r
357 SectionLen = *SectionTableAddr++;
\r
358 bss_init(ExeAddr, SectionLen);
\r
361 // ******************************
\r
362 // Check to see if we are running the code from a non-zero
\r
363 // address (eg RAM, external flash), in which case we need
\r
364 // to modify the VTOR register to tell the CPU that the
\r
365 // vector table is located at a non-0x0 address.
\r
367 // Note that we do not use the CMSIS register access mechanism,
\r
368 // as there is no guarantee that the project has been configured
\r
370 unsigned int * pSCB_VTOR = (unsigned int *) 0xE000ED08;
\r
371 if ((unsigned int *)g_pfnVectors!=(unsigned int *) 0x00000000) {
\r
372 // CMSIS : SCB->VTOR = <address of vector table>
\r
373 *pSCB_VTOR = (unsigned int)g_pfnVectors;
\r
380 #if defined (__cplusplus)
\r
382 // Call C++ library initialisation
\r
384 __libc_init_array();
\r
387 #if defined (__REDLIB__)
\r
388 // Call the Redlib library, which in turn calls main()
\r
395 // main() shouldn't return, but if it does, we'll just enter an infinite loop
\r
402 //*****************************************************************************
\r
403 // Default exception handlers. Override the ones here by defining your own
\r
404 // handler routines in your application code.
\r
405 //*****************************************************************************
\r
406 __attribute__ ((section(".after_vectors")))
\r
407 void NMI_Handler(void)
\r
413 __attribute__ ((section(".after_vectors")))
\r
414 void HardFault_Handler(void)
\r
420 " mrseq r0, msp \n"
\r
421 " mrsne r0, psp \n"
\r
422 " ldr r1, [r0, #24] \n"
\r
423 " ldr r2, handler2_address_const \n"
\r
425 " handler2_address_const: .word prvGetRegistersFromStack \n"
\r
429 __attribute__ ((section(".after_vectors")))
\r
430 void MemManage_Handler(void)
\r
436 __attribute__ ((section(".after_vectors")))
\r
437 void BusFault_Handler(void)
\r
443 __attribute__ ((section(".after_vectors")))
\r
444 void UsageFault_Handler(void)
\r
450 __attribute__ ((section(".after_vectors")))
\r
451 void SVCall_Handler(void)
\r
457 __attribute__ ((section(".after_vectors")))
\r
458 void DebugMon_Handler(void)
\r
464 __attribute__ ((section(".after_vectors")))
\r
465 void PendSV_Handler(void)
\r
471 __attribute__ ((section(".after_vectors")))
\r
472 void SysTick_Handler(void)
\r
479 //*****************************************************************************
\r
481 // Processor ends up here if an unexpected interrupt occurs or a specific
\r
482 // handler is not present in the application code.
\r
484 //*****************************************************************************
\r
485 __attribute__ ((section(".after_vectors")))
\r
486 void IntDefaultHandler(void)
\r
493 /* Debug functions. */
\r
494 void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
\r
496 /* These are volatile to try and prevent the compiler/linker optimising them
\r
497 away as the variables never actually get used. If the debugger won't show the
\r
498 values of the variables, make them global my moving their declaration outside
\r
499 of this function. */
\r
500 volatile uint32_t r0;
\r
501 volatile uint32_t r1;
\r
502 volatile uint32_t r2;
\r
503 volatile uint32_t r3;
\r
504 volatile uint32_t r12;
\r
505 volatile uint32_t lr; /* Link register. */
\r
506 volatile uint32_t pc; /* Program counter. */
\r
507 volatile uint32_t psr;/* Program status register. */
\r
509 r0 = pulFaultStackAddress[ 0 ];
\r
510 r1 = pulFaultStackAddress[ 1 ];
\r
511 r2 = pulFaultStackAddress[ 2 ];
\r
512 r3 = pulFaultStackAddress[ 3 ];
\r
514 r12 = pulFaultStackAddress[ 4 ];
\r
515 lr = pulFaultStackAddress[ 5 ];
\r
516 pc = pulFaultStackAddress[ 6 ];
\r
517 psr = pulFaultStackAddress[ 7 ];
\r
519 /* When the following line is hit, the variables contain the register values. */
\r