• 【HC32L110】华大低功耗单片机启动文件详解


    本文主要记录华大低功耗单片机 HC32L110 的 汇编启动过程,包括startup_hc32l110启动文件详细注释

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://blog.csdn.net/qq_39217004/article/details/137968603

    0. 常用汇编指令

    在这里插入图片描述
    在这里插入图片描述

    1.启动文件的作用

    启动文件为 startup_hc32l110.s,启动文件中完成了:

    • 堆和栈的初始化

      • 包括堆栈的大小,主栈指针 MSP 的初始值
    • 向量表定义

      • 定义各MSP的初值以及中断服务函数的入口地址
    • 中断服务程序

    • 设置系统时钟频率 (在复位中断服务程序Reset_handler中调用系统时钟频率初始化程序)

    • 中断寄存器初始化

    • 进入C的main函数

    2.堆栈定义

    2.1栈

    栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM 的大小。当程序较大时,需要修改栈的大小,不然可能会出现的HardFault的错误。

    • EQU是伪指令,相当于C 中的 define
    • ARER 伪指令表示下面将开始定义一个代码段或者数据段
    • ARER 后面的关键字表示这个段的属性。段名为STACK,可以任意命名;NOINIT 表示不初始化;READWRITE 表示可读可写,ALIGN=3,表示按照 8 字节对齐。
    • SPACE 用于分配大小等于 Stack_Size连续内存空间,单位为字节。
    • __initial_sp表示栈顶地址。栈是由高向低生长的
    ; Stack Configuration
    ; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
    
    Stack_Size      EQU     0x00000100
    
                    AREA    STACK, NOINIT, READWRITE, ALIGN=3   
    Stack_Mem       SPACE   Stack_Size
    __initial_sp
    
    ; 定义栈大小为  0x100     256字节
    ; 定义一个数据段,8字节对齐,名称为 STACK ,数据段不初始化,仅仅保留内存单元,可读可写
    ; 分配一段大小为 Stack_Size 的连续内存空间,并初始化为0
    ; 表示栈顶指针地址
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.2堆

    堆主要用来动态内存的分配,像 malloc()函数申请的内存就在堆中。

    ; Heap Configuration
    ;  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
    
    Heap_Size       EQU     0x00000400
    
                    AREA    HEAP, NOINIT, READWRITE, ALIGN=3
    __heap_base
    Heap_Mem        SPACE   Heap_Size
    __heap_limit
    
    ; 定义堆大小为  0x400     1024字节
    ; 定义一个数据段,8字节对齐,名称为 HEAP ,数据段不初始化,仅仅保留内存单元,可读可写
    ; __heap_base放置在SPACE之前表示堆的起始地址。
    ; 分配一段大小为 Heap_Size 的连续内存空间,并初始化为0
    ; __heap_limit放置在SPACE之后表示堆的结束地址。
    
    
                    PRESERVE8   ; 指示编译器8字节对齐
                    THUMB       ; 指示编译器以后的指令为THUMB指令
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.向量表

    向量表本质上是一个U32的数组,每个元素代表一种异常,中断向量表 存放的实际上是中断服务程序的入口地址。当异常(也即是中断事件)发生时,CPU 的中断系统会将相应的入口地址赋值给 PC 程序计数器,之后就开始执行中断服务程序。 在地址 0 (即 FLASH 地址 0)处必须包含一张向量表,用于初始时的异常分配。

    • EXPORT将标识符申明为可被外部引用
    • DCD 表示分配 1 个 4 字节的空间
    ; Vector Table Mapped to Address 0 at Reset
    ;中断向量表定义
                    AREA    RESET, DATA, READONLY     ;定义只读数据段,名字是REST
    
                                                      ;EXPORT:在程序中声明一个全局的标号__Vectors,
                                                      ;该标号可在其他的文件中引用
    
                    EXPORT  __Vectors                 ;表示向量表的起始地址
                    EXPORT  __Vectors_End             ;表示向量表的结束地址
                    EXPORT  __Vectors_Size            ;表示向量表的大小
    
    
    ; 中断向量表
    __Vectors       DCD     __initial_sp              ; Top of Stack
                    DCD     Reset_Handler             ; Reset
                    DCD     NMI_Handler               ; NMI
                    DCD     HardFault_Handler         ; Hard Fault
                    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
                    DCD     0                         ; Reserved
                    DCD     0                         ; Reserved
                    DCD     PendSV_Handler            ; PendSV
                    DCD     SysTick_Handler           ; SysTick
                    ………………省略一部分
                    
                    __Vectors_End
    
    __Vectors_Size 	EQU     __Vectors_End - __Vectors
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    4.复位程序

    复位程序是系统上电后执行的第一个程序

    ; Reset Handler
                                                            ;利用PROC、ENDP这一对伪指令把程序段分为若干过程
                                                            ;使得程序结构明晰
    Reset_Handler   PROC                                    ;过程开始
                    EXPORT  Reset_Handler             [WEAK] ;weak 符号表示 该函数可以在外部重写
                    IMPORT  SystemInit                       ; IMPORT表示函数是从外部带入的,代码中的系统初始化程序
                    IMPORT  __main
    
                   ;reset NVIC if in rom debug
                    LDR     R0, =0x20000000        ; 将ram 地址写入R0寄存器
                    LDR     R2, =0x0			   ;将 flash 0地址写入R2寄存器
                    MOVS    R1, #0                 ; for warning,  将立即数0 写入R1寄存器
                    ADD     R1, PC,#0              ; for A1609W,   将PC初值+0 写入R1寄存器
                    CMP     R1, R0				   ; 比较RAM首地址与 flash 首地址的值 
                    BLS     RAMCODE                ; 若满足小于等于,则跳转
    
                  ; ram code base address. 
                    ADD     R2, R0,R2
    RAMCODE
                  ; reset Vector table address.
                    LDR     R0, =0xE000ED08       ; ?????????????
                    STR     R2, [R0]
    
                    LDR     R0, =SystemInit         ;执行初始化,
                    BLX     R0
                    LDR     R0, =__main             ;__main是C库函数 想要使用__main这个C库函数 必须勾选微库选项
                    BX      R0
                    ENDP
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    5.中断服务程序

    我们平时要使用哪个中断,就需要编写相应的中断服务程序,只是启动文件把这些函数留出来了,但是内容都是空的,真正的中断复服务程序需要我们在外部的 C 文件里面重新实现,这里只是提前占了一个位置罢了。

    B . 表示无线循环,类似于while(1)

    6.堆栈初始化

    堆栈初始化是由一个IF条件来实现的,MICROLIB的定义与否决定了堆栈的初始化方式。如果没有定义__MICROLIB , 则会使用双段存储器模式,

    且声明了__user_initial_stackheap 具有全局属性,这需要开发者自己来初始化堆栈。

    ; User Initial Stack & Heap                      ;堆和栈的初始化
    
                    IF      :DEF:__MICROLIB          ;如果定义了MICORLIB,使用微库
    
                    EXPORT  __initial_sp            ; 赋予【栈顶地址】【堆起始地址】【堆结束地址】全局的属性
                    EXPORT  __heap_base             ; 可在外部使用
                    EXPORT  __heap_limit
    
                    ELSE      
                                                    ;如果使用默认的C库
                    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    7. 启动过程详解

    7.1从0地址开始

    ARM 内核单片机的启动方式都是如下图流程:

    image-20240419151911263

    通过以上分析可知,flash 的0 地址存储这中断向量表。

    • 单片机从 flash 的 0 地址取出数据赋给MSP指针,然后从 0+ 4 地址处取出值赋值给PC
    • 此时 SP = 栈顶地址 PC = Reset_Handler,程序从复位开始执行

    image-20240419152505491

    7.2在Reset_Handler中干了啥?

    • Reset_Handler仅仅执行了两个函数调用,一个是SystemInit,另一个__main,
    • SystemInit定义在system_hc32xxxx.c中,主要初始化了系统时钟系统:RCH,RCL,XTH,XTL,PLL,SystemClk,HCLK,PCLK等等.
    • __main函数由编译器生成,负责初始化栈、堆等,并在最后跳转到用户自定义的main()函数,来到C的世界

    8.启动过程总结

    • ;先在RAM中分配系统使用的栈,RAM的起始地址为0x2000_0000
    • ;然后在RAM中分配变量使用的堆
    • ;然后在CODE区(flash)分配中断向量表,flash的起始地址为0x0000_0000,该中断向量表就从这个起始地址开始分配
    • ;分配完成后,再定义和实现相应的中断函数,
    • ;所有的中断函数全部带有[weak]特性,即弱定义,如果编译器发现在别处文件中定义了同名函数,在链接时用别处的地址进行链接。
    • ;中断函数仅仅实现了Reset_Handler,其他要么是死循环,要么仅仅定义了函数名称
    • ;HC32被设置为从内部FLASH启动时(这也是最常见的一种情况),当HC32遇到复位信号后,
    • ;从0x0000_0000处取出栈顶地址存放于MSP寄存器,从0x0000_0004处取出复位中断服务入口地址放入PC寄存器,
    • ;继而执行复位中断服务程序Reset_Handler
    • ;Reset_Handler仅仅执行了两个函数调用,一个是SystemInit,另一个__main,
    • ;SystemInit定义在system_hc32xxxx.c中,主要初始化了HC的时钟系统:RCH,RCL,XTH,XTL,PLL,SystemClk,HCLK,PCLK等等.
    • ;__main函数由编译器生成,负责初始化栈、堆等,并在最后跳转到用户自定义的main()函数,来到C的世界

    9. startup.s 文件注释

    ;/******************************************************************************
    ;* Copyright (C) 2017, Xiaohua Semiconductor Co.,Ltd All rights reserved.
    ;*
    ;* This software is owned and published by:
    ;* Xiaohua Semiconductor Co.,Ltd ("XHSC").
    ;*
    ;* BY DOWNLOADING, INSTALLING OR USING THIS SOFTWARE, YOU AGREE TO BE BOUND
    ;* BY ALL THE TERMS AND CONDITIONS OF THIS AGREEMENT.
    ;*
    ;* This software contains source code for use with XHSC
    ;* components. This software is licensed by XHSC to be adapted only
    ;* for use in systems utilizing XHSC components. XHSC shall not be
    ;* responsible for misuse or illegal use of this software for devices not
    ;* supported herein. XHSC is providing this software "AS IS" and will
    ;* not be responsible for issues arising from incorrect user implementation
    ;* of the software.
    ;*
    ;* Disclaimer:
    ;* XHSC MAKES NO WARRANTY, EXPRESS OR IMPLIED, ARISING BY LAW OR OTHERWISE,
    ;* REGARDING THE SOFTWARE (INCLUDING ANY ACOOMPANYING WRITTEN MATERIALS),
    ;* ITS PERFORMANCE OR SUITABILITY FOR YOUR INTENDED USE, INCLUDING,
    ;* WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, THE IMPLIED
    ;* WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE OR USE, AND THE IMPLIED
    ;* WARRANTY OF NONINFRINGEMENT.
    ;* XHSC SHALL HAVE NO LIABILITY (WHETHER IN CONTRACT, WARRANTY, TORT,
    ;* NEGLIGENCE OR OTHERWISE) FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT
    ;* LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
    ;* LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING FROM USE OR
    ;* INABILITY TO USE THE SOFTWARE, INCLUDING, WITHOUT LIMITATION, ANY DIRECT,
    ;* INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOSS OF DATA,
    ;* SAVINGS OR PROFITS,
    ;* EVEN IF Disclaimer HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
    ;* YOU ASSUME ALL RESPONSIBILITIES FOR SELECTION OF THE SOFTWARE TO ACHIEVE YOUR
    ;* INTENDED RESULTS, AND FOR THE INSTALLATION OF, USE OF, AND RESULTS OBTAINED
    ;* FROM, THE SOFTWARE.
    ;*
    ;* This software may be replicated in part or whole for the licensed use,
    ;* with the restriction that this Disclaimer and Copyright notice must be
    ;* included with each copy of this software, whether used in part or whole,
    ;* at all times.
    ;*/
    ;/*****************************************************************************/
    
    ;/*****************************************************************************/
    ;/*  Startup for ARM                                                          */
    ;/*  Version     V1.2                                                         */
    ;/*  Date        2016-06-02                                                   */
    ;/*  Target-mcu  {MCU_SERIES}                                                 */
    ;/*****************************************************************************/
    
    ; Stack Configuration
    ; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
    
    Stack_Size      EQU     0x00000100
    
                    AREA    STACK, NOINIT, READWRITE, ALIGN=3   
    Stack_Mem       SPACE   Stack_Size
    __initial_sp
    
    ; 定义栈大小为  0x100     256字节
    ; 定义一个数据段,8字节对齐,名称为 STACK ,数据段不初始化,仅仅保留内存单元,可读可写
    ; 分配一段大小为 Stack_Size 的连续内存空间,并初始化为0
    ; 表示栈顶指针地址
    
    
    ; Heap Configuration
    ;  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
    
    Heap_Size       EQU     0x00000400
    
                    AREA    HEAP, NOINIT, READWRITE, ALIGN=3
    __heap_base
    Heap_Mem        SPACE   Heap_Size
    __heap_limit
    
    ; 定义堆大小为  0x400     1024字节
    ; 定义一个数据段,8字节对齐,名称为 HEAP ,数据段不初始化,仅仅保留内存单元,可读可写
    ; __heap_base放置在SPACE之前表示堆的起始地址。
    ; 分配一段大小为 Heap_Size 的连续内存空间,并初始化为0
    ; __heap_limit放置在SPACE之后表示堆的结束地址。
    
    
                    PRESERVE8   ; 指示编译器8字节对齐
                    THUMB       ; 指示编译器以后的指令为THUMB指令
    
    
    ; Vector Table Mapped to Address 0 at Reset
    ;中断向量表定义
                    AREA    RESET, DATA, READONLY     ;定义只读数据段,名字是REST
    
                                                      ;EXPORT:在程序中声明一个全局的标号__Vectors,
                                                      ;该标号可在其他的文件中引用
    
                    EXPORT  __Vectors                 ;表示向量表的起始地址
                    EXPORT  __Vectors_End             ;表示向量表的结束地址
                    EXPORT  __Vectors_Size            ;表示向量表的大小
    
    ; 中断向量表
    __Vectors       DCD     __initial_sp              ; Top of Stack
                    DCD     Reset_Handler             ; Reset
                    DCD     NMI_Handler               ; NMI
                    DCD     HardFault_Handler         ; Hard Fault
                    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
                    DCD     0                         ; Reserved
                    DCD     0                         ; Reserved
                    DCD     PendSV_Handler            ; PendSV
                    DCD     SysTick_Handler           ; SysTick
    
                    DCD     IRQ000_Handler            ; 
                    DCD     IRQ001_Handler            ; 
                    DCD     IRQ002_Handler            ; 
                    DCD     IRQ003_Handler            ; 
                    DCD     IRQ004_Handler            ; 
                    DCD     IRQ005_Handler            ; 
                    DCD     IRQ006_Handler            ; 
                    DCD     IRQ007_Handler            ; 
                    DCD     IRQ008_Handler            ; 
                    DCD     IRQ009_Handler            ; 
                    DCD     IRQ010_Handler            ; 
                    DCD     IRQ011_Handler            ; 
                    DCD     IRQ012_Handler            ; 
                    DCD     IRQ013_Handler            ; 
                    DCD     IRQ014_Handler            ; 
                    DCD     IRQ015_Handler            ; 
                    DCD     IRQ016_Handler            ; 
                    DCD     IRQ017_Handler            ; 
                    DCD     IRQ018_Handler            ; 
                    DCD     IRQ019_Handler            ; 
                    DCD     IRQ020_Handler            ; 
                    DCD     IRQ021_Handler            ; 
                    DCD     IRQ022_Handler            ; 
                    DCD     IRQ023_Handler            ; 
                    DCD     IRQ024_Handler            ; 
                    DCD     IRQ025_Handler            ; 
                    DCD     IRQ026_Handler            ; 
                    DCD     IRQ027_Handler            ; 
                    DCD     IRQ028_Handler            ; 
                    DCD     IRQ029_Handler            ; 
                    DCD     IRQ030_Handler            ; 
                    DCD     IRQ031_Handler            ; 
    
    __Vectors_End
    
    __Vectors_Size 	EQU     __Vectors_End - __Vectors
    
    
    
                    AREA    |.text|, CODE, READONLY         ;代码段定义,只读
    
    
    ; Reset Handler
                                                            ;利用PROC、ENDP这一对伪指令把程序段分为若干过程
                                                            ;使得程序结构明晰
    Reset_Handler   PROC                                    ;过程开始
                    EXPORT  Reset_Handler             [WEAK] ;weak 符号表示 该函数可以在外部重写
                    IMPORT  SystemInit                       ; IMPORT表示函数是从外部带入的,代码中的系统初始化程序
                    IMPORT  __main
    
                   ;reset NVIC if in rom debug
                    LDR     R0, =0x20000000
                    LDR     R2, =0x0
                    MOVS    R1, #0                 ; for warning, 
                    ADD     R1, PC,#0              ; for A1609W, 
                    CMP     R1, R0
                    BLS     RAMCODE
    
                  ; ram code base address. 
                    ADD     R2, R0,R2
    RAMCODE
                  ; reset Vector table address.
                    LDR     R0, =0xE000ED08 
                    STR     R2, [R0]
    
                    LDR     R0, =SystemInit
                    BLX     R0
                    LDR     R0, =__main             ;__main是C库函数 想要使用__main这个C库函数 必须勾选微库选项
                    BX      R0
                    ENDP
    
    
    ; Dummy Exception Handlers (infinite loops which can be modified)
    
    ; B       .  表示原地跳转(即无限循环),等同于while(1);
    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  IRQ000_Handler               [WEAK]
                    EXPORT  IRQ001_Handler               [WEAK]
                    EXPORT  IRQ002_Handler               [WEAK]
                    EXPORT  IRQ003_Handler               [WEAK]
                    EXPORT  IRQ004_Handler               [WEAK]
                    EXPORT  IRQ005_Handler               [WEAK]
                    EXPORT  IRQ006_Handler               [WEAK]
                    EXPORT  IRQ007_Handler               [WEAK]
                    EXPORT  IRQ008_Handler               [WEAK]
                    EXPORT  IRQ009_Handler               [WEAK]
                    EXPORT  IRQ010_Handler               [WEAK]
                    EXPORT  IRQ011_Handler               [WEAK]
                    EXPORT  IRQ012_Handler               [WEAK]
                    EXPORT  IRQ013_Handler               [WEAK]
                    EXPORT  IRQ014_Handler               [WEAK]
                    EXPORT  IRQ015_Handler               [WEAK]
                    EXPORT  IRQ016_Handler               [WEAK]
                    EXPORT  IRQ017_Handler               [WEAK]
                    EXPORT  IRQ018_Handler               [WEAK]
                    EXPORT  IRQ019_Handler               [WEAK]
                    EXPORT  IRQ020_Handler               [WEAK]
                    EXPORT  IRQ021_Handler               [WEAK]
                    EXPORT  IRQ022_Handler               [WEAK]
                    EXPORT  IRQ023_Handler               [WEAK]
                    EXPORT  IRQ024_Handler               [WEAK]
                    EXPORT  IRQ025_Handler               [WEAK]
                    EXPORT  IRQ026_Handler               [WEAK]
                    EXPORT  IRQ027_Handler               [WEAK]
                    EXPORT  IRQ028_Handler               [WEAK]
                    EXPORT  IRQ029_Handler               [WEAK]
                    EXPORT  IRQ030_Handler               [WEAK]
                    EXPORT  IRQ031_Handler               [WEAK]
    
    
    IRQ000_Handler
    IRQ001_Handler
    IRQ002_Handler
    IRQ003_Handler
    IRQ004_Handler
    IRQ005_Handler
    IRQ006_Handler
    IRQ007_Handler
    IRQ008_Handler
    IRQ009_Handler
    IRQ010_Handler
    IRQ011_Handler
    IRQ012_Handler
    IRQ013_Handler
    IRQ014_Handler
    IRQ015_Handler
    IRQ016_Handler
    IRQ017_Handler
    IRQ018_Handler
    IRQ019_Handler
    IRQ020_Handler
    IRQ021_Handler
    IRQ022_Handler
    IRQ023_Handler
    IRQ024_Handler
    IRQ025_Handler
    IRQ026_Handler
    IRQ027_Handler
    IRQ028_Handler
    IRQ029_Handler
    IRQ030_Handler
    IRQ031_Handler
                   B .
    
                    ENDP
    
    
                    ALIGN             ;填充字节使地址对齐
    
    
    
    
    ; User Initial Stack & Heap                      ;堆和栈的初始化
    
                    IF      :DEF:__MICROLIB          ;如果定义了MICORLIB,使用微库
    
                    EXPORT  __initial_sp            ; 赋予【栈顶地址】【堆起始地址】【堆结束地址】全局的属性
                    EXPORT  __heap_base             ; 可在外部使用
                    EXPORT  __heap_limit
    
                    ELSE      
                                                    ;如果使用默认的C库
                    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
  • 相关阅读:
    第3章 【MySQL】字符集和比较规则
    力扣刷题第二十五天--二叉树
    软件测试面试-如何定位线上出现bug
    C/C++编程新手容易犯的10种编程错误
    【linux编程】linux文件IO的标准函数及其示例(fread,fwrite,fgetc,fputc,fgets,fputs,fprintf,fscanf)
    智能物联时代下RFID技术在汽车零部件智能制造中的引领作用
    AI赋能写作:探索设计模式的魅力
    速溶颗粒:实验中的好伙伴
    【马蹄集】第二十四周——高精度计算专题
    "嫦娥奔月",难道古人早已看透一切?
  • 原文地址:https://blog.csdn.net/qq_39217004/article/details/137968603