Analyse startup_stm32f407xx.s

1. Instructions d'assemblage ARM utilisées

Nom de la commande Fonction de commande
EQU Donner un nom symbolique à une constante numérique, équivalent à définir en C
RÉGION Assembler un nouveau segment de code ou segment de données
ESPACE Allouer de l'espace mémoire
PRESERVE8 La pile de fichiers actuelle doit être alignée sur 8 octets
EXPORTATION Déclarez une étiquette avec des attributs globaux qui peuvent être utilisés par des fichiers externes
IMPORTATION Déclarer une étiquette d'un fichier externe
DCD Allouer de la mémoire en unités de mots, nécessiter un alignement sur 4 octets et exiger l'initialisation de ces mémoires
PROC Définir des sous-programmes, associés à ENDP
ENDP Indique la fin du sous-programme
FAIBLE Définition faible, si le fichier externe définit une étiquette, l'étiquette du fichier externe est préférentiellement utilisée, qui est la pseudo-instruction ARM
ALIGNER Le compilateur aligne l'adresse de stockage des instructions ou des données. Par défaut, il indique un alignement sur 4 octets, qui est une pseudo-instruction ARM
SI, AUTRE, ENDIF Instruction de branche conditionnelle d'assembly, similaire au langage C
LDR Charger des mots de la mémoire dans un registre
B Aller à une étiquette
BL Sautez à l'adresse donnée par le registre / étiquette, et sauvegardez l'instruction suivante avant le saut en LR
BX Aller à l'adresse donnée par le registre / étiquette et déterminer l'état du processeur en fonction du LSE du registre
BLX Sautez à l'adresse donnée par le registre / étiquette, et déterminez l'état du processeur selon le LSE du registre, et sauvegardez l'instruction suivante avant le saut en LR
FIN Atteindre la fin du fichier, la fin du fichier

Deuxièmement, la fonction principale du fichier

  • Initialisation de pile et de tas
  • Table de vecteur d'interruption d'initialisation
  • Appelez Reset_Handler
  • Autres codes

3. Analyse du contenu du document

Stack_Size      EQU     0x00000400

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

初始化栈:
开辟栈大小为0x00000400(1KB),名字为STACK,NOINIT不初始化,可读可写,8(2^3)字节对齐。 栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM 的大小。如果编写的程序比较大,定义的局部变量很多,那么就需要修改栈的大小。如果某一天,你写的程序出现了莫名奇怪的错误,并进入了硬fault 的时候,这时你就要考虑下是不是栈不够大而溢出了。 

Heap_Size       EQU     0x00000200

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

初始化堆:
开辟堆大小为0x00000200(512字节),名字为HEAP,不初始化,可读可写,8字节对齐。堆主要用于动态内存的分配。

PRESERVE8
THUMB

指定当前文件的堆栈按照8字节对齐,且后面的指令兼容THUMB指令

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

定义一个名为RESET的数据段,只读。并声明 __Vectors、__Vectors_End 和__Vectors_Size 三个具有全局属性的标号,可供外部的文件调用。

__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     HASH_RNG_IRQHandler               ; Hash and Rng
                DCD     FPU_IRQHandler                    ; FPU
            
__Vectors_End

__Vectors_Size  EQU  __Vectors_End - __Vectors

__Vectors 为向量表起始地址,__Vectors_End 为向量表结束地址,两个相减即可算出向量表大小。向量表从FLASH 的0地址开始放置,以4个字节为一个单位,地址0 存放的是栈顶地址,0X04存放的是复位程序的地址,以此类推。

AREA    |.text|, CODE, READONLY

定义一个名为.text的代码段,只读。

Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

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

复位子程序是系统上电后第一个执行的程序,调用SystemInit函数初始化系统时钟,然后调用C库函数__main,最终调用main函数去到C的世界。

NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP
......
                B       .
                ENDP

B		.表示无限循环
在启动文件里面已经帮我们写好所有中断的中断服务函数,跟我们平时写的中断服务函数不一样的就是这些函数都是空的,真正的中断复服务程序需要我们在外部的C 文件里面重新实现,这里只是提前占了一个位置而已。

如果我们在使用某个外设的时候,开启了某个中断,但是又忘记编写配套的中断服务程序或者函数名写错,那当中断来临的时,程序就会跳转到启动文件预先写好的空的中断服务程序中,并且在这个空函数中无限循环,即程序就死在这里。

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

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

ALIGN

ENDIF

END

用户堆栈初始化由C库函数__main完成,__MICROLIB由KEIL里面开启,__use_two_region_memory由用户自己实现。
Publié 81 articles originaux · 21 éloges · 30 000+ vues

Je suppose que tu aimes

Origine blog.csdn.net/qq_33575901/article/details/103135465
conseillé
Classement