Detailed explanation of Huada (now renamed Xiaohua Semiconductor) chip startup file

The source code file name of this article is: startup_hcf460.S, which is a pure assembly file.

First of all, you need to master some basic assembly syntax, and the main used lists are marked (refer to stm32 related information):

 Because it is different from stm32, the sram3 area of ​​the Huada chip is a bit special. Please refer to the Huada chip user manual.

 The STR instruction is used in the startup file. The format of the STR instruction is:
STR{condition} source register, <memory address>
The STR instruction is used to transfer a 32-bit word data from the source register to the memory. This instruction is commonly used in programming
. The addressing methods are flexible and diverse. For usage, please refer to the instruction LDR.

Instruction example:
STR R0, [R1], #8; Write the word data in R0 into the memory with R1 as the address, and write the new address R1+8 into R1.
STR R0, [R1, #8]; Write the word data in R0 into the memory with the address R1+8.
str r1, [r0]; transfer the value of the r1 register to the (memory) memory with the address value r0

Pay attention to the semicolon; it is a comment mark in assembly, similar to C++'s //.

1. Stack area

Stack_Size      EQU     0x00000400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp

The size of the opened stack is 0x00000400 (1k B), the name is STACK, NOINIT means not initialized, readable and writable, 8 (23) byte aligned. The stack is used for overhead of local variables, function calls, function parameters, etc. The size of the stack cannot exceed the size of the internal SRAM. If the program you write is relatively large and has many local variables defined, you need to modify the stack size. If one day, the program you wrote has an inexplicable error and enters a hard fault, then you need to consider whether the stack is not large enough and has overflowed. EQU: Macro definition pseudo-instruction, equivalent to equal, similar to define in C.

AREA: Tells the assembler to assemble a new code segment or data segment.

STACK represents the segment name, which can be named arbitrarily; NOINIT means not initialized; READWRITE means readable and writable, ALIGN=3 means aligned according to 2^3, that is, 8-byte alignment.

SPACE: used to allocate a certain size of memory space, in bytes. The size specified here is equal to Stack_Size. The label __initial_sp is placed next to the SPACE statement, indicating the end address of the stack, that is, the top address of the stack (the stack grows from high to low).

2. Heap area

Heap_Size       EQU     0x00000200

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

 The size of the allocated heap is 0x00000200 (512 bytes), the name is HEAP, NOINIT means not initialized, readable and writable, and 8 (2^3) byte aligned. __heap_base represents the starting address of the heap, and __heap_limit represents the end address of the heap (the heap grows from low to high, which is opposite to the growth direction of the stack). The heap is mainly used for dynamic memory allocation. The memory requested by the malloc() function is on the heap.

                PRESERVE8
                THUMB

PRESERVE8: Specifies that the stack of the current file is aligned to 8 bytes.

THUMB: Indicates that the following instructions are compatible with the THUMB instruction.

THUBM is ARM's previous instruction set, 16 bits. Now the Cortex-M series uses the THUMB-2 instruction set. THUMB-2 is 32-bit, compatible with 16-bit and 32-bit instructions, and is a superset of THUMB.

3. Vector table

                AREA    RESET, DATA, READONLY
                EXPORT  __Vectors
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size

Define a data segment with the name RESET, which is readable, and declare that the three labels __Vectors, __Vectors_End and __Vectors_Size have global attributes and can be called by external files.

EXPORT: declares that a label can be used by external files, giving the label global attributes. If it is an IAR compiler, use the GLOBAL directive. When the kernel responds to an exception that occurs, the corresponding exception service routine (ESR) is executed. In order to determine the entry address of the ESR, the kernel uses the "vector lookup table mechanism". A vector table is used here, see the table below. The vector table is actually a WORD (32-bit integer) array, each subscript corresponds to an exception, and the value of the subscript element is the entry address of the ESR. The location of the vector table in the address space can be set, and the address of the vector table is pointed out through a relocation register in the NVIC. After reset, the value of this register is 0. Therefore, a vector table must be included at address 0 (ie Flash address 0) for initial exception allocation. It should be noted that there is something different here: type 0 is not an entry address, but gives the initial value of MSP after reset.

For the interrupt vector table, please refer to the user manual. Note that the driver library has been updated on the official website, and the user manual has also been updated.

 The vector table code is relatively long and takes up most of the startup code.

__Vectors       DCD     __initial_sp              ; Top of Stack
                DCD     Reset_Handler             ; Reset Handler
                DCD     NMI_Handler               ; 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
                DCD     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

                ; Peripheral Interrupts
                DCD     IRQ000_Handler        ; IRQ000_Handler
                DCD     IRQ001_Handler        ; IRQ001_Handler
                DCD     IRQ002_Handler        ; IRQ002_Handler
                DCD     IRQ003_Handler        ; IRQ003_Handler
                DCD     IRQ004_Handler        ; IRQ004_Handler
                DCD     IRQ005_Handler        ; IRQ005_Handler
                DCD     IRQ006_Handler        ; IRQ006_Handler
                DCD     IRQ007_Handler        ; IRQ007_Handler
                DCD     IRQ008_Handler        ; IRQ008_Handler
                DCD     IRQ009_Handler        ; IRQ009_Handler
                DCD     IRQ010_Handler        ; IRQ010_Handler
                DCD     IRQ011_Handler        ; IRQ011_Handler
                DCD     IRQ012_Handler        ; IRQ012_Handler
                DCD     IRQ013_Handler        ; IRQ013_Handler
                DCD     IRQ014_Handler        ; IRQ014_Handler
                DCD     IRQ015_Handler        ; IRQ015_Handler
                DCD     IRQ016_Handler        ; IRQ016_Handler
                DCD     IRQ017_Handler        ; IRQ017_Handler
                DCD     IRQ018_Handler        ; IRQ018_Handler
                DCD     IRQ019_Handler        ; IRQ019_Handler
                DCD     IRQ020_Handler        ; IRQ020_Handler
                DCD     IRQ021_Handler        ; IRQ021_Handler
                DCD     IRQ022_Handler        ; IRQ022_Handler
                DCD     IRQ023_Handler        ; IRQ023_Handler
                DCD     IRQ024_Handler        ; IRQ024_Handler
                DCD     IRQ025_Handler        ; IRQ025_Handler
                DCD     IRQ026_Handler        ; IRQ026_Handler
                DCD     IRQ027_Handler        ; IRQ027_Handler
                DCD     IRQ028_Handler        ; IRQ028_Handler
                DCD     IRQ029_Handler        ; IRQ029_Handler
                DCD     IRQ030_Handler        ; IRQ030_Handler
                DCD     IRQ031_Handler        ; IRQ031_Handler
                DCD     IRQ032_Handler        ; IRQ032_Handler
                DCD     IRQ033_Handler        ; IRQ033_Handler
                DCD     IRQ034_Handler        ; IRQ034_Handler
                DCD     IRQ035_Handler        ; IRQ035_Handler
                DCD     IRQ036_Handler        ; IRQ036_Handler
                DCD     IRQ037_Handler        ; IRQ037_Handler
                DCD     IRQ038_Handler        ; IRQ038_Handler
                DCD     IRQ039_Handler        ; IRQ039_Handler
                DCD     IRQ040_Handler        ; IRQ040_Handler
                DCD     IRQ041_Handler        ; IRQ041_Handler
                DCD     IRQ042_Handler        ; IRQ042_Handler
                DCD     IRQ043_Handler        ; IRQ043_Handler
                DCD     IRQ044_Handler        ; IRQ044_Handler
                DCD     IRQ045_Handler        ; IRQ045_Handler
                DCD     IRQ046_Handler        ; IRQ046_Handler
                DCD     IRQ047_Handler        ; IRQ047_Handler
                DCD     IRQ048_Handler        ; IRQ048_Handler
                DCD     IRQ049_Handler        ; IRQ049_Handler
                DCD     IRQ050_Handler        ; IRQ050_Handler
                DCD     IRQ051_Handler        ; IRQ051_Handler
                DCD     IRQ052_Handler        ; IRQ052_Handler
                DCD     IRQ053_Handler        ; IRQ053_Handler
                DCD     IRQ054_Handler        ; IRQ054_Handler
                DCD     IRQ055_Handler        ; IRQ055_Handler
                DCD     IRQ056_Handler        ; IRQ056_Handler
                DCD     IRQ057_Handler        ; IRQ057_Handler
                DCD     IRQ058_Handler        ; IRQ058_Handler
                DCD     IRQ059_Handler        ; IRQ059_Handler
                DCD     IRQ060_Handler        ; IRQ060_Handler
                DCD     IRQ061_Handler        ; IRQ061_Handler
                DCD     IRQ062_Handler        ; IRQ062_Handler
                DCD     IRQ063_Handler        ; IRQ063_Handler
                DCD     IRQ064_Handler        ; IRQ064_Handler
                DCD     IRQ065_Handler        ; IRQ065_Handler
                DCD     IRQ066_Handler        ; IRQ066_Handler
                DCD     IRQ067_Handler        ; IRQ067_Handler
                DCD     IRQ068_Handler        ; IRQ068_Handler
                DCD     IRQ069_Handler        ; IRQ069_Handler
                DCD     IRQ070_Handler        ; IRQ070_Handler
                DCD     IRQ071_Handler        ; IRQ071_Handler
                DCD     IRQ072_Handler        ; IRQ072_Handler
                DCD     IRQ073_Handler        ; IRQ073_Handler
                DCD     IRQ074_Handler        ; IRQ074_Handler
                DCD     IRQ075_Handler        ; IRQ075_Handler
                DCD     IRQ076_Handler        ; IRQ076_Handler
                DCD     IRQ077_Handler        ; IRQ077_Handler
                DCD     IRQ078_Handler        ; IRQ078_Handler
                DCD     IRQ079_Handler        ; IRQ079_Handler
                DCD     IRQ080_Handler        ; IRQ080_Handler
                DCD     IRQ081_Handler        ; IRQ081_Handler
                DCD     IRQ082_Handler        ; IRQ082_Handler
                DCD     IRQ083_Handler        ; IRQ083_Handler
                DCD     IRQ084_Handler        ; IRQ084_Handler
                DCD     IRQ085_Handler        ; IRQ085_Handler
                DCD     IRQ086_Handler        ; IRQ086_Handler
                DCD     IRQ087_Handler        ; IRQ087_Handler
                DCD     IRQ088_Handler        ; IRQ088_Handler
                DCD     IRQ089_Handler        ; IRQ089_Handler
                DCD     IRQ090_Handler        ; IRQ090_Handler
                DCD     IRQ091_Handler        ; IRQ091_Handler
                DCD     IRQ092_Handler        ; IRQ092_Handler
                DCD     IRQ093_Handler        ; IRQ093_Handler
                DCD     IRQ094_Handler        ; IRQ094_Handler
                DCD     IRQ095_Handler        ; IRQ095_Handler
                DCD     IRQ096_Handler        ; IRQ096_Handler
                DCD     IRQ097_Handler        ; IRQ097_Handler
                DCD     IRQ098_Handler        ; IRQ098_Handler
                DCD     IRQ099_Handler        ; IRQ099_Handler
                DCD     IRQ100_Handler        ; IRQ100_Handler
                DCD     IRQ101_Handler        ; IRQ101_Handler
                DCD     IRQ102_Handler        ; IRQ102_Handler
                DCD     IRQ103_Handler        ; IRQ103_Handler
                DCD     IRQ104_Handler        ; IRQ104_Handler
                DCD     IRQ105_Handler        ; IRQ105_Handler
                DCD     IRQ106_Handler        ; IRQ106_Handler
                DCD     IRQ107_Handler        ; IRQ107_Handler
                DCD     IRQ108_Handler        ; IRQ108_Handler
                DCD     IRQ109_Handler        ; IRQ109_Handler
                DCD     IRQ110_Handler        ; IRQ110_Handler
                DCD     IRQ111_Handler        ; IRQ111_Handler
                DCD     IRQ112_Handler        ; IRQ112_Handler
                DCD     IRQ113_Handler        ; IRQ113_Handler
                DCD     IRQ114_Handler        ; IRQ114_Handler
                DCD     IRQ115_Handler        ; IRQ115_Handler
                DCD     IRQ116_Handler        ; IRQ116_Handler
                DCD     IRQ117_Handler        ; IRQ117_Handler
                DCD     IRQ118_Handler        ; IRQ118_Handler
                DCD     IRQ119_Handler        ; IRQ119_Handler
                DCD     IRQ120_Handler        ; IRQ120_Handler
                DCD     IRQ121_Handler        ; IRQ121_Handler
                DCD     IRQ122_Handler        ; IRQ122_Handler
                DCD     IRQ123_Handler        ; IRQ123_Handler
                DCD     IRQ124_Handler        ; IRQ124_Handler
                DCD     IRQ125_Handler        ; IRQ125_Handler
                DCD     IRQ126_Handler        ; IRQ126_Handler
                DCD     IRQ127_Handler        ; IRQ127_Handler
                DCD     IRQ128_Handler        ; IRQ128_Handler
                DCD     IRQ129_Handler        ; IRQ129_Handler
                DCD     IRQ130_Handler        ; IRQ130_Handler
                DCD     IRQ131_Handler        ; IRQ131_Handler
                DCD     IRQ132_Handler        ; IRQ132_Handler
                DCD     IRQ133_Handler        ; IRQ133_Handler
                DCD     IRQ134_Handler        ; IRQ134_Handler
                DCD     IRQ135_Handler        ; IRQ135_Handler
                DCD     IRQ136_Handler        ; IRQ136_Handler
                DCD     IRQ137_Handler        ; IRQ137_Handler
                DCD     IRQ138_Handler        ; IRQ138_Handler
                DCD     IRQ139_Handler        ; IRQ139_Handler
                DCD     IRQ140_Handler        ; IRQ140_Handler
                DCD     IRQ141_Handler        ; IRQ141_Handler
                DCD     IRQ142_Handler        ; IRQ142_Handler
                DCD     IRQ143_Handler        ; IRQ143_Handler

__Vectors_End

__Vectors_Size  EQU     __Vectors_End - __Vectors

 __Vectors is the starting address of the vector table, __Vectors_End is the ending address of the vector table, and the size of the vector table can be calculated by subtracting the two. The vector table is placed starting from address 0 of Flash, with 4 bytes as a unit. Address 0 stores the top address of the stack, 0x04 stores the address of the reset program, and so on. From the code point of view, the vector table stores the function names of the interrupt service functions, but we know that the function name in C language is an address. DCD: Allocate one or more words of memory, aligned with 4 bytes, and require initialization of these memories. In the vector table, DCD allocates a bunch of memory and initializes them with the entry address of the ESR.

4. Reset procedure

AREA    |.text|, CODE, READONLY

Define a code segment named .text, read-only.

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  SystemInit
                IMPORT  __main
SET_SRAM3_WAIT
                LDR     R0, =0x40050804
                MOV     R1, #0x77
                STR     R1, [R0]

                LDR     R0, =0x4005080C
                MOV     R1, #0x77
                STR     R1, [R0]

                LDR     R0, =0x40050800
                MOV     R1, #0x1100
                STR     R1, [R0]

                LDR     R0, =0x40050804
                MOV     R1, #0x76
                STR     R1, [R0]

                LDR     R0, =0x4005080C
                MOV     R1, #0x76
                STR     R1, [R0]

                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =__main
                BX      R0
                ENDP

 The reset subroutine is the first program executed after the system is powered on. It calls the System Init function to initialize the system clock, then calls the C library function _mian, and finally calls the main function to enter the C language world.

WEAK: Indicates a weak definition. If the external file defines the label first, the label will be referenced first. If the external file does not declare it, no error will occur. This means that the reset subroutine can be re-implemented by the user in other files, and this is not the only one. IMPORT: Indicates that the label comes from an external file, similar to the EXTERN keyword in C language. This means that the two functions System Init and __main come from external files.

System Init(): A standard library function, defined in the system_hc32f460.c library file. Its main function is to configure the system clock. The clock here needs to be configured by the user. The maximum frequency of the Huada chip supports 200M.

__main: A standard C library function whose main function is to initialize the user stack and call the main function at the end of the function to enter the C language world. This is why every program we write has a main function. LDR, BLX, and BX are instructions of the CM4 core, which can be found in Chapter 4 of "CM3 Authoritative Guide Cn R2". The specific functions are shown in the table below.

 It is worth noting that there is a piece of code above that operates the R0 and R1 registers. What does this code mean? Check the manual and find the address of 0x40050804. It is found that the control register of sram is operated. After comparing the manual in detail, the function is to set the read and write waiting period for the sram3 area to 2 cycles.

 

 5. Interrupt service routine

The code below is the interrupt service routine. It is too long and will not be pasted. The startup file has helped us write all the interrupt service functions, but unlike the interrupt service functions we usually write, these functions are empty. The real interrupt service program needs to be re-implemented in the external C file. Here is just the advance Just occupied a position. If you enable an interrupt when using a certain peripheral, but forget to write the supporting interrupt service routine or write the wrong function name, then when the interrupt comes, the program will jump to the space pre-written in the startup file. in the interrupt service routine, and loops infinitely in this empty function, that is, the program "dies" here.

6. User stack initialization

                ALIGN


; User Initial Stack & Heap

                IF      :DEF:__MICROLIB

                EXPORT  __initial_sp
                EXPORT  __heap_base
                EXPORT  __heap_limit

                ELSE

                IMPORT  __use_two_region_memory
                EXPORT  __user_initial_stackheap

__user_initial_stackheap PROC
                LDR     R0, =  Heap_Mem
                LDR     R1, =(Stack_Mem + Stack_Size)
                LDR     R2, = (Heap_Mem +  Heap_Size)
                LDR     R3, = Stack_Mem
                BX      LR
                ENDP

                ALIGN

                ENDIF


                END

 ALIGN: Align the address where the instruction or data is stored, followed by an immediate number. The default indicates 4-byte alignment.

First, determine whether __MICROLIB is defined. If this macro is defined, the labels __initial_sp (top address of stack), __heap_base (starting address of heap), and __heap_limit (end address of heap) are given global attributes, which can be called by external files. This macro is configured in KEIL, as shown in the figure below. Then the initialization of the stack is completed by the C library function _main.

 If __MICROLIB is not defined, dual-segment memory mode is used, and the label __user_initial_stackheap is declared to have global attributes, allowing users to initialize the stack themselves. IF, ELSE, ENDIF: Assembly conditional branch statements, similar to if and else in C language. END: End of file.

Summarize:

The startup file is written in assembly language and is the first program executed after the system is powered on and reset. It mainly does the following work:

1) Initialize the stack pointer: SP=_initial_sp.

2) Initialization program pointer: PC=Reset_Handler.

3) Initialize the interrupt vector table.

4) Set the waiting period of sram3 and configure the system clock.

5) Call the C library function _main to initialize the user stack, and finally call the main function to enter the C language world.

Guess you like

Origin blog.csdn.net/weixin_41579872/article/details/127653434