单片机的启动过程

启动过程简介

单片机的启动过程是加电后,先运行芯片内部固有程序(这个程序是用户访问不到也改写不了的),即启动代码。启动代码程序建立完运行环境后,会去读串口状态,就是用户下载程序用到的各个端口,判断用户是否正在使用端口准备下载程序,如果是,就按用户要求,把用户程序下载到指定地址上。如果不是,就跳转到已经下载过的用户程序入口,从而把芯片控制权交给用户程序。如果是新的芯片还没有下载过,那么就停留在读取串口状态的循环中。

启动代码通常都烧写在flash中,它是系统一上电就执行的一段程序,它运行在任何用户C代码之前。上电后,arm处理器处于arm态,运行于管理模式,同时系统所有中断被禁止,PC到地址0处取指令执行。一个可执行映像文件必须有个入口点,而能放在rom起始处的映像文件的入口地址也必须设置为0。在汇编语言中,可以自行定义定义一个程序的入口点,当工程中有多个入口点时,需要在连接器中使用-entry指出程序的入口点。如果用户创建的程序中,包含了main函数,则与C库初始化代码对应的也会有个入口点。 总的来说,启动代码主要完成两方面的工作,一是初始化执行环境,例如中断向量表、堆栈、I/O等;二是初始化c库和用户应用程序。

在第一阶段,启动代码的过程可以描述为:

(1)建立中断向量表;
(2)初始化存储器;
(3)初始化堆栈寄存器;
(4)初始化i/o以及其他必要的设备;
(5)根据需要改变处理器的状态。

(1)建立中断向量表
初始化代码必须建立好中断向量表,以备应用程序后续使用。如果系统的地址0处是rom,则中断向量表直接是一些跳转指令就可以了,他们转到相应的中断处理函数执行。如果系统的0地址处不是rom,则中断向量表是通过动态的方式创建的,这主要是通过存储器映射的方式来实现:即上电后,rom中的地址被映射到地址0,它首先开始执行以便完成环境的初始化,最重要的它会将中断向量表拷贝到ram中,然后通过地址映射将ram地址映射为0,这样ram中的中断向量就可以使用了。
(2)初始化存储系统
对于有mmu的处理器,需要正确初始化mmu,没有的只需正确初始化存储控制器,为每个bank配置正确的参数就可以了。
(3)初始化堆栈指针
初始化代码必须初始化处理器各种模式下的堆栈指针,所有系统或用户程序会涉及的处理器模式对应的堆栈指针都应该被初始化。通常未定义指令和预取指终止异常对应模式的堆栈指针不需要配置,除非用户需要使用它们作为调试使用。
(4)初始化i/o以及其他必要设备
关键的输入输出模块必须在中断打开之前被配置,例如看门狗,否则它们会在系统启动后产生复位信号。
(5)改变处理器状态和模式
启动代码运行时,处理器状态认为管理模式,如果用户程序需要运行在用户模式,可以切换转入用户模式;所有处理器上电后是处于arm状态的,如果需要改变处理器状态,也可以在启动代码里切换到thumb态。

第二阶段

在执行环境建立起来后,接下来就是应用程序的初始化,简单点就是讲用户程序加载到他们相应的运行地址,初始化数据区等,这个阶段完成后,才能进入用户最终的C代码区域。用户应用程序的初始化过程包括:将rw段的数据拷贝到他们的运行地址处,同时在rw段后面初始化相应大小的字段数据,把他们初始化为0,使用了库函数的程序(工程中有main函数)是在库函数_main中自动完成这些工作的。

C51的启动过程

当用keil作为开发环境,创建一个工程时,需要选择所使用的单片机型号,然后Keil会将相应单片机的startup.A51文件拷贝到工程目录下,在编译时,该文件会被编译到最终的目标文件中。一般情况下,这个文件是不需要我们做修改的,保持默认状态即可。

startup.A51文件主要完成了如下过程:

  1. 初始化8051硬件堆栈的大小和堆栈指针;
  2. 初始化中断向量表,分配每个中断的入口地址和中断服务函数;
  3. 初始化内部RAM空间,即DATA/IDATA,将内容清零;
  4. 初始化外部RAM空间,即XDATA/PDATA,将内容清零;
  5. 初始化SMALL/COMPACT/LARGE模式下reentrant函数使用的堆栈指针;
  6. 调用main()函数,去执行我们编写的代码。

STM32的启动过程

参考:

https://blog.csdn.net/qq_15391889/article/details/82723461

http://www.elecfans.com/emb/danpianji/20181109811542.html

参考资料

1. 单片机的启动过程

2. 8051 MCU学习之分析单片机的启动过程

猜你喜欢

转载自blog.csdn.net/u014587123/article/details/108190445