嵌入式实时操作系统的设计与开发 (启动内核学习)

RTOS的引导模式

RTOS的引导是指将操作系统装入内存并开始执行的过程。

时间限制主要包括:系统要求快速启动系统启动后要求程序能实时运行。

空间限制主要包括:Flash等非易失性存储空间限制RAM等易失性存储空间限制。

通常不可能同时满足两种要求,需根据具体情况进行折中处理,由此,RTOS的引导分为如下两种模式。

需要BootLoader的引导模式

BootLoader是在RTOS内核运行之前执行的一段小程序,它将RTOS内核从外部存储介质复制到内存中,并让PC跳转到刚复制到内存的内核的首条指令。

在嵌入式系统中,BootLoader依赖于硬件,几乎不可能建立一个通用的BootLoader。不同的CPU体系结构都有不同的BootLoader,另外,BootLoader还依赖于具体的嵌入式板级设备的配置。

对于采用高性能RAM的系统,出于成本因素,RAM空间有一定限制,此时一般采用Bootloader引导方式:由Loader程序把RTOS内核中的数据段复制到RAM中,代码段在Flash中运行。

因为代码段在低速的Flash中运行,该方式在节省空间的同时,牺牲了时间。这种引导方式适合于硬件成本低、运行速度相对较慢的嵌入式系统,但是启动时间却较快。

如果RAM空间没有限制,足够程序运行时,由Loader程序把RTOS内核从非易失性存储介质全部复制到RAM中,对于某些压缩的内核,复制后还需要解压。此时,不能满足对启动速度要求特别高的系统,但是系统的运行速度却能得到保障。

不需要BootLoader的引导模式

对于实时性要求较高的系统,通常要求系统能够快速启动。由于将Flash中的代码复制到RAM中的操作会带来一定的时间开销,因此,对于此类系统启动时无须BootLoader,而直接在NorFlash或ROM等可以做主存的非易失性存储介质中运行,以达到较快的启动速度。但这种引导模式不能满足运行速度的要求,因为Flash的访存时间与RAM的访存时间存在数量级上的差距。

通常,除了上述两种引导模式中考虑时间、空间效率以外,出于空间效率的要求,需要对RTOS内核使用压缩工具进行压缩,在RTOS引导时,采用逆向解压缩算法解压。

同时,出于实时性的考虑,压缩算法不能过于复杂,否则压缩、解压过程消耗大量时间将与启动时间限制发生严重冲突。

采用压缩策略并不一定会增加系统启动时间,因为压缩、解压过程虽然消耗了一定的时间,但是由于内核体积小,由Flash复制到RAM中的时间相应减少,有可能反而减少了时间消耗。

以VxWorks操作系统为例,VxWorks Image分为在ROM中运行和RAM中运行两种,而且在ROM中运行的VxWorks Image是非压缩的,不需要解压;但在RAM中运行的VxWorks Image是压缩的,引导时需要解压COPY所有的text和data到RAM中。

BootLoader

BootLoader可以拆分成两部分:一个是Boot,另一个是Loader。

  1. Boot:Boot意味着系统启动时会从这里启动,具体一定就是当大家按下开机键时,CPU执行的第一条指令就是Boot的代码,也就是说Boot的代码要存储在CPU第一条指令的地址处。
  2. Loader:加载代码程序,这个程序就是内核映像。

从上面可以看出,在PC上,BIOS满足上面的特性,因为PC启动时就是从BIOS的地址处启动的,然后BIOS的代码读取硬盘的第一扇区的数据,即引导程序,然后将控制权交给引导程序,再由引导程序加载操作系统内核代码运行。

而在嵌入式系统中,Vivi、Uboot等就是BootLoader,这些程序都是开机时就启动,启动后,会从NAND Flash或SD卡等存储设备中奖RTOS内核程序代码复制到SDRAM中,然后执行内核代码。

aCoral的BootLoader就是start.s,代码很少。

Vivi,Uboot代码量大的原因主要是:它们都支持多种嵌入式平台,都可以看成是一个通用的BootLoader,除了提供上面启动、RTOS加载两个功能外,它们还支持更多功能,如支持各种命令,这些命令主要分为以下两大类:

  1. 操作设备类:支持板载设备的操作,如操作Flash等。
  2. 数据相关类(通信和管理):支持FTP、NFS等网络协议,支持USB下载等。

有些BootLoader,如ARM公司的Bootmonitor还支持文件系统,能以文件系统的方式管理NANDFlash、SDCARD上的数据。

有了上面两大类操作的支持后,BootLoader不再是纯粹的BootLoader了,它已具备了一些操作系统的功能,只是不支持操作系统支持的任务管理、调度、切换等功能。

其实像Vivi,Uboot这些BootLoader在电子产品很少用到,因为电子产品强调性能、成本,且不愿意用户有太大的修改权利,且Vivi,Uboot尺寸很大,启动时间长,严重影响系统的性能和成本,因此商用后,BootLoader肯定越小越好。

真正在商用产品中,BootLoader这部分代码直接写到操作系统,这个简单的BootLoader是和内核一起编译,并且通过链接器链接在一起的。

存储介质的划分方法

  1. 按存储介质分类。作为存储介质的基本要求,必须具备能够显示两个有明显区别的物理状态的性质,分别用来表示二进制码的0和1。另一方面,存储器的存取速度又取决于该物理状态的改变速度。目前主要是半导体器件和磁性材料,用半导体器件组成的存储器称为半导体存储。
  2. 按存取方式分类。如果存储器中任何存储单元的内容都能被随机存取,且存取时间和存储单元的物理位置无关,这种存储器称为随机存储器。半导体存储器和磁芯存储器都是随机存储器。如果存储器只能按某种顺序来存取,也就是说存取时间和存储单元的物理位置有关,这种存储器称为顺序存储器。例如,磁带存储器就是顺序存储器。一般来说,顺序存储器的存取周期较长,磁盘存储器是半顺序存储器。
  3. 按存储器的读写功能分类。有些半导体存储器存储的内容是固定不变的,即只能读出而不能写入,因此这种半导体存储器称为只读存储器(ROM)。既能读出又能写入的半导体存储器,称为随机存储器(RAM)。
  4. 按信息的可保存性分类。断电后信息即消失的存储器,称为非永久记忆的存储器。断电后仍能保存信息的存储器,称为永久性记忆的存储器。磁性材料做成的存储器是永久性存储器,半导体读写存储器RAM是非永久性存储器。
  5. 按串、并行存取方式分类。目前使用的半导体存储器大多为并行存取方式,但也有以串行存取方式工作的存储器,如电耦合器件(CCD)、串行移位寄存器和镍延迟线构成的存储器等。

为什么会出现这么多种类呢?这是价格和用户需求平衡的结果。

例如,大家知道程序最后运行必须要有随机可读写存储器来存储变量,且速度要快,这导致了RAM的产生,但是RAM价格昂贵,于是又导致了SDRAM的产生,SDRAM和RAM的区别就是它是靠电容的值来保存0,1信息,时间一长就会丢失数据,故需要周期性刷新,这个在SDRAM控制器芯片的控制下能很好解决,且不太影响性能,但是它的速度比RAM低一些,复杂一些,但是价格低很多,容量可以做到很大,故是一种很好的存储器,因此目前无论是嵌入式还是PC设备都广泛使用到了SDRAM。

虽然SDRAM解决了可读写和速度问题。但是它们都是非永久记忆的存储器,断电后信息即消失,明显不能满足用户永久保存代码和数据的需求,因为用户总不至于每次启动计算机都要下载一次程序吧,于是就产生了NAND Flash、硬盘等永久记忆的存储器(硬盘容量很大,但是很少用在嵌入式系统中)。

这些存储器是永久记忆的,且能做到很大容量,但是速度慢,不过某种程序上还是可以承受的,因为有办法可以解决这个问题。
在启动阶段,Boot的工作完成后,Loader程序将系统程序和用户程序从这些存储介质上复制到SDRAM中,这样程序真正运行时,代码和数据就是从SDRAM中读取的了,也就没有速度问题。

有了NANDFlash、硬盘等永久记忆的存储器还不够,因为它们是按块访问的,而不是按地址访问,这种块模式访问往往需要有硬件控制器,而硬件控制器又需要有程序来控制,那这个控制器的驱动从何而来?这就是鸡生蛋、蛋生鸡的问题,正因如此,又出现了一种存储器ROM,如NorFlash等只读存储器。

NORFlash这种存储器也是永久记忆的存储器,但它和NANDFlash等不一样,它是按地址随机访问的,也就是说不需要驱动,和SDRAM的访问方式一样,可以很简单地访问数据,这就解决了这个问题,但是这种按地址访问的永久记忆的存储器相比有点贵,做不到很大容量。其实也没有必要过多使用这种存储器,因为它是只读的,没法修改,不会过多使用,所以只要能够容纳BootLoader程序就可以了,其它的代码交给廉价的可读写的NANDFlash。

BootLoader所选用的存储器肯定得是按地址随机存取的永久性记忆的存储器,当然对于支持NANDFlash启动的SOC,这可以存储在NANDFlash。

刚才不是说NANDFlash、SDCARD都是需要控制器才能访问数据的,控制器又需要驱动程序,那如何做到从这些地方启动呢?

其实,解决方法和上面讨论的一样,就是必须有一个复制过程,该复制过程可以有三种方式,硬件方式、软件方式、内存映射。

  1. 硬件方式。就是硬件实现对存储设备控制器的控制,读取指定大小的数据,它没法做的控制器的驱动程序那样,可以随机读取任意大小的数据,但是只要能够复制指定地址,指定大小的数据就已经够了,硬件可以看成是简化版的驱动。
  2. 软件方式。这种方式就更简单了,芯片自带一个ROM,往往是片内ROM,里面装有驱动程序,这个驱动程序负责将BootLoader从NAND Flash等存储器复制到RAM中,然后跳转到BootLoader中运行。这样方式其实和我们把BootLoader存储在ROM中是一样的,只不过板子自带了一个BootLoader,实现小量数据复制。
  3. 内存映射。当用户使用跳线选择启动方式后,硬件自动开启了内存映射,将其它地址映射到CPU启动地址
    如ARM11的PB11MPCore,CPU的启动地址是0x0,如果配置为NOR Flash启动,则可将NORFlash的原本地址0x40000000~0x43FFFFFF映射到0x0~0x3FFFFFFF,这样就相当于从NORFlash启动,这种方式是经常用的方式。
    由于NOR Flash原本内存空间映射到地址0x0了,导致地址0x0对应的内存没法使用,因此启动后需将映射取消,这就是取消地址映射。需要有按地址随机存储器的支持,即将存储启动代码的存储器的地址映射到启动地址。

RTOS映像文件的存储介质

RTOS这类操作系统一般比较小,存储介质选择余地有很多,可以放在ROM中,也可以放在NAND Flash中,无论放在哪里,只要BootLoader能找到RTOS映像文件,再将其复制到SDRAM就可以了。所以关键是看BootLoader是否强大,对于强大的BootLoader,其实RTOS都可以放在主机上,然后BootLoader可以通过网络将RTOS下载到SDRAM上,再从SDRAM上启动。

对于BootLoader和内核链在一起的RTOS,操作系统内核是跟BootLoader一起存储在一种存储介质中的。

相关推荐
LN-ZMOI16 分钟前
c++学习笔记1
c++·笔记·学习
五味香20 分钟前
C++学习,信号处理
android·c语言·开发语言·c++·学习·算法·信号处理
云端奇趣1 小时前
探索 3 个有趣的 GitHub 学习资源库
经验分享·git·学习·github
我感觉。1 小时前
【信号与系统第五章】13、希尔伯特变换
学习·dsp开发
知识分享小能手1 小时前
mysql学习教程,从入门到精通,SQL 修改表(ALTER TABLE 语句)(29)
大数据·开发语言·数据库·sql·学习·mysql·数据分析
冰榫2 小时前
9.30学习记录(补)
学习
霸王蟹2 小时前
Vue3 项目中为啥不需要根标签了?
前端·javascript·vue.js·笔记·学习
向上的车轮3 小时前
Django学习笔记八:发布RESTful API
笔记·学习·django
向上的车轮3 小时前
Django学习笔记九:RESTAPI添加用户认证和授权
笔记·学习·django
落雨便归尘3 小时前
c++进阶篇——初窥多线程(四) 线程同步的概念以及锁
c++·笔记·学习