小白的单片机之旅——单片机的启动
如前文《小白的单片机之旅——从点亮led说起(1)》所述,我们给mcu的所有文件就是一个bin文件,显然单片机的启动过程也体现于其中,与之相对应的文件就是与单片机硬件紧密对应的启动.s文件,下面我们以非常常见的使用ARM的cortex-M3内核的stm32f103zet单片机为例,说一说启动文件的内容。
一般该启动文件厂家会直接提供不需要自己去写,具体的文件内容这里不详细展开,就简单看一下启动文件的注释部分。简单来说启动文件做了以下一些事情:1、初始化栈指针;2、初始化程序指针为复位向量(这就是上电之后最开始要做的一些动作);3、设置中断向量表(如果对照bin文件和我们编译生成的map文件就会发现bin文件中栈顶指针数据、复位向量后面紧接着的就是各种中断处理函数的地址,这些就构成了硬件需要的完整的中断向量表,可以看到的是很多中断都预先有定义并且被定义成weak,这就表示,用户可以重写对应的中断处理函数,在编译过程中会使用用户定义的那个);4、初始化时钟系统(刚上电的时候clk是很慢的,在这里初始化时钟之后,mcu就快了);5、如果有外部扩展sram,初始化之;6、按照链接脚本的指示初始化对应的内存数据(比如我们定义的那些初始化的全局变量就是这个阶段生效的);7、跳转到我们用户的main函数(这就是我们一般认为c的程序入口)。
stm32f103zet对应启动文件的注释部分截图
中断向量表部分
由此,我们可以简要知道mcu上电之后发生的一些事情,进入我们的main函数之后,我们自己的“意志”开始执行了,下一节我们就一起看看如何将我们的控制led的意图告诉mcu,并让它正确的执行。
单片机启动流程分析(由单片机转linux非常有必要看一下)
一 单片机启动流程概述
单片机上电后一直到准备好C语言运行环境并跳转到main函数执行总共经历了5个步骤:
1.内核初始化;
2.强制PC指针指向中断向量表的复位中断向量执行复位中断函数;
3.在复位中断函数中调用 SystemInit 函数,初始化时钟,配置中断向量表等
4.调用 __main 函数完成全局/静态变量的初始化和重定位工作,初始化堆栈和库函数
5.跳转到main函数中执行
二 内核初始化
在单片机上电后首先会进行一系列内核的初始化,关于这部分工作我们只需要了解即可,在内核初始化的过程中主要做了以下几件事情:
1.内核复位和NVIC寄存器部分清零;
2.内核设置堆栈:内核从向量表0地址读出堆栈地址,并设置主堆栈指针(SP_main);
3.设置PC和LR寄存器
a. LR设置未初始复位值0xFFFF FFFF
b. 单片机的内部硬件机制自动将PC指针定位到中断向量表的复位中断向量出,把复位中断函数Reset_Handler的地址赋值给PC指针,然后跳转执行Reset_Handler。
三 复位中断函数 Reset_Handler
在内核复位的最后一步,将PC指针指向了复位中断向量,而复位中断服务函数中的内容才是我们真正需要关心的内容。查看IAR环境中的* .s 单片机汇编启动文件有以下一段内容:
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit ;加载SystemInit的地址到寄存器R0中
BLX R0 ;跳转R0中的地址执行(执行SystemInit函数)
LDR R0, =__main ;加载SystemInit的地址到寄存器R0中
BX R0 ;跳转R0中的地址执行(执行__main函数)
ENDP
1
2
3
4
5
6
7
8
9
上面的代码就是Reset_Handler的中断服务函数,可以看到在服务中断函数中先使用 IMPORT声明了两个函数 __main,SystemInit,然后顺序跳转执行SystemInit和**__main**函数。下面我们再来了解一下这两个函数具体干了些什么事情:
SystemInit 函数:
在system_stm32f4xx.c文件中我们可以看到该函数的定义,该函数主要干了以下两件事情:
1.初始化时钟:SYSCLK,HCLK,PCLK2 and PCLK1 prescalers
2.配置中断向量表:中断向量表的定位是在 Flash 还是 SRAM,是否需要偏移)
注意:可以通过system_stm32f4xx文件中的宏定义修改系统时钟频率(通过设置锁相环的相关系数),中断向量表的地址(位于SRAM还是Flsah,是否偏移,偏移地址多少等参数)
__main()函数(在IAR中是 __iar_program_start ):
该函数被封装进了编译器的库中,所以不同的IDE该函数的名称有所区别,但所实现的功能大致类似:
1.完成全局变量/静态变量/常量的初始化和重定位工作:
a. 跳转进入__scatterload_rt2函数:通过设置四个寄存器来配置待copy内容(静态变量、全局变量、常量)的的加载域和运行域,设置待copy内容的大小,为后续__scatterload_cpy()函数服务。
b. 跳转进入__scatterload_cpy函数,完成静态变量、全局变量、常量的从flash到SRAM的重定位。
c. 跳转进入__scatterload_zeroinit函数,完成未初始化的全局变量的初始化。
2.初始化堆栈(这里指程序栈)和库函数:
跳转进入__user_steup_stackheap函数:调用**__user_libspac__user_libspace**为C库保持了静态数据。这是一个96字节,0初始化的数据块,该块由C库创建。在C库初始化期间可以用来当做临时栈。再调用 __user_initial_stackheap 用户的初始化堆栈函数,实现用户的堆栈的配置,调用 _fp_init 和 __rt_fp_status_addr (C库函数) 两个函数调用实现浮点运算的支持。
3.程序的跳转,进入main()函数:
跳转进入用户的main函数
注意:
未初始化和初始值为零的全局变量,静态变量一般在RAM中, 初始值不为零的全局变量/静态变量 一般在FLASH中。
因为Flash不能随机写(只能写0,不能写1),所以一般会在程序运行之前将初始值不为零的全局变量重定位到RAM中。
全局变量和常量的地址在编译时都已经被分配好了(所以能够在 .map 文件中看到), 而局部变量则是程序运行时在栈中创建的,栈空间大小可以在IDE中设置。
单片机启动时,不需要用将代码从ROM搬移到RAM ,而 ARM 则需要。单片机程序执行的过程分三个步骤:取执行->分析指令->执行指令。取指令的任务是:根据 PC的值从程序存储器读出指令,送到指令寄存器。然后分析执行执行。这样单片机就从内部程序存储器去代码指令,从 RAM 存取相关数据。要知道RAM取数的速度是远高于ROM的,但是单片机因为本身运行频率不高,所以从ROM取指令慢并不影响。而ARM不同,CPU运行的频率高,远大于从 ROM读写的速度,所以一般有大型的操作系统时,都需要将代码部分拷贝到RAM中再执行。
————————————————
版权声明:本文为CSDN博主「GWen9」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/aa386447225/article/details/109546384
相关问答
单片机 bootloader 启动过程 ?分为以下几个步骤:1.开机复位:单片机初始状态下处于复位状态,所有寄存器、引脚和内存的值会被清零,程序从复位地址开始执行。2.初始化系统时钟:正常情况下...
arm 单片机 的 启动 方式?ARM单片机的启动方式主要分为两种:硬件启动和软件启动。硬件启动是通过外部引脚或者复位电路使芯片进入复位状态,然后根据芯片内部的复位向量表执行初始化程...
ARM-M0 单片机启动 流程?ARM-M0单片机的启动流程如下:首先,复位信号被触发,将处理器置于初始状态。然后,处理器会执行复位向量表中的第一个指令,该指令通常是跳转到主程序的入口点。...
单片机 一 启动 就执行程序?这个是与时钟有关的,上电后进行复位,然后根据时钟信号,程序计数器就开始计数,让程序不断运行。单片机里面一般都有个测试io口的程序。如果单片机一启动就执...
自己做的 单片机 (STC89C52)系统为什么要先碰一下晶振的脚才能 启动 ?请告诉我解决方法和原因?应该是晶振两边的电容导致的晶振没有起振。看看你所用的单片机的资料给的晶振两边的电容典型值是多大的,如果电容值没有问题,你找找看有没有虚焊。应该是晶振...
什么是 单片机 冷开启-ZOL问答单片机冷启动是一个技术术语,是指单片机从最原始状态启动运行。实现这一目标视不同的单片机内部结构而有所不同。STC单片机只有掉电且电路中电容器储存电压低...
51 单片机 程序写入以后怎么运行?在将程序写入51单片机后,您可以按照以下步骤来运行它:1.确保您已正确地将51单片机与外部电路连接,包括电源、晶振、复位电路和其他所需的外围设备。2.将编...
51 单片机启动 电压?51单片机是由多少伏直流电压供电51单片机有5V和3.3V工作电压的,如果是5V工作电压,那么选5V直流电压供电。如果是3.3V,最好选3.3V直流电压供电,也可以选5V直...
会51 单片机 ,如何快速学习使用STM32 单片机 ?单片机其实都是相通的,会了一种单片机,对着数据手册查看一下寄存器的设置可以快速的入手其他型号的单片机。会51单片机,说明有单片机的基础,再去学习STM32单...
51 单片机 编程程序怎么编?51单片机编程程序怎么编?♣这种技术性问题在今日头条上,几乎没有一个高手给你一个答复。因为学习51单片机编程程序是需要长篇大论,并且用电脑操作截图来说明...