咱们写嵌入式程序,根本上选用C言语来编写,以main( )作为程序的进口。但实际上,mian()并不是最先要履行的,在这之前需求做一些根本的作业,如堆、栈的界说;main函数的复位衔接等,这些作业就需求一个专门的发动程序来完结,因为需求做的作业内容不多,而且需求更直接的办理内存,一般选用汇编编写。
无论是STM32、ARM系列的单片机,仍是简略的如51,PIC等,都认为上述原因,需求发动程序,只不过51,PIC等单片机的发动程序已经在相应的IDE编译、链接的时分隐含的编译了,故在写单片机程序的时分无需考虑。而STM32的发动有相应的发动文件,本文将选用KEIL MDK自带的发动文件STM32F10x.s进行剖析。
1 发动形式的挑选
STM32芯片自带的发动方法有3种如下表
发动形式挑选引脚 |
发动形式 |
阐明 |
|
BOOT1 |
BOOT0 |
||
X |
0 |
主闪存存储器 |
主闪存存储器作为发动区域 |
0 |
1 |
体系存储器 |
体系存储器作为发动区域 |
1 |
1 |
内置SRAM |
内置SRAM作为发动葡萄 |
STM32的发动挑选,经过设置BOOT1、BOOT0的引脚的凹凸电平即可挑选。其间主闪存发动是将程序下载到内置的Flash进行发动(该flash可运转程序),该程序可以掉电保存,下次开机可主动发动;体系存储器发动是将程序写入到一快特定的区域,一般由厂家直接写入,不能被随意更改或擦除。内置SRAM发动,因为SRAM掉电丢掉,不能保存程序,一般只用于程序的调试。
就程序的发动而言,选用以上3种方法发动,但关于一个嵌入式体系的程序来说,假如程序履行文件很大,而STM32内置的存储空间有限,就需求外置Nand flash/Nor flash 和SDRAM,即程序存储在flash中,程序履行在SDRAM中,既节省了本钱有提高了运转功率。假如选用外置的Flash+SDRAM的方法,就需求一个愈加杂乱的发动文件(bootloader),需求考虑flash的COPY,Flash的驱动,内存的办理,通讯机制等,本文暂不触及此内容,今后有时机专门叙述。
2 发动文件STM32F10x.s剖析
关于STM32F10x.s的发动文件,首要做了3个作业:分配和初始化堆、栈;界说复位向量并初始化;中止向量表及其相应的反常处理程序。
2.1 界说堆、栈及其初始化
堆和栈是可以运转C言语的条件,如以下程序:
界说栈:
Stack_Size EQU 0x00000200
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
界说堆:
Heap_Size EQU 0x00000000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
初始化堆、栈:
_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
2.2 界说复位向量
Boot引脚的设置不同,复位时,开端地址的方位不同,SRAM的开端地址为0x2000000, flash的开端地址为0x8000000。Cortex-M3内核规则,开端地址有必要寄存堆定指针,而第二个地址有必要寄存复位中止进口向量。在体系复位时,内核会主动从其实地址的下一个地址(即32位)空间取出复位中止进口向量,然后跳转到复位中止服务程序,该服务程序就会跳转到main()履行程序。
中止向量表(部分向量):
__Vectors
DCD __initial_sp ; Top of Stack // 初始化堆跳转
DCD Reset_Handler ; Reset Handler // 复位中止向量跳转
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
复位中止服务程序
; Reset Handler // 该程序会跳转到main()
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
LDR R0, =__main
BX R0
ENDP
3 其他中止向量及服务子程序
在发动文件中,只界说了中止向量,其相应的服务子程序跳转到空操作。为今后扩展中止服务程序做了预备。
在以上这些都成功跑完之后,咱们的微处理器(MCU)就开端main函数之旅……