在本章中,我们将从整体来看构建一个完整的QNX嵌入式系统所需要的关键步骤。
首先,我们将看到QNX中微子系统需要做什么才能运行。然后,我们将看看这些组件以及它们是如何运作的。最后,我们将概述自定义某些部分时可能需要遵循的步骤
简介
从软件的角度来看,系统启动时会执行以下步骤:
- 处理器在重置向量处开始执行。IPL (Initial Program Loader)查找操作系统镜像,并将控制权传递给镜像中的Startup程序。
- Startup程序配置系统,并将控制转移到微内核和进程管理器(procnto)。
- procnto模块加载额外的驱动程序和应用程序。
IPL的作用
该软件执行的第一步是加载操作系统镜像。这是由一个叫做IPL(Initial Program Loader)的程序完成的。IPL的初始任务是最低限度地配置硬件,以创建一个允许Startup程序以及微内核运行的环境。具体来说,这项任务至少包括以下步骤:
- 从复位向量开始执行。
- 初始化DDR
- 配置时钟。
- 设置堆栈以允许IPL执行操作系统校验和Setup(镜像下载、扫描、设置和跳转)
Startup充当的角色
软件执行的第二步是配置处理器和硬件,检测系统资源,并启动操作系统。这是由Startup程序完成的。
IPL只进行了必要的最低配置,达到Startup程序可以运行的状态,而Startup程序的工作是“完成”配置。如果IPL检测到各种资源,它将把这个信息传递给Startup(这样Startup就不必重新检测相同的资源)。
为了让QNX尽可能的可配置,我们给了Startup对基本定时器、中断控制器、缓存控制器等硬件的编程权限。它还可以提供内核调用(callouts),内核可以调用这些代码片段来执行特定于硬件的功能。例如,当硬件中断被触发时,一些代码必须确定中断的来源,而另一段代码必须能够清除中断的来源。
注意,启动程序不配置诸如串口波特率之类的东西。它也不初始化以太网控制器等标准外围设备,这些是留给QNX启动后驱动去做的。
一旦启动代码初始化了系统,并将有关系统的信息放置在system page区域(内核稍后将查看的专用内存块)中,Startup将执行最后的任务——将控制权传递给QNX内核和进程管理器(procnto)。
Startup的职责
让我们来看看启动代码的总体职责和流程:
1. 复制并解压QNX镜像。
2. 配置硬件。
3. 确定系统配置。
4. 启动内核。
复制并解压镜像
如果映像不在DDR中的链接地址,Startup将它复制到链接地址。如果Image已经压缩,Startup会自动解压缩图像。系统镜像的压缩是可选的。
配置硬件
这里的主要任务是设置能够确定系统配置(然后执行系统配置)所需的最小值。在硬件配置阶段需要配置的细节取决于您的特定硬件。
决定系统配置
根据嵌入式系统的性质,您可能希望在启动时动态确定配置,或者(在深度嵌入式系统的情况下)简单地“硬编码”配置信息。
不管信息的来源是什么,启动代码的配置部分都需要将这些信息存储到一组定义良好的数据结构中,OS在启动时将查看这些数据结构。统称为system page区域,这些数据结构包含以下信息:
•内存配置
•硬件设备配置
•处理器类型
建立callouts
为了让QNX Neutrino内核便于移植(不仅适用于不同的处理器,而且适用于这些处理器的不同硬件配置),Startup必须提供大量的调用。并不是所有的callout都需要用户编写—我们有一个库可以提供其中的许多代码。
以下类的callout函数可以提供给QNX Neutrino
• 调试接口
• 时钟/计时器接口
• 中断控制器接口
• 缓存控制器接口
• 电源管理
• 其他
启动OS
Startup执行的最后一步是启动操作系统。
startup库
如果以上这些听起来需要大量的工作,那么,确实如此!但是请注意,我们已经为一些常见的启动程序提供了源代码,并创建了一个库来执行上面的大部分功能。