完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM32 官方为广大开发者提供一套统一开发固件,主要是屏蔽寄存器封装,提供初始化等功能,较少开发者负担。只需要调用相关模块封装,对相关结构提初始化即可,较少开发调试时间。本次主要以官方STM32F4xx_DSP_StdPeriph_Lib_V1.8.0固件版本为主,主要讲解各个模块主要作用以及使用方法,固件主要结构将在后面做介绍
本次主要讲解开发过程中大家都会忽略的STM32 启动文件流程,STM43 启动文件名为startup_stm32f40_41xxx.s,其目录在STM32F4xx_DSP_StdPeriph_Lib_V1.8.0LibrariesCMSISDeviceSTSTM32F4xxSourceTemplatesarm,也可以按照整个文件名搜索整个固件,会发现有很多相同文件分布在不同目录,主要是因为官方固件提供很多开发样例,每个样例都需要进行启动文件,官方提供用例在STM32F4xx_DSP_StdPeriph_Lib_V1.8.0ProjectSTM32F4xx_StdPeriph_Examples中。启动文件时以.s开头,都是用ARM汇编指令集来完成的。具体ARM汇编可以参考《Arm 体系结构与编程》 启动文件工作 1:初始化堆栈空间 2:PC指针 Rest_Handler 3: 初始化中断向量表 4:系统时钟 5:堆栈初始化完成之后,进入main函数 初始化栈空间 初始化文件开头代码 首先是初始化栈空间代码如下: 上述代码的意思是开辟空间为0x00000400(1KB)的栈空间, 主要用于局部遍历,函数调用,参数形参等开销,不能超过芯片内部SRAM。可以根据需要进行调整,防止程序溢出 EQU:为ARM汇编伪指令,相当于C中define,意思为定义Stack_Size 代表0x00000400 AREA: 汇编伪指令,意思是定义伪一个代码端或者数据段,其格式为 AREA sectionname {,attr} {,attr} sectionname为定义的代码或者数据段名字, attr为该字段属性 AREA STACK, NOINIT, READWRITE, ALIGN=3 意思为 定义该数据段名字为STACK,NOINIT指定本数据段仅仅保留了内存单元,而没有将各初始值写入内存单元。 READWRITE为该数据段即可写又可读, ALIGN为字节对齐,为2的3次方等于8,8字节对齐。 SPACE:用于一块内存单元,并用0初始化。申请Stack_Size大小内存。 __initial_sp 紧随SPACE后面,表示申请内存的结束地址,即栈顶位置,栈是由高向低生长,故需要指向栈顶位置 初始化堆空间 紧接着为堆空间地址申请,代码如下 堆空间大小为Heap_Size即0x00000200(512Byte),EQU AREA和SPACE指令上面已经讲到 不再解释。__heap_base在SPACE之前,因为堆空间是向上增长的,__heap_base指向为堆的地址,__heap_limit为堆的结束地址。 PRESERVE8:当前代码中数据段是8字节对齐,因为汇编指令中LDRD和STRD指令要求内存单元地址是8字节对齐的,在程序中使用这些指令在数据栈中传送数据时,要求该数据段是8字节对齐。 THUMB:兼容THUMB指令集。THumb指令集是堆ARM指令集的一个子集进行重新编码得到得,其指令长度为16位。THUMN-2为32位。 中断向量表初始化 接下来将会进入中断向量表: 定义RESET数据段为可读,中断向量表本质上为一张中断函数指针,每个地址记录中断服务程序入口地址,发生中断后,STM32将会进入到相应的中断服务程序,每个地址代表不同的中断,由厂商写死,不可更改,《STM32F4xx中文参考手册》中可知,每个地址代表的中断: 篇幅有限并没有详细列出来,可以查看手册 EXPORT:声明一个标号可被外部的文件使用,使标号具有全局属性,上述代表中分别定义__Vectors为中断向量首地址,__Vectors_End为中断向量表末尾地址,__Vectors_Size为中断向量大小,实际代码中断向量表如下: DCD:分配一个或者多个以字为单位的内存,以4字节对齐,并要求初始化这些内存。 __initial_sp为0x0000 0000地址,为初始化栈地址,Reset_Handler为复位中断程序,该处理采用汇编进行编写 __Vectors_Size为计算中断向量表大小为(__Vectors_End - __Vectors)。 Reset Handler reset为程序上电进入,设置时钟,进入main函数处理 首先声明Reset_Handler, SystemInit和__main函数,SystemInit为外部C语言编写文件主要是对时钟初始化,__main为main函数入口,可以被该汇编文件进行调用。 LDR:从存储器中加载到寄存器中。 BL:程序跳转指令,程序PC指针跳转到由寄存器/标号给出的地址,并把跳转前的下一条指令地址保存到LR中 BLX: 与BL不同之处,根据寄存器的LSE确定处理器的状态,并把跳转前的下一条指令保存到LR。 上述程序,首先把SystemInit()函数地址加载在R0中,并跳转到SystemInit()函数,执行SystemInit,执行完毕后 加载__main函数,程序跳转到main函数中。 SystemInit()函数功能意义在后续中继续解释。 中断服务程序 中断服务程序默认没有编写,默认的中断程序如下: 上述每个中断程序默认为无限循环,当进入到中断,而开发者有没有实现中断服务程序将会进入死循环。 注意:中断服务程序需要开发者实现相应中断,一般是在stm32f4xx_it.c文件中。 堆初始化 堆的初始化调用是在一下程序中: IF:相当于C中if ,上述代码意思是判定__MICROLIB宏是否定义 如果定义,将会跳转到__initial_sp,使用上述代码中默认堆栈大小初始化,如果没有定义将会使用__use_two_region_memory,用户自定义。 __MICROLIB宏的定义是在keil5工具中进行勾选,如下所示: |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 06:50 , Processed in 0.898233 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号