打印
[牛人杂谈]

详解startup_M051.s

[复制链接]
891|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

在Keil新建的所有工程中,毫无例外地都包含startup_M051.s,如图19.1-1。


图19.1-1 startup_M051.s


该文件主要作用于上电时初始化单片机的硬件堆栈、初始化RAM、分配内存空间和跳转到主函数即main函数。硬件堆栈是用来存放函数调用地址、变量和寄存器值的;分配内存空间为异常提供更加快速的访问,减少中断延迟。如果不加载该startup_M051.s文件,编译的代码可能会使单片机不能正常工作。

那么什么是堆栈呢?在计算机领域,堆栈是一个不容忽视的概念,但是很多人甚至是计算机专业的人也没有明确堆栈这两种数据结构。堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除。

堆,一般是在堆的头部用一个字节存放堆的大小,堆中的具体内容由程序员安排。

栈,在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,接着是函数中的局部变量,注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址(后进先出),也就是主函数中的下一条指令,程序由该点继续运行。

虽然堆栈的说法是连起来叫,但是他们还是有很大区别的,连着叫只是由于历史的原因。

startup_M051.s文件并不复杂,只要用户有基本的汇编基础,就可以看懂,以下就给出该上电初始化文件的详细注解,可以作为参考,只作为选学内容。


沙发
天灵灵地灵灵|  楼主 | 2017-7-20 16:53 | 只看该作者
startup_M051.s核心内容详解

Stack_Size      EQU     0x00000400        ;//栈大小定义为0x00000400字节
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;声明数据段STACK
;该数据段内存单元无初始化,可读写,并重新字对齐
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size       ;//为栈分配内存空间,并初始化为0
__initial_sp


Heap_Size       EQU     0x00000000  ;//堆大小定义为0x00000000字节

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size        ;//为堆分配内存空间,并初始化为0
__heap_limit

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;声明数据段RESET
;该数据段内存单元只读
;功能:为所有Handler分配内存单元
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                PRESERVE8                ;//当前堆栈保持8字节对齐
                THUMB                    ;//THUMB模式
;//向量表映射到复位地址0
                AREA    RESET, DATA, READONLY
                EXPORT  __Vectors

__Vectors       DCD     __initial_sp              ; Top of Stack
                DCD     Reset_Handler             ; Reset Handler
                DCD     NMI_Handler               ; NMI Handler
                DCD     HardFault_Handler         ; Hard Fault Handler
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     SVC_Handler               ; SVCall Handler
                DCD     0                         ; Reserved
                DCD     0                         ; Reserved
                DCD     PendSV_Handler            ; PendSV Handler
                DCD     SysTick_Handler           ; SysTick Handler

                DCD     BOD_IRQHandler  
                DCD     WDT_IRQHandler  
                DCD     EINT0_IRQHandler
                DCD     EINT1_IRQHandler
                DCD     GPAB_IRQHandler
                DCD     GPCDE_IRQHandler
                DCD     PWMA_IRQHandler
                DCD     PWMB_IRQHandler
                DCD     TMR0_IRQHandler
                DCD     TMR1_IRQHandler
                DCD     TMR2_IRQHandler
                DCD     TMR3_IRQHandler
                DCD     UART0_IRQHandler
                DCD     UART1_IRQHandler
                DCD     SPI0_IRQHandler
                DCD     SPI1_IRQHandler
                DCD     SPI2_IRQHandler
                DCD     SPI3_IRQHandler
                DCD     I2C0_IRQHandler
                DCD     I2C1_IRQHandler
                DCD     CAN0_IRQHandler
                DCD     CAN1_IRQHandler
                DCD     Default_Handler
                DCD     USBD_IRQHandler  
                DCD     PS2_IRQHandler  
                DCD     ACMP_IRQHandler
                DCD     PDMA_IRQHandler
                DCD     Default_Handler
                DCD     PWRWU_IRQHandler
                DCD     ADC_IRQHandler
                DCD     Default_Handler  
                DCD     RTC_IRQHandler  

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;声明代码段|.text|,只读
;功能:复位时,代码从该代码段首先执行
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;               
                AREA    |.text|, CODE, READONLY

                ENTRY                             ;//进入代码段

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main                  ;//引入C文件中的main函数

                LDR     R0, =__main            ;//获取C文件中的main函数地址
                BX      R0                       ;//跳转到main函数
                ENDP


NMI_Handler     PROC
                EXPORT  NMI_Handler               [WEAK]
                B       .               ;//停止
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler         [WEAK]
                B       .                           ;//停止
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_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  BOD_IRQHandler            [WEAK]
                EXPORT  WDT_IRQHandler            [WEAK]
                EXPORT  EINT0_IRQHandler          [WEAK]
                EXPORT  EINT1_IRQHandler          [WEAK]
                EXPORT  GPAB_IRQHandler           [WEAK]
                EXPORT  GPCDE_IRQHandler          [WEAK]
                EXPORT  PWMA_IRQHandler           [WEAK]
                EXPORT  PWMB_IRQHandler           [WEAK]
                EXPORT  TMR0_IRQHandler           [WEAK]
                EXPORT  TMR1_IRQHandler           [WEAK]
                EXPORT  TMR2_IRQHandler           [WEAK]
                EXPORT  TMR3_IRQHandler           [WEAK]
                EXPORT  UART0_IRQHandler          [WEAK]
                EXPORT  UART1_IRQHandler          [WEAK]
                EXPORT  SPI0_IRQHandler           [WEAK]
                EXPORT  SPI1_IRQHandler           [WEAK]
                EXPORT  SPI2_IRQHandler           [WEAK]
                EXPORT  SPI3_IRQHandler           [WEAK]
                EXPORT  I2C0_IRQHandler           [WEAK]
                EXPORT  I2C1_IRQHandler           [WEAK]
                EXPORT  CAN0_IRQHandler           [WEAK]
                EXPORT  CAN1_IRQHandler           [WEAK]
                EXPORT  USBD_IRQHandler           [WEAK]
                EXPORT  PS2_IRQHandler            [WEAK]
                EXPORT  ACMP_IRQHandler           [WEAK]
                EXPORT  PDMA_IRQHandler           [WEAK]
                EXPORT  PWRWU_IRQHandler          [WEAK]
                EXPORT  ADC_IRQHandler            [WEAK]
                EXPORT  RTC_IRQHandler            [WEAK]

BOD_IRQHandler
WDT_IRQHandler
EINT0_IRQHandler
EINT1_IRQHandler
GPAB_IRQHandler
GPCDE_IRQHandler
PWMA_IRQHandler
PWMB_IRQHandler
TMR0_IRQHandler
TMR1_IRQHandler
TMR2_IRQHandler
TMR3_IRQHandler
UART0_IRQHandler
UART1_IRQHandler
SPI0_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
SPI3_IRQHandler
I2C0_IRQHandler
I2C1_IRQHandler
CAN0_IRQHandler
CAN1_IRQHandler
USBD_IRQHandler
PS2_IRQHandler
ACMP_IRQHandler
PDMA_IRQHandler
PWRWU_IRQHandler
ADC_IRQHandler
RTC_IRQHandler
                B       .                        ;//停止
                ENDP

                ALIGN                            ;//添加补丁字节满足一定的对齐方式


; //用户初始化的堆栈

                IF      :DEF:__MICROLIB          ;//检查是否定义了__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


使用特权

评论回复
板凳
天灵灵地灵灵|  楼主 | 2017-7-20 16:53 | 只看该作者
深入重点:

ü 什么是堆栈?

ü startup_M051.s上电时初始化单片机的硬件堆栈、初始化RAM、分配内存空间和跳转到主函数即main函数。

ü 使用IMPORT或EXPORT声明外部符号时,若链接器在连接微控制器时不能解释该符号,而伪指令中没有[WEAK]选项时,则链接器会报告错误,若伪指令中有[WEAK]选项时,则链接器不会报告错误,而是进行下面的操作:

          1:如果该符号被B或者BL指令引用,则该符号被设置成下一条指令的地址,该B或者  BL指令相当于一条NOP指令。

          2:其他情况下该符号被设置为0

使用特权

评论回复
地板
yiyigirl2014| | 2017-7-20 20:23 | 只看该作者
TMR3_IRQHandler好多的中断处理函数入口就这里了。

使用特权

评论回复
5
wahahaheihei| | 2017-7-20 21:11 | 只看该作者
硬件堆栈是用来存放函数调用地址、变量和寄存器值的

使用特权

评论回复
6
643757107| | 2017-7-23 11:50 | 只看该作者
高手中的高手才去修改这个,默认就行了,别乱动。

使用特权

评论回复
7
zhuotuzi| | 2017-7-29 22:20 | 只看该作者
么有仔细想过,看看。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

161

主题

3304

帖子

13

粉丝