Cortex-M0 (NXP LPC11C14) startup code analysis

Publisher:心满愿望Latest update time:2019-01-15 Source: eefocusKeywords:Cortex-M0  LPC11C14 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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


Keywords:Cortex-M0  LPC11C14 Reference address:Cortex-M0 (NXP LPC11C14) startup code analysis

Previous article:GPIO Interrupts for LPC178x/7x
Next article:LPC11C14 communication interface I2C

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号