• 19.1 详解startup_M051.s


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

     

    图19.1-1 startup_M051.s

     

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

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

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

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

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

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

     

    程序清单19.1-1 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

     

     

    深入重点:

    ü 什么是堆栈?

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

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

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

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

    …………………………………………

     

    书籍下载地址(复制到下载工具进行下载):

     

     

     

    https://files.cnblogs.com/wenziqi/ARMCortex-M0原理与应用实践.part1.rar

     

     

     

    https://files.cnblogs.com/wenziqi/ARMCortex-M0原理与应用实践.part2.rar

     

     

     

    注:书籍内容会不定期进行更新!

     

  • 相关阅读:
    bzoj 1176 cdq分治套树状数组
    Codeforces 669E cdq分治
    Codeforces 1101D 点分治
    Codeforces 1100E 拓扑排序
    Codeforces 1188D Make Equal DP
    Codeforces 1188A 构造
    Codeforces 1188B 式子转化
    Codeforces 1188C DP 鸽巢原理
    Codeforces 1179D 树形DP 斜率优化
    git commit -m "XX"报错 pre -commit hook failed (add --no-verify to bypass)问题
  • 原文地址:https://www.cnblogs.com/wenziqi/p/2358294.html
Copyright © 2020-2023  润新知