STM32开始第一步

启动文件讲解

(1)启动文件简介

  • 初始化堆栈指针SP=_initial_sp
  • 初始化PC 指针=Reset_Handler
  • 初始化中断向量表
  • 配置系统时钟
  • 调用C 库函数_main 初始化用户堆栈,从而最终调用main 函数去到C的世界

(2)查找ARM汇编指令

  • 查找位置STM32开始第一步_第1张图片
  • 启动文件所用到的汇编指令
    STM32开始第一步_第2张图片
    • EQU: 格式name EQU expr{, type}
    例如:
    abc EQU 2     
    xyz EQU label+8         
    fiq EQU 0x1C, CODE32
    (type的种类ARM,THUMB,CODE32,CODE16,DATA)
    
    • AREA:格式 AREA sectionname{,attr}{,attr}…
      例如:    AREA    Example(名称),CODE(表示CODE类型),READONLY(表示只读)
      
    • ARM汇编中的注释:“;”

(3)启动文件代码讲解

【1】Stack—栈

Stack_Size EQU 0x00000400 //定义栈的大小为1024

AREA STACK, NOINIT (不初始化), READWRITE(可读可写), ALIGN=3(8字节对齐)

Stack_Mem SPACE Stack_Size //给Stack_Mem分配大小为SPACE Stack_Size的储存
__initial_sp //表示栈的结束地址,即栈顶地址

注意栈的大小可以修改,有的时候发现溢出错误时可能是栈的大小不够,但即使修改栈的大小也要保证比SRAM小
【2】Heap 堆

 Heap_Size EQU 0x00000200(512字节)
 AREA HEAP, NOINIT, READWRITE,ALIGN=3
__heap_base  //表示堆的起始地址
Heap_Mem SPACE Heap_Size
 __heap_limit //表示堆的结束

PRESERVE8 //当前堆按照8字节对齐
THUMB    //表示兼容AMR的以前的指令集

堆是由低向高生长的,跟栈的生长方向相反。

【3】向量表

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

EXPORT:声明一个变量有全局属性

1 __Vectors DCD __initial_sp //栈顶地址
2 DCD Reset_Handler //复位程序地址
3 DCD NMI_Handler
4 DCD HardFault_Handler
5 DCD MemManage_Handler
6 DCD BusFault_Handler
7 DCD UsageFault_Handler
8 DCD 0 ; 0 表示保留
9 DCD 0
10 DCD 0
11 DCD 0
12 DCD SVC_Handler
13 DCD DebugMon_Handler
14 DCD 0
15 DCD PendSV_Handler
16 DCD SysTick_Handler
17
18
19 //外部中断开始
20 DCD WWDG_IRQHandler
21 DCD PVD_IRQHandler
22 DCD TAMP_STAMP_IRQHandler
23
24 //限于篇幅,中间代码省略
25 DCD LTDC_IRQHandler
26 DCD LTDC_ER_IRQHandler
27 DCD DMA2D_IRQHandler
28 __Vectors_End //表示向量表的结束
__Vectors_Size EQU __Vectors_End - __Vectors //表示向量表的大小

DCD:以四个字节为一个单位进行内存的分配。

从__initial_sp开始每4个字节分配给一个中断函数的地址
【4】复位程序

 AREA |.text|, CODE, READONLY 
 Reset_Handler PROC //PROC 表示一个函数的开始
 EXPORT Reset_Handler [WEAK]
 IMPORT SystemInit //声明外部的函数SystemInit与__main
 IMPORT __main
//以下是赋地址与跳转到对应地址
 LDR R0, =SystemInit
 BLX R0
 LDR R0, =__main
 BX R0
 ENDP //PROC 表示一个函数的结束

这里可以通过修改__main名,来改变所要进入的主函数名称

【5】中断服务程序


 ;限于篇幅,中间代码省略
 SysTick_Handler PROC
 EXPORT SysTick_Handler [WEAK]
 B .
 ENDP


 EXPORT WWDG_IRQHandler [WEAK]

 
 ;限于篇幅,中间代码省略
 LTDC_IRQHandler

 B .//B:跳转到一个标号。这里跳转到一个‘.’,即表示无限循环。
 ENDP

流程大概是,当一个中断触发时,就定义出一个中断句柄例如WWDG_IRQHandler,并声明成个弱函数,让用户可以自行修改,但如果用户没有从新编写这个中断函数,则程序就会跳转到之前写好的中断函数中,例如SysTick_Handler,从而导致无限循环。

【6】用户堆栈初始化


 IF :DEF:__MICROLIB //相当于indef,一般是没有定义的

 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

你可能感兴趣的:(STM32,Learning,stm32)