02_STM32启动文件详解

目录

介绍

一、Stack-栈(使用的是RAM的内存)

二、Heap-推(使用的是RAM的内存)

三、中断向量表(使用的是flash)

四、复位函数

五、中断服务函数地址


六、堆和栈的初始化


介绍

启动文件是以.s后缀的汇编编写的,启动文件的作用:

1.初始化推栈指针SP  

2.初初始化PC指针,指向复位程序

3.初始化中断向量表

4.配置系统时钟

5.调用C库函数_main,最终进入c语言编写的代码

一、Stack-栈(使用的是RAM的内存)

作用:用于局部变量、函数调用、函数形参的开销

汇编指令讲解:

EQU:宏定义的伪指令,相当于等于,类似于C语言中的宏定义define

AREA: 告诉汇编器汇编一个新的代码段或者数据段

SPACE:用于分配一定大小的内存空间,单位字节

Stack_Size      EQU     0x00000400

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

Stack_Size      EQU     0x00000400

Stack_Size 等于 0x00000400(1kb)的空间

AREA    STACK, NOINIT, READWRITE, ALIGN=3

定义栈空间  命名为STACK,NOINIT表示不初始化,READWRITE表示可读可写,ALIGN=3表示2的3次方(8个字节)对齐开辟。

Stack_Mem       SPACE   Stack_Size

分配内存为Stack_Size大小的空间单位字节

__initial_sp

初始化栈指针就是指向栈顶地址(栈使用的时候栈顶先出依次到栈底,先进后出)

标号__initial_sp紧挨着SPACE语句放置,表示栈的结束地址,即栈顶地址,栈是由高向低生长的。

二、Heap-推(使用的是RAM的内存)

作用:用于动态内存的分配,malloc函数

EQU:宏定义的伪指令,相当于等于,类似于C语言中的宏定义define

AREA: 告诉汇编器汇编一个新的代码段或者数据段

SPACE:用于分配一定大小的内存空间,单位字节

Heap_Size       EQU     0x00000400

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

Heap_Size       EQU     0x00000400

Heap_Size 等于 0x00000400(1kb)的空间

AREA    STACK, NOINIT, READWRITE, ALIGN=3

定义栈空间  命名为HEAP,NOINIT表示不初始化,READWRITE表示可读可写,ALIGN=3表示2的3次方(8个字节)对齐开辟。

__heap_base

表示堆的起始地址

Heap_Mem        SPACE   Heap_Size

分配内存为Heap_Size大小的空间单位字节

__heap_limit

初始化推指针

标号__initial_sp紧挨着SPACE语句放置,表示推的结束地址,堆是由低向高生长的(于栈相反)。

                PRESERVE8
                THUMB

PRESERVE8表示指定当前文件的推栈按照8字节对齐

THUMB表示后面指令位THUMB指令

三、中断向量表(使用的是flash)

AREA: 告诉汇编器汇编一个新的代码段或者数据段

EXPORT:声明一个标号具有全局属性,类似于C中的extem功能

DCD:分配一个或者多个以字节为单位的内存,以四字节对齐,并要求初始化这些内存。在向量表中,DCD分配了一推内存,并且以ESR的入口地址初始化它们。

AREA: 告诉汇编器汇编一个新的代码段或者数据段

1.向量表实际上是一个32位的整形数组,一个元素对应一个异常(ESR:中断程序服务地址),数组元素存的就是ESR的入口地址。

2.向量表在复位后从FLASH的0地址开始,具体的初始化值查询参考手册的中断章节。

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

AREA    RESET, DATA, READONLY

定义一个数据段 命名为RESET,DATA表示数据, READONLY表示可读

EXPORT  __Vectors

表示向量表的开始地址(全局属性)

EXPORT  __Vectors_End

表示向量表的结束地址(全局属性)

EXPORT  __Vectors_Size

表示向量表的大小(全局属性)

__Vectors       DCD     __initial_sp
               DCD     Reset_Handler 
等等很多
               DCD     SysTick_Handler 
               DCD     WWDGT_IRQHandler  
等等很多
               DCD     USBFS_IRQHandler
__Vectors_End

__Vectors_Size  EQU     __Vectors_End - __Vectors

                AREA    |.text|, CODE, READONLY

__Vectors       DCD     __initial_sp                      

中断向量表的第一个字节存放的是__initial_sp栈顶的指针

               DCD     Reset_Handler

中断向量表的第二个字节存放的是Reset_Handler函数入口地址

              DCD     SysTick_Handler

SysTick_Handler以上是内核使用的

DCD     WWDGT_IRQHandler

从 WWDGT_IRQHandler到USBFS_IRQHandler,都是用户使用的。

__Vectors_End

表示向量表结束

__Vectors_Size  EQU     __Vectors_End - __Vectors

表示量表的大小   __Vectors_Size=Vectors结束地址-Vectors开始地址

AREA    |.text|, CODE, READONLY

定义一个代码段   命名text, CODE表示代码段,READONLY只读

四、复位函数

PROC:表示子程序的开始

EXPORT:声明一个标号具有全局属性,类似于C中的extem功能

WEAK:表示弱定义,如果外部文件优先定义了该标号则首先引用该标号,如果外部文件没有声明也不会出错。这里表示复位子程序可以有程序用户在其他文件重新实现,这里并不是唯一的。

IMPORT:表示该标号来自外部文件,跟C语言中的extern关键字类似。

LDR:从存储器中加载字到一个寄存器中

BLX:跳转到有寄存器给出的地址,并根据寄存器的LES确定处理器的状态,还要吧跳转钱的下一条指令地址保存到LR

BX:跳转到有寄存器/标号给出的地址,不用返回

ENDP:表示子程序的结束

Reset_Handler   PROC
                EXPORT  Reset_Handler                     [WEAK]
                IMPORT  SystemInit
                IMPORT  __main
                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =__main
                BX      R0
                ENDP

Reset_Handler   PROC

表示复位子程序开始

               EXPORT  Reset_Handler                     [WEAK]

表示用户可在其他地方定义全局函数

                IMPORT  SystemInit

外部的一个函数SystemInit:主要初始化系统时钟

                IMPORT  __main

外部的一个函数

LDR     R0, =SystemInit

把SystemInit函数入口地址加载到R0寄存器中

BLX     R0

跳转到R0寄存器去执行里面的函数,执行完返回。

                LDR     R0, =__main

把__main函数入口地址加载到R0寄存器中。

(注意这里的_main不是我们写程序的main,这里的_main是外部导入进来的,是C库里面的,执行这个_main后最后会道我们写程序的main里面)

_main的作用:1.初始化程序里面的局部变量全局变量由C库完成2.调用我们写程序的mai函数

                BX      R0

执行完不用返回

                ENDP

子程序结束

五、中断服务函数地址

PROC:表示子程序的开始

EXPORT:声明一个标号具有全局属性,类似于C中的extem功能

WEAK:表示弱定义,如果外部文件优先定义了该标号则首先引用该标号,如果外部文件没有声明也不会出错。这里表示复位子程序可以有程序用户在其他文件重新实现,这里并不是唯一的。

B .:表示无限循环

用汇编全写好了,在三章中断向量表初化函数__initial_sp用到

NMI_Handler     PROC
                EXPORT  NMI_Handler                       [WEAK]
                B       .
                ENDP

NMI_Handler     PROC

表示子程序的开始

                EXPORT  NMI_Handler                       [WEAK]

表示用户可在其他地方定义全局函数

                B       .

表示无限循环

                ENDP

子程序结束

六、堆和栈的初始化

上面我们只是开辟了空间没有初始化

EXPORT:声明一个标号具有全局属性,类似于C中的extem功能

IMPORT:表示该标号来自外部文件,跟C语言中的extern关键字类似。

IF、ELSE:和C语言的if、else一样


                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

如果DEF:__MICROLIB成立就把__heap_limit、__heap_base、__initial_sp声明为全局文件

如果没定义会执行__user_initial_stackheap PROC这段代码来初始化(我们都是会定义DEF:__MICROLIB这个的所以不会跑去执行下面这段代码区执行)

  • 12
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
查看文章 STM32 keil mdk启动代码发分析_转2010年01月29日 星期五 13:50 ;// Stack Configuration ;// Stack Size (in Bytes) ;// Stack_Size EQU 0x00000200 ;//定义堆栈大小 AREA STACK, NOINIT, READWRITE, ALIGN=3 ;//定义一个数据段 按8字节对齐 ;AREA 伪指令用于定义一个代码段或数据段 NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0 Stack_Mem SPACE Stack_Size ;//保留Stack_Size大小的堆栈空间 分 配连续 Stack_Size 字节的存储单元并初始化为 0 __initial_sp ;//标号,代表堆栈顶部地址,后面有用 ;// Heap Configuration ;// Heap Size (in Bytes) ;// Heap_Size EQU 0x00000020 ;//定义堆空间大小 AREA HEAP, NOINIT, READWRITE, ALIGN=3 ;//定义一个数据段,8字节对齐 __heap_base Heap_Mem SPACE Heap_Size ;//保留Heap_Size的堆空间 __heap_limit ;//标号,代表堆末尾地址,后面有用 PRESERVE8 ;//指示编译器8字节对齐 THUMB ;//指示编译器为THUMB指令 ; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY ;//定义只读数据段,其实放在CODE区,位于0地址 EXTERN NMIException EXTERN HardFaultException EXTERN MemManageException EXTERN BusFaultException EXTERN UsageFaultException EXTERN SVCHandler EXTERN DebugMonitor EXTERN PendSVC EXTERN SysTickHandler ;//声明这些符号在外部定义,同C ;//在××it.c中实现这些函数 ,中断就能自动调用了 EXPORT __Vectors EXPORT __initial_sp ;EXPORT:在程序中声明一个全局的标号__Vectors,该标号可在其他的文件中引用;I

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值