General purpose of startup code
1. Initialization of heap and stack;
2. Vector table definition;
3. Address remapping and transfer of interrupt vector table;
4. Initialize the fracture with special requirements;
5. Processor mode;
6. Enter the C application.
After ARM reset, the program starts to execute code from address 0x00, so there is usually a process of mapping the Flash address to 0x00. But for this Cortex M0, the startup code is relatively simple. From the storage distribution diagram, we can see that LPC11C14 has 32K on-chip Flash, and the address range is 0x0000 0000 ~ 0x0000 8000. When we burn the program (less than 32K) into the on-chip Flash, there is no need to remap the Flash address in the startup code.
NXP LPC11C14 storage distribution diagram mainly looks at Flash
Analysis of the CortexM0 startup code:
1. Stack initialization part
At the beginning of the program, first define the size and properties of the stack, and then initialize the heap. The ARM-Thumb procedure call standard and the ARM and Thumb C/C++ compilers always use a full descending type stack.
;
;
;
Stack_Size EQU 0x00000020 //Define stack size
AREA STACK, NOINIT, READWRITE, ALIGN=3 //Define a data segment aligned to 8 bytes. The AREA pseudo-instruction is used to define a //code segment or a data segment.
//NOINIT defines that this data segment only reserves the memory cells without writing the initial
//values into the memory cells, or initializing the values of each memory cell to 0.
Stack_Mem SPACE Stack_Size //Reserve stack space of Stack_Size size to allocate
storage units of consecutive Stack_Size //sections and initialize them to 0
__initial_sp //Label--the top address of the stack. In M0, the stack is full and decrementing, and the stack pointer is located at the high address of the stack.
Stack_Size EQU 0x00000020 //Define the stack size
;
Heap_Size EQU 0x00000000 //Define the heap space size
AREA HEAP, NOINIT, READWRITE, ALIGN=3 //Define a data segment, 8-byte alignment
__heap_base //Label--represents the bottom address of the heap
Heap_Mem SPACE Heap_Size //Reserve the heap space of Heap_Size
__heap_limit //Label--heap limit address
PRESERVE8 //The directive specifies that the current file keeps the stack 8-byte aligned. It sets the PRES8 compilation attribute to
//notify the linker. The linker checks whether any code that requires the stack to be 8-byte aligned is only called directly or indirectly by the code that keeps the //stack 8-byte aligned.
THUMB //Instructs the compiler that the following pseudo-instructions are Thum instructions
2. Definition of Interruption Scale
In the scatter-loading file generated by MDK, RESET is set at address 0 of the flash, which specifies the address of the vector table.
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY //Define a read-only data segment, located at address 0, which is actually placed in the CODE area
//EXPORT declares a global label __Vetors in the program
//Can be used in other files
/*
The DCD directive is used to allocate a continuous word storage unit and initialize it with the expression specified in the directive. The expression can be a program label or a numeric expression. DCD can also be replaced by "&".
*/
__Vectors DCD __initial_sp ; Top of Stack // Assign 4 bytes and 32 bits of address to __initial_sp
DCD Reset_Handler ; Reset Handler//Assign address to label Reset_Handler
DCD NMI_Handler ; NMI Handler //Assign address to label NMI_Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler; Usage Fault Handler
DCD 0; Reserved //Reserved, do not assign
DCD to any label 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler; SysTick Handler
; External Interrupts
DCD WAKEUP_IRQHandler; 15 wakeup sources for all the DCD WAKEUP_IRQHandler ; QHandler DCD WAKEUP_IRQHandler DCD WAKEUP_IRQHandler DCD WAKEUP_IRQHandler DCD WAKEUP_IRQHandler DCD WAKEUP_IRQHandler DCD WAKEUP_IRQHandler DCD WAKEUP_IRQHandler ; PIO1 ( 0:11 ) DCD
CAN_IRQHandler
; CAN DCD SSP1_IRQHandler; SSP1 DCD I2C_IRQHandler; I2C DCD TIMER16_0_IRQHandler; 16-bit Timer0 DCD TIMER16_1_IRQHandler; 16-bit Timer1 DCD TIMER32_0_IRQHandler; dler ; SSP0 DCD UART_IRQHandler ; UART DCD USB_IRQHandler ; USB IRQ DCD USB_FIQHandler ; USB FIQ DCD ADC_IRQHandler ; A/D Converter DCD WDT_IRQHandler ; Watchdog timer
DCD BOD_IRQHandler ; Brown Out Detect
DCD FMC_IRQHandler ; IP2111 Flash Memory Controller
DCD PIOINT3_IRQHandler ; PIO INT3
DCD PIOINT2_IRQHandler ; PIO INT2
DCD PIOINT1_IRQHandler ; PIO INT1
DCD PIOINT0_IRQHandler ; PIO INT0
IF :LNOT::DEF:NO_CRP //进行宏定义判断
AREA |.ARM.__at_0x02FC|, CODE, READONLY
/******************************************************************************************************************************
There are several key places here, "NO_CRP", 0x02FC and 0xFFFFFFFF. If we define "NO_CRP" in the front, then our subsequent code will not work. Therefore, when encryption is needed, the code read protection must not be defined in the front, that is, the encryption keyword. After encryption, the chip can no longer be erased, unless the previously burned program has IAP, which can make the chip enter ISP mode.
******************************************************************************************************************************/
CRP_Key DCD 0xFFFFFFFF // Encryption level
ENDIF
AREA |.text|, CODE, READONLY // Code segment definition
Using the pair of pseudo instructions PROC and ENDP to divide the program segment into several processes makes the program structure clearer.
; Reset Handler
Reset_Handler PROC //Beginning of the procedure
EXPORT Reset_Handler [WEAK] //[WEAK] weak definition, meaning that if the label
//(function) is defined elsewhere, the address of that place will be used when linking. If it is not
//defined elsewhere, the compiler will not report an error, and link with this address
IMPORT __main //Notify the compiler to use the label in other files
LDR R0, =__main //Using "=" indicates that LDR is currently a pseudo-instruction, not a standard instruction. Assign
the address of __main //to R0.
BX R0 //BX is the program jump between the ARM instruction set and the THUMB instruction set
ENDP //End of process
; Dummy Exception Handlers (infinite loops which can be modified)
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .//Jump in place (i.e. infinite loop)
ENDP
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
MemManage_Handler\
PROC
EXPORT MemManage_Handler [WEAK]
B .
ENDP
BusFault_Handler\
PROC
EXPORT BusFault_Handler [WEAK]
B .
ENDP
UsageFault_Handler\
PROC
EXPORT UsageFault_Handler [WEAK]
B .
ENDP
SVC_Handler PROC
EXPORT SVC_Handler [WEAK]
B .
ENDP
DebugMon_Handler\
PROC
EXPORT DebugMon_Handler [WEAK]
B .
ENDP
PendSV_Handler PROC
EXPORT PendSV_Handler [WEAK]
B .
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler [WEAK]
B .
ENDP
Default_Handler PROC
EXPORT WAKEUP_IRQHandler [WEAK]
EXPORT CAN_IRQHandler [WEAK]
EXPORT SSP1_IRQHandler [WEAK]
EXPORT I2C_IRQHandler [WEAK]
EXPORT TIMER16_0_IRQHandler [WEAK]
EXPORT TIMER16_1_IRQHandler [WEAK]
EXPORT TIMER32_0_IRQHandler [WEAK]
EXPORT TIMER32_1_IRQHandler [WEAK]
EXPORT SSP0_IRQHandler [WEAK]
EXPORT UART_IRQHandler [WEAK]
EXPORT USB_IRQHandler [WEAK]
EXPORT USB_FIQHandler [WEAK]
EXPORT ADC_IRQHandler [WEAK]
EXPORT WDT_IRQHandler [WEAK]
EXPORT BOD_IRQHandler [WEAK]
EXPORT FMC_IRQHandler [WEAK]
EXPORT PIOINT3_IRQHandler [WEAK]
EXPORT PIOINT2_IRQHandler [WEAK]
EXPORT PIOINT1_IRQHandler [WEAK]
EXPORT PIOINT0_IRQHandler [WEAK]
WAKEUP_IRQHandler
CAN_IRQHandler
SSP1_IRQHandler
I2C_IRQHandler
TIMER16_0_IRQHandler
TIMER16_1_IRQHandler
TIMER32_0_IRQHandler
TIMER32_1_IRQHandler
SSP0_IRQHandler
UART_IRQHandler
USB_IRQHandler
USB_FIQHandler
ADC_IRQHandler
WDT_IRQHandler
BOD_IRQHandler
FMC_IRQHandler
PIOINT3_IRQHandler
PIOINT2_IRQHandler
PIOINT1_IRQHandler
PIOINT0_IRQHandler
B .
ENDP
ALIGN填充字节使地址对齐
; User Initial Stack & Heap
3. Initialization of heap and stack
IF :DEF:__MICROLIB // Usage of "DEF": DEF:xx means true if xx is defined, otherwise false
EXPORT __initial_sp // Customize the top of the stack
EXPORT __heap_base // Assign global attributes to the starting address of the heap
EXPORT __heap_limit // Assign global attributes to the end limit address of the heap so that it can be called by external programs
ELSE // If __MICROLIB is not defined, use the default C runtime library
IMPORT __use_two_region_memory // Inform the compiler to use the label in other files //__use_two_region_memory
EXPORT __user_initial_stackheap // Declare the global label __user_initial_stackheap so that external programs can also call this label
// Then assign values to the stack and heap and call it during the execution of the __main function
// If the default C library is used, the code under the label // will not be executed during program startup
/******************************************************************************************************************************
_user_initial_stackheap() returns:
· The stack base in r0
· The stack base in r1, which is the highest address in the stack area
· The stack limit in r2
· The stack limit in r3, which is the lowest address in the stack area.
There are single -zone models and dual-zone models.
Single-region model: (r0, r1) is a single stack and heap region. r1 is greater than r0, and r2 and r3 are ignored.
The memory area r0--r1 is shared by the stack and the heap. The stack grows upward from r0, and the stack grows downward from r1.
Two-region model: (r0, r2) is the initial heap, (r3, r1) is the initial stack. r2 is greater than or equal to r0, and r3 is less than r1.
The heap and stack specify separate memory areas.
******************************************************************************************************************************/
__user_initial_stackheap // Label __user_initial_stackheap, indicating the stack initialization program entry
//Then assign values to the stack and the heap, and call it during the execution of the __main function
LDR R0, = Heap_Mem //Save the starting address of the heap
LDR R1, = (Stack_Mem + Stack_Size) //Save the size of the stack
LDR R2, = (Heap_Mem + Heap_Size) //Save the size of the heap
LDR R3, = Stack_Mem //Save the top of the stack pointer
BX LR
ALIGN //Padding bytes to align the addresses
ENDIF
END
Previous article:GPIO Interrupts for LPC178x/7x
Next article:LPC11C14 communication interface I2C
- Popular Resources
- Popular amplifiers
- uCOS-III Kernel Implementation and Application Development Practical Guide - Based on STM32 (Wildfire)
- FreeRTOS kernel implementation and application development practical guide: based on STM32
- Embedded system development tips, a novice\'s growth log and a project manager\'s recipe
- Digital Signal Processing FPGA Implementation Chinese Version
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- I downloaded a source code from the Internet. Please help me find out what IDE this project was developed in. Thanks
- X-NUCLEO-IKS01A3 MakeCode Driver (Extension) Collection
- This strange circuit
- EEWORLD University ---- test
- What is ModBus? What are the differences and connections with RS485 protocol?
- Is this speed too fast? I have never experienced it properly.
- Application Differences between HT8691 and HT8691R
- Welcome the new moderator of the "201420208012" eSports
- What is the difference between a servo motor and a brushless DC motor?
- [Raspberry Pi Pico Review] ADC External Benchmark vs. Onboard Benchmark