
1、先说启动文件 我们正常在操作一款单片机的时候,都是从main函数开始进行编程的,但是单片机上电是从main函数开始执行的吗?答案当然是否定的,在main函数之前单片机最先执行的是硬件设置SP、PC然后是“启动文件”,一般主要是项目文件里面的startup_xxxxx.s文件。 其实不光STM32系列单片机是这样,我们接触的NXP的微控制器、TI的MSP430以及51单片机等等其实都是有上述的启动文件的。启动文件负责的就是从单片机复位开始到main函数之前这段时间所需要进行的工作。我们一般很少接触启动文件的主要原因是开发环境往往给开发者自动的提供了这个启动文件,不需要我们再去操心,直接从main函数开始进行设计就可以了。 STM32三种启动方式 接触过STM32系列单片机的朋友应该知道STM32有三种启动模式,用户可以通过设置BOOT0和BOOT1的引脚电平状态,来选择复位后的启动模式。 需要注意的是STM32上电复位以后,代码区都是从0x00000000开始的,三种启动模式只是将各自存储空间的地址映射到0x00000000中。 1)从Flash启动,将Flash地址0x08000000映射到0x00000000,这样启动以后就相当于从0x08000000开始的,这是我们最常用的模式; 2)从SRAM启动,将SRAM地址0x20000000映射到0x00000000,这样启动以后就相当于从0x20000000开始的,用于调试,笔者基本没用过; 3)从系统存储器启动(可以看上篇文章里的内存映射图,System memory),将系统存储器地址0x1FFFF000映射到0x00000000,这样启动以后就相当于从0x1FFFF000开始执行的,值得注意的是这个系统存储器里面存储的其实是STM32自带的Bootloader代码,这其实是一个官方的IAP,它提供了可以通过UART1接口将用户的代码下载到Flash中的功能,下载完以后再切换到从Flash中启动就可以正常运行了。打个比方这个官方的Bootloader就相当于我们玩路由器时的“不死breed”。笔者之前在调STM32低功耗的时候将下载口给复用了其他功能导致“变砖”,就是通过这种方式恢复的。 启动模式 3、切回正题 下面我们来具体看一下从用户的Flash启动STM32,从上电到main函数之间的这段时间都做了什么。 第一步是硬件设置SP、PC 我们参考《Cortex-M3权威指南》向量表章节表7.6,如下图所示: 上电后的向量表 前两段地址主要是用来指定SP和PC的初值,上一节我们已经知道了映射关系,所以这时已自动从0x08000000位置处读取数据赋值给了栈指针SP,从0x08000004位置处读取数据赋值给了PC。需要注意的是这个复位向量初始值并不是固定的,可以通过一个叫“向量表偏移量寄存器”来修改定位。 向量表偏移寄存器 下图是我们那个开源OLED时钟项目的HEX文件,用J-Flash打开就可以看到设置完的SP=0x20005B88,PC=0x0800282D。
J-Flash 2)第二步是设置系统时钟 我们接着来追踪系统的运行轨迹,上面我们已经知道了PC的地址为0x0800282D,但是这没有遵循4字节对齐,我们将其对齐为0x0800282C,这时我们打开项目文件里面的.map文件,找到这个地址,如下图示: .map文件 我们发现来到了第一节说的startup_xxxxx.s文件,我们打开startup文件找到:
startup文件 我们发现运行到了SystemInit,C的世界我们就不陌生了,在项目文件的system_stm32f10x.c里面可以找到SystemInit函数,也就是初始化系统时钟了。 3)第三步是main 到这里大家可能会以为已经到了main函数了,其实不是这样的。main和main是不一样的,我们寻找这个___main会发现找不到,startup文件里面没有,map文件里面也没有。其实它是在MDK自带的库里面了,主要的功能是软件设置SP、加载.data.bss并初始化栈区。由于需要在线跟踪才能看到,我在这里就不给大家列出来了,感兴趣的朋友可以深入研究一下。 4)最后来到C的世界 在执行到___main的最后就跳转到了C文件的main函数了。 最后用一张图来整体看一下流程:
流程图 |
不清楚为什么正点原子的例程,想添加SCB添加到watch1却是无效的(在core_cm3.h定义的寄存器都不可以),但是可以添加GPIOA并且有效(stm32f10x.h定义的寄存器都可以)
不知道为什么用正点原子的开源例程硬件仿真时。想观察寄存器的值,所以添加到watch1观察,不清楚为啥SCB,NVTC等都添加了但是无效,但是GPIOA却又可以。
哪里能下载ST官方展示的NUCLEO-G071RB配合X-NUCLEO-GFX01M1运行TouchGFX案例的源程序?
基于STM32的锂动力电池检测装置的设计
STM32G474 的DAC4无输出
STM32G030PWM中断小坑
STM32中如何实现数据加密
简单聊聊STM32的SPI外设
STM32的I2S外设
stm32cubeide新用户无法注册
感谢分享