不同嵌入式系统启动过程分析(小型单片机以51为例,大型单片机以ARM-A系列为例)

4 篇文章 1 订阅
3 篇文章 0 订阅

启动即是芯片上电复位要运行的程序,启动作为一个模块独立于操作系统而在,因为操作系统需要通过启动这个模块来加载和引导的。所以启动的英文术语是boot loader。我对boot loader的定义包括两部分:1.加载os 2. 为了让os能够正常运行所要做的硬件和软件初始化工作。

我们常常看到boot loader这个词语用于arm引导linux,X86引导windows等等。可见一般意义上,能用上boot loader都是一些计算能力强并外挂SDRAM的SOC方案。

那我们咱们去理解单片机这种内存资源有限型的嵌入式系统的启动呢?就以51为例。

(小型)51单片机启动流程

           51体系SOC一般都是内置K字节级别的nor flash用于运行代码,并内置一块K级别较小的ram用于数据读写。很明显这种系统跑不了linux这种高大上的系统,那51的启动都干嘛呢?我们从程序开发流程说起:

           1)编写程序,编译,链接成可执行文件。一般在keil集成环境中。

           2)keil的二进制工具(类似gcc的objcopy)中的可执行文件,抽取code和data数据,生成带有加载地址的.HEX格式文件。记住是加载地址,而不是运行地址。

           3)烧写.HEX文件数据到nor flash,其根据的是文件中的加载地址。一般来说,代码段的加载地址和运行地址是一样的,这样才能在nor flash中跑起来。但是data是要放在内置ram区域才能可读写的,可是ram掉电会消失啊。所以data是先加载到nor flash的。即data的运行地址在ram区域,而加载地址在flash区域。

           4)上电复位后,启动代码会进行硬件初始化,例如时钟,看门狗,串口等等

           5)准备好栈,然后把data从加载的地方copy到ram的运行区域(链接地址)

           6)初始化好bss,然后就jump到主程序开始跑啦。

          简单的嵌入式系统一般没有os,就是上面的流程。这种系统的代码量一般比较小,全部放到内置的nor flash中,没有外挂的nand flash或者card。它可以支持读写卡,但是代码只放到内置的nor flash,而没有放到外置的卡中。

          事实上51也可以像arm那样引导操作系统的,当然操作系统不仅对内存有要求,对CPU计算能力也有要求,所以51是不能胜任跑linux的。但是51也能引导并跑简单的操作系统的,例如UCOS等等,只要ram足够大就可以。所以基于51的SOC系统也可以跑Linux那样的系统,代码是放在外置的nand flash或者card中,那启动就要成为一个独立的模块和U启动COS、应用程序放在外置的nand中,上电的时候先通过irom来加载启动的代码到iram中,然后跑启动代码,并在启动代码中引导os。

TIPS

对于单片机的程序执行时codedata的存放与读取,理解如下:对单片机编程后,程序的代码段,data段,bss段,rodata段等都存放在Flash中。当单片机上电后,初始化汇编代码将data段,bss段,复制到RAM中,并建立好堆栈,开始调用code段程序的main函数。以后,便有了程序存储器,和数据存储器之分,运行时从Flash(即指令存储器,代码存储器)中读取指令,从RAM中读取与写入数据。RAM存在的意义就在于速度更快。

(大型)ARM启动流程

这里只是ARM为例做说明,其实是一类内存资源比较丰富的嵌入式系统启动流程。以下将使用ARM + Linux的架构说明。

内存资源宽裕型操作系统一般都外挂SDRAM,并且CPU的计算能力都比较强,例如基于cortex A、MIPS 74k等核心的SOC。

  图1,对于资源紧缺型系统,内置flash和ram。上电之前就已经通过烧写工具将代码写到内置flash(nor flash),而iram用于data读写。

图2是资源宽裕型系统,其代码都放在外置存储介质中,如nand,sd卡等,包括引导OS的启动代码、OS、根文件系统和用户数据。上电后的运行过程是:

       1)irom中有第一阶段的启动代码,一般称为boot loader 0(BL0),其作用是为了引导nand flash中的启动代码到IRAM中,而nand flash中的启动代码是为了引导OS代码,称为BL1。BL0上电运行,这时SDRAM尚未初始化,所以其需要将BL1搬到IRAM中运行。BL0的代码量比较小,主要是固化nand flash和card的读驱动代码,因为其要支持不同的启动介质。

            由于受成本约束,IRAM也不可能很大,那BL0搬BL1的大小一般是固定的,一定要小于IRAM大小;而引导OS的启动代码往往超过IRAM大小,所以引导OS的启动代码又再分为两部分,一般分是由BL0搬到IRAM,即BL1;剩下的一部分称为BL2。UBOOT就是这样。

       2)BL0引导BL1到IRAM后,把控制权交给BL1。BL1初始化好SDRAM,接着将BL2搬到SDRAM。

       3)BL1将控制权交给BL2,BL2接着引导OS,最后把控制权交给OS。

 

事实上,为了支持不同的启动模式,如上电复位,看门狗中断,睡眠唤醒等等,在2)中,BL1会将自身BL1和BL2一起搬到SDRAM。可见BL1可能运行在IRAM中,也有可能运行在SDRAM中,一份代码只有一个链接地址,怎么可以在两个不同的虚拟地址上运行呢?答案就是BL1一定是位置无关的,GCC编译选项是-fPIC (Position-Independent Code)。

总结自微信公众号嵌入式企鹅圈

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值