Explicar el archivo de inicio STM32 en detalle

 Este artículo explica el código del archivo de inicio STM32 startup_stm32f10x_hd.s El código de este archivo se puede encontrar en cualquier proyecto STM32F10x.

Resumen de las instrucciones de ensamblaje de ARM utilizadas por los archivos de inicio

 

​​​​​​​​​​​​​​​​Pila—— Pila

Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=Stack_Mem SPACE Stack_Size__initial_sp

    El tamaño de la pila abierta es 0X00000400 (1 KB), el nombre es STACK, NOINIT significa sin inicialización, legible y escribible, y alineación de 8 (2^3) bytes.

    La función de la pila se usa para la sobrecarga de variables locales, llamadas a funciones, parámetros de funciones, etc., y el tamaño de la pila no puede exceder el tamaño de la SRAM interna. Si el programa que escribe es relativamente grande y hay muchas variables locales definidas, necesita modificar el tamaño de la pila. Si un día, el programa que escribió tiene un error inexplicable e ingresa una falla grave, entonces debe considerar si la pila no es lo suficientemente grande y se desborda.

    EQU: una pseudoinstrucción para la definición de macros, equivalente a igual, similar a definir en C.

    AREA: Le dice al ensamblador que ensamble un nuevo código o segmento de datos. STACK indica el nombre del segmento, que se puede nombrar arbitrariamente; NOINIT indica que no hay inicialización; READWRITE indica que se puede leer y escribir, ALIGN=3 indica alineación según 2^3, es decir, alineación de 8 bytes.

    ESPACIO: se utiliza para asignar un cierto tamaño de espacio de memoria, la unidad es byte. Aquí el tamaño especificado es igual a Stack_Size.

    La etiqueta __initial_sp se coloca junto a la instrucción SPACE, lo que indica la dirección final de la pila, es decir, la dirección de la parte superior de la pila, y la pila crece de mayor a menor.

montón - montón

    El tamaño del montón abierto es 0X00000200 (512 bytes), el nombre es HEAP, NOINIT significa sin inicialización, legible y escribible, y alineación de 8 (2^3) bytes. __heap_base representa la dirección inicial del par y __heap_limit representa la dirección final del montón. El montón crece de menor a mayor, en dirección opuesta a la dirección de crecimiento de la pila.

    El montón se utiliza principalmente para la asignación de memoria dinámica y la memoria solicitada por la función malloc() está en el montón. Esto se usa menos en STM32.

PRESERVE8 THUMB

   PRESERVE8: especifica que la pila del archivo actual está alineada en 8 bytes.

    THUMB: Indica que las siguientes instrucciones son compatibles con las instrucciones THUMB. THUBM es el conjunto de instrucciones anterior de ARM, 16 bits, ahora la serie Cortex-M utiliza el conjunto de instrucciones THUMB-2, THUMB-2 es de 32 bits, compatible con instrucciones de 16 y 32 bits, es un superconjunto de THUMB. Artículos sobre la pila: una explicación clásica de la pila del lenguaje C.

mesa de vectores

AREA RESET, DATA, READONLYEXPORT __VectorsEXPORT __Vectors_EndEXPORT __Vectors_Size

    Defina un segmento de datos llamado RESET, legible. Y declare que las tres etiquetas __Vectors, __Vectors_End y __Vectors_Size tienen atributos globales y pueden ser llamados por archivos externos.

    EXPORTAR: Declara que una etiqueta puede ser utilizada por archivos externos, para que la etiqueta tenga atributos globales. Si es un compilador IAR, se utiliza la instrucción GLOBAL.

    Cuando el kernel responde a una excepción que ocurre, se ejecuta la rutina de servicio de excepción (ESR) correspondiente. Para determinar la dirección de entrada del ESR, el núcleo utiliza un "mecanismo de búsqueda de tabla de vectores". Aquí se utiliza una tabla vectorial. La tabla de vectores es en realidad una matriz WORD (entero de 32 bits), cada subíndice corresponde a una excepción y el valor del elemento del subíndice es la dirección de entrada del ESR. Se puede establecer la ubicación de la tabla de vectores en el espacio de direcciones, y la dirección de la tabla de vectores se indica a través de un registro de reubicación en el NVIC. Después del reinicio, el valor de este registro es 0. Por lo tanto, se debe incluir una tabla de vectores en la dirección 0 (es decir, la dirección 0 de FLASH) para la asignación de excepción inicial. Cabe señalar que aquí hay una alternativa: el tipo 0 no es una dirección de entrada, sino un valor inicial de MSP después del reinicio. La siguiente figura es la tabla de vectores de F103.

__Vectors DCD __initial_sp ;栈顶地址DCD Reset_Handler ;复位程序地址DCD NMI_HandlerDCD HardFault_HandlerDCD MemManage_HandlerDCD BusFault_HandlerDCD UsageFault_HandlerDCD 0 ; 0 表示保留DCD 0DCD 0DCD 0DCD SVC_HandlerDCD DebugMon_HandlerDCD 0DCD PendSV_HandlerDCD SysTick_Handler;外部中断开始DCD WWDG_IRQHandlerDCD PVD_IRQHandlerDCD TAMPER_IRQHandler;限于篇幅,中间代码省略DCD DMA2_Channel2_IRQHandlerDCD DMA2_Channel3_IRQHandlerDCD DMA2_Channel4_5_IRQHandler__Vectors_End__Vectors_Size EQU __Vectors_End - __Vectors

    __Vectors es la dirección de inicio de la tabla de vectores, __Vectors_End es la dirección final de la tabla de vectores y el tamaño de la tabla de vectores se puede calcular restando los dos.

    La tabla de vectores se coloca a partir de la dirección 0 de FLASH, con 4 bytes como unidad, la dirección 0 almacena la dirección superior de la pila, 0X04 almacena la dirección del programa de reinicio, y así sucesivamente. Desde el punto de vista del código, los nombres de las funciones del servicio de interrupción se almacenan en la tabla de vectores, pero sabemos que el nombre de la función en lenguaje C es una dirección.

    DCD: Asigna una o más palabras de memoria, alineadas con cuatro bytes, y requiere la inicialización de estas memorias. En la tabla de vectores, DCD asigna un montón de memoria y los inicializa con la dirección de entrada del ESR.

procedimiento de reinicio

AREA |.text|, CODE, READONLY

    Defina un segmento de código llamado .text, que sea legible.

 

    La subrutina de reinicio es el primer programa que se ejecuta después de encender el sistema. Llama a la función SystemInit para inicializar el reloj del sistema, luego llama a la función de biblioteca C _mian y finalmente llama a la función principal para ir al mundo C.

    DÉBIL: indica una definición débil. Si el archivo externo define primero la etiqueta, se hará referencia primero a la etiqueta. Si el archivo externo no declara, no habrá error. Esto significa que el usuario puede volver a implementar la subrutina de restablecimiento en otros archivos, lo cual no es único aquí.

    IMPORT: Indica que la etiqueta proviene de un archivo externo, similar a la palabra clave EXTERN en lenguaje C. Aquí significa que las dos funciones SystemInit y __main son de archivos externos.

    SystemInit() es una función de biblioteca estándar definida en el archivo de biblioteca system_stm32f10x.c. La función principal es configurar el reloj del sistema.Después de llamar a esta función aquí, la configuración del reloj del sistema del microcontrolador se configura a 72M. __main es una función de biblioteca C estándar, su función principal es inicializar la pila del usuario y llamar a la función principal al final de la función para ir al mundo C. Es por eso que cada programa que escribimos tiene una función principal.

     LDR, BLX y BX son las instrucciones del núcleo CM4, que se pueden consultar en el Capítulo 4 - Conjunto de instrucciones de la "Guía autorizada CM3 CnR2". Las funciones específicas se muestran en la siguiente tabla:

 rutina de servicio de interrupción

    En el archivo de inicio, todas las funciones de servicio de interrupción para interrupciones se han escrito para nosotros. La diferencia con las funciones de servicio de interrupción que solemos escribir es que estas funciones están vacías. El programa de servicio de interrupción real debe volver a implementarse en un C externo. archivo. , aquí hay solo un lugar por adelantado.

    Si habilitamos una interrupción cuando usamos un determinado periférico, pero olvidamos escribir la rutina de servicio de interrupción de soporte o escribimos el nombre de función incorrecto, cuando llegue la interrupción, el programa saltará al archivo de inicio preescrito en la rutina de servicio de interrupción vacía. , y bucle infinito en esta función vacía, es decir, el programa muere aquí.

NMI_Handler PROC ;系统异常EXPORT NMI_Handler [WEAK]B .ENDP;限于篇幅,中间代码省略SysTick_Handler PROCEXPORT SysTick_Handler [WEAK]B .ENDPDefault_Handler PROC ;外部中断EXPORT WWDG_IRQHandler [WEAK]EXPORT PVD_IRQHandler [WEAK]EXPORT TAMP_STAMP_IRQHandler [WEAK];限于篇幅,中间代码省略LTDC_IRQHandlerLTDC_ER_IRQHandlerDMA2D_IRQHandlerB .ENDP

   B: Saltar a una etiqueta. Salta a un '.' aquí, lo que significa un ciclo infinito

Inicialización de la pila de usuario

ALIGN

    ALINEAR: Alinea la dirección donde se almacena la instrucción o dato, seguido de un valor inmediato. El valor predeterminado significa alineación de 4 bytes.

  • 栈和堆初始化,由 C 库函数_main 来完成IF :DEF:__MICROLIB ;这个宏在 KEIL 里面开启EXPORT __initial_spEXPORT __heap_baseEXPORT __heap_limitELSEIMPORT __use_two_region_memory ; 这个函数由用户自己实现EXPORT __user_initial_stackheap__user_initial_stackheapLDR R0, = Heap_MemLDR R1, =(Stack_Mem + Stack_Size)LDR R2, = (Heap_Mem + Heap_Size)LDR R3, = Stack_MemBX LRALIGNENDIFEND

    Primero juzgue si __MICROLIB está definido.Si esta macro está definida, las etiquetas __initial_sp (dirección superior de la pila), __heap_base (dirección de inicio del montón), __heap_limit (dirección final del montón) se otorgan para ser llamados por archivos externos. Configuramos esta macro en KEIL, vea la figura a continuación para más detalles. Luego, la inicialización de la pila se realiza mediante la función de biblioteca C _main.

 

   Si __MICROLIB no está definido, se usa el modo de memoria de segmento dual y la etiqueta de declaración __user_initial_stackheap tiene atributos globales, lo que permite a los usuarios inicializar la pila por sí mismos.

    Para el código de ensamblaje anterior, debe prestar atención a:

  • IF, ELSE, ENDIF: declaración de ramificación condicional de ensamblaje, similar al lenguaje C if, else

  • FIN: fin del archivo

Supongo que te gusta

Origin blog.csdn.net/qq_41050642/article/details/128322445
Recomendado
Clasificación