跳到主要内容

嵌入式操作系统-寒枫25年5月

第一章 嵌入式系统概论

嵌入式系统是由嵌入式微处理器、外围硬件设备、嵌入式操作系统以及用户的应用程序等四个部分组成,以应用为中心,以计算机技术为基础,软硬件可配置,对功能、可靠性、成本、体积、功耗有严格约束的专用系统。

嵌入式系统特点

实时性:环境特定;快速启动。异步事件的并发处理:多任务;随机性。 应用/操作系统一体化 VxWorks;Linux。应用固化不可修改性。实用性:面向行业;定向开发。适用性:可裁减,适应应用。 鲁棒性:容错。够用即可:成本、资源。可信性:安全、防危、可靠等。

实时系统特点

实时系统:即要求及时,在系统允许的时间范围内完成任务。

• 时间约束 任务具有一定的时间约束(截止时间)。 • 可预测性 要求硬件延迟的可预测性、软件系统的可预测性、以及应用程序响应时间的可预测性。 • 可靠性 环境恶劣,有较高的可靠性 —— 工业级。 • 交互作用  与外部环境的交互 —— 必须在规定的时间内对外部请求做出反应。 • 多任务类型 周期任务、突发任务、非周期任务、非实时任务。 • 负载不均衡 必须满足一定的峰值负荷要求。 • 实时调度

安全性要求级别:家庭、办公、工业、航天航空

嵌入式系统发展趋势

嵌入式系统硬件:复杂化、多核、异构

处理器整体结构:集中式(单处理器、性能更高)、分布式(SoC、GPU、加速器、...)、AI 加速芯片 结论:混合硬件

嵌入式软件:混合调度、高效利用、AI 集成、...混合关键(实时、安全、可靠、...)调度;

RTOS 的小型、高效,时空隔离下的资源利用模块化/模型化设计,设备端 AI 融入,...

嵌入式系统结构

核心原理框架
嵌入式系统核心原理框架
软件结构
嵌入式系统软件结构

第二章 嵌入式硬件基础

硬件是以嵌入式微处理器为核心,主要由嵌入式微处理器、总线、存储器、输入/输出接口和设备组成。

处理器

结构,处理器,特点,分类,功耗管理

ARM 的七种工作模式,大端存储和小端存储。

  • 大端存储:将数据的最高有效字节(MSB )存于内存低地址端 ,最低有效字节(LSB )存于高地址端。比如 16 进制数 0x1234,内存中低地址存 0x12,高地址存 0x34 ,符合阅读习惯,处理效率低。
  • 小端存储:把数据的最低有效字节存于内存低地址端 ,最高有效字节存于高地址端。像 0x1234,内存里低地址是 0x34,高地址是 0x12 ,但契合部分 CPU 从低地址往高地址读数据的方式。arm 默认。

总线

ARM AMBA

PCI 总线、PCI-E 总线、CPCI 总线

存储器

Cache、主存、外存

NOR Flash 与 NAND Flash 特性对比表

特性NORNAND
写入/擦除一个块的操作时间1~5s2~4ms
读性能1200~1500KB600~800KB
写性能<80KB200~400KB
接口/总线SRAM接口/独立的地址数据总线8位地址/数据/控制总线,I/O接口复杂
读取模式随机读取串行地存取数据
成本较高较低,单元尺寸约为NOR的一半,生产过程简单,同样大小的芯片可以做更大的容量
容量及应用场合1~64MB,主要用于存储代码8MB~1GB,主要用于存储数据
擦写次数(耐用性)约10万次约100万次
位交换(bit位反转)较多,关键性数据需要错误探测/错误更正(EDC/ECC)算法
坏块处理无,因为坏块故障率少随机分布,无法修正

第三章 嵌入式软件体系结构

体系结构:具有一定形式的结构化元素,即构件的集合,包括处理构件、数据构件和连接构件。

嵌入式软件体系结构

软件体系结构通用模型

无结构、层级结构、圈层结构、对象结构、客户机/服务器结构模型……

所谓的 MVC 结构,B/S 结构也是从 C/S 结构演变来

软件体系结构通用模型

虚拟机体系架构:以牺牲运行效率为代价,优化应用的可移植性。一个抽象计算机,有自己的抽象指令,解释执行抽象指令,在实际 计算机上运行

虚拟机体系架构1 虚拟机体系架构2

模型驱动的软件开发

传统设计方法:当面对一个新的业务需求时,总是从先建立数据表等结构开始

基于模型驱动的软件设计,使用 UML

模型驱动软件开发UML

嵌入式实时模型

轮询模型

总体框架是死循环,可以包含子轮询(不是死循环)

轮询模型框架
典型系统
轮询模型典型系统

前后台模型—中断模型

前后台中断模型
典型系统结构
前后台模型典型系统结构

第四章 嵌入式软件基础

开发一个 ES,相当于开发一台计算机,需要开发硬件系统 H/W,对所开发硬件,需要开发/配置相应的驱动程序,需要提供系统引导程序 Bootload,可能需要配置 RTOS,需要针对应用领域,采用专用的 RTOS 并进一步优化,最后:开发特定领域的嵌入式应用软件

软件 = 算法 + 数据结构 + 文档;软件即服务

• 嵌入式软件  Embedded Software,ES。分类如下

嵌入式应用软件:多媒体应用、传感器网络、信息家电 嵌入式支撑软件:编辑编译、调试测试、文件数据库系统 嵌入式基础软件:系统引导、板级支持包、嵌入式操作系统

概念:实时软件 Reaitime Software,RTS;

板级支持包 Board Support Package,BSP:嵌入式系统的基础部分,实现系统可移植性的关键 负责上电时的硬件初始化、启动 RTOS 或应用程序的支持模块、提供底层硬件驱动,提供上层软件提供访问底层硬件的手段。

板级支持包BSP示意图

启动加载 Bootloader;

驱动程序 Driver:对设备初始化和释放。对设取应用程序传送给设备文件的数据,并回送应用程序请求的数据。检测和处理设备出现的错误

嵌入式软件运行的五个阶段 ☆

嵌入式软件运行五个阶段

嵌入式软件运行过程主要包括以下五个阶段

板级初始化

  • 顺序与特性:上电复位后开始,完全与硬件相关,一般采用汇编语言实现。
  • 核心内容:初始化 CPU 中堆栈指针寄存器、BSS 段(Block Storage Space),以及进行 CPU 芯片级的初始化,包括中断控制器、内存等的初始化。

系统引导 / 升级

  • 选择方式:根据测试通信端口数据或判断特定开关,选择进入系统软件引导阶段或系统升级阶段。
  • 系统引导阶段:有 RAM 启动(系统软件从 NorFlash 中读出并加载到 RAM 中运行,运行速度快,软件可压缩存储在 Flash 中)、NorFlash 启动(系统软件直接在 NorFlash 上运行)和外存启动(软件从外存中读取出来加载到 RAM 中运行,成本低)三种方式。
  • 系统升级阶段:分为远程升级(通过网络,支持 TFTP、FTP、HTTP 等方式)和本地升级(使用超级终端或特定的升级软件进行)。

RTOS 的引导模式 • 需要 Boot Loader 的引导模式:采用高性能 RAM 的系统;受 RAM 空间的限制,运行时载入,让 PC 跳转到刚拷贝到内存的内核的首条指令 • 不需要 Boot Loader 的引导模式:对需要快速启动的系统;时间效率要求较高,空间限制较少。 • 方法:直接在 NorFlash 或 ROM 等非易失性主存介质中运行,启动速度快。

系统初始化

  • 工作内容:完成操作系统等系统软件运行必需的初始化工作,如根据系统配置初始化数据空间,初始化系统所需的接口和外设。
  • 执行顺序:首先完成内核的初始化,接着完成网络、文件系统等的初始化,最后完成中间件等的初始化工作。

应用初始化

  • 工作内容:进行应用软件运行必需的初始化工作,包括应用任务的创建,信号量的创建,消息队列的创建,以及应用相关的其它初始化。

多任务系统运行

  • 运行状态:系统进入多任务状态,操作系统按照已确定的算法进行任务的调度,各应用任务分别完成特定的功能。

acoral嵌入式系统

acoral嵌入式系统启动流程

板级初始化 Boot:romInit(),上电后执行的第一个函数。关中断设置哑堆栈(dummy stack,也称虚拟堆栈),保存启动类型(冷启动和热启动)到堆栈上,清 Cache,初始化 CPU 内的寄存器,硬件初始化,主要是初始化 SDRAM 接口,调用 romStart()。

系统引导 Load :romStart(),执行的第一个 C 程序。完成必要的硬件初始化:sysHwInit(),把 ROM 代码和数据段拷贝并重定位到 RAM,代码段未驻留在 ROM 中,拷贝代码段和数据段,代码段是驻留在 ROM 中的,只拷贝数据段。未用的内存(RAM)清零,需要时,要进行解压缩,跳转到 sysInit()。sysHwInit()功能:硬件初始化

系统初始化: sysInit(),依赖特定系统的汇编代码模块,类似 romInit()(不处理 RAM)。处理过程: 关中断,无效 Cache,初始化处理器的寄存器,包括 C 堆栈指针,清除所有悬置的中断,跳转到 usrInit()。

用户初始化:usrInit(),VxWorks 下的第一个 C 程序。无效 Cache,BSS 段清 0,保存启动类型,调用函数 intVecBaseSet()设置中断向量表基本地址,调用 sysHwInit()初始化硬件到静止状态:设备复位,并禁止其产生中断,调用 usrKernelInit(),选择适当的初始化函数完成初始化,调用 kernelInit(),初始化多任务环境。usrKernelInit()初始化内核可选组件。KernelInit()初始化多任务环境,启动内核。

系统启动:usrRoot(),初始化 I/O 系统、驱动器、设备,启动系统。 处理过程:

Ø 内存清零:memInit (pMemPoolStart, memPoolSize); Ø 初始化 MMU 单元:usrMmuInit (); Ø 时钟设置:sysClkConnect(),sysClkRateSet(),sysClkEnable (); Ø I/O 初始化:iosInit () ,限制了最多同时打开设备数; Ø 字符设备设置:ttyDrv(),缺省为对控制台的调用; Ø 初始化结构、信号、消息等:excInit(),logInit(),sigInit() Ø 初始化管道等:pipeDrv(),stdioInit(),mathSoftInit()或 mathHardInit(); Ø 初始化 USB、SCSI、IDE、SATA、网络等设备接口; Ø 配置并初始化目标代理机:wdbConfig() Ø 启动内核

Vxwork嵌入式系统

基本启动过程

VxWorks基本启动过程

RAM 中引导 VxWorks

RAM中引导VxWorks

快速启动

通用原理 针对影响因素,逐项优化 • 具体措施 没有完全通用的流程,只能针对具体应用优化 • 硬件优化 提升处理器性能、存储容量、... → 通用,但成本? • 软件优化 优化启动运行过程!→ 代码优化;专用、延迟启动、待机、...

可信启动

可信  TCG(可信计算组织),若一个实体的行为总是以预期的方式朝着预期的目标前进,那么这个实体就是可信的 • 信任根 可信计算机系统可信的基点 • 一个可信计算平台必须包括三个信任根 可信度量根:对平台进行可信度量的基点 可信存储根:平台可信度量值的存储基点 可信报告根:平台向访问客体提供平台状态的报告基点 可信度量根核 上电后在可信度量根中第一个被启动的软件段 信任链 以信任根为基础逐级验证,最终得到一个可信启动信任链:E0→E1→E2→…→En

第五章 EOS 内核基础

• 优先级驱动  Priority Driven;任何时刻,总是将处理器分配给优先级最高的任务的机制 • 可调度性  Schedulability;一个任务的完成时间不大于截止时间(Deadline),称任务可调度;若系统所有任务可 调度,称系统可调度 • 优先级反转  Priority Inversion;高优先任务等待低优先级任务释放资源而被堵塞的情况 —— 产生死锁的原因 • 优先级继承  Priority Inheritance;优先级反转时,低优先级任务提高优先级确保继续执行以释放资源的方法

RTOS

对比项目RTOS通用 OS
体系结构整体、层次、微内核、构件化整体、层次、微内核、构件化
TCB 结构增加时间参数:周期、截止时间等名称、ID、优先级、当前状态、上下文等
任务调度静态调度表、固定优先级(RM 类)、动态优先级(EDF 类);原则上用户不能改变优先级基于优先级的调度;时间片轮转调度;系统态优先于用户态;优先级可用户改变
内存管理主要使用静态内存划分采用虚拟存储机制
中断管理多数中断处理转化为周期性查询任务;执行次序由统一考虑的优先级决定中断处理优先于任务执行
共享资源问题存在优先级逆转问题信号量机制处理互斥访问
系统开销所有系统操作的时间开销有界,需要量化系统开销基本可忽略
系统功耗需要严格管理几乎可忽略
系统可重入性系统内核可在调度点重入,实时性保证强核心态不可重入,系统执行可预测性弱
可信保障适应应用需要的等级要求没有严格要求

第六章 内核的编写 ☆

aCoral,你电团队写的一个系统,其中任务即线程 源码下载

搭建 aCoral 交叉开发环境

• 基本模块:内核、文件系统、轻型 TCP/IP、GUI、简单应用服务 网页服务器、Telent 服务、文件操作、GUI 图形、测试、...

任务管理

任务与程序的区别

• 任务能真实地描述工作内容的并发性,而程序不能 • 程序是任务的组成部分:任务还包括数据、堆栈及其上下文环境等(TCB) • 程序是静态的,任务是动态的 • 任务有生命周期:诞生 → 消亡,是短暂的;而程序相对长久永存 • 任务具有创建等功能;而程序没有

硬嵌入式实时系统的实时确保措施:实时调度算法、任务控制块(TCB)设计,前端功能集成

掌握概念:任务控制块、资源控制块、任务状态切换、任务队列

任务调度策略

• 静态调度表驱动:类似火车时刻表;静态,开销小,可预测,实时保障强;不灵活 • 基于优先权的调度 使高优先级任务优先处理;优先级可静态赋予,或动态生成。分为可抢占的调度和非抢占的调度 。 • 时间片的调度:为每个任务分配每次执行的时间片,循环执行或依某种规则执行

任务调度策略1 任务调度策略2

创建任务

需要掌握相关代码

1、分配任务空间:acoral_get_res(),资源空间分配 2、策略初始化:acoral_policy_thread_init(),选择策略,初始任务参数,调用 acoral_thread_init() 3、任务初始化:acoral_thread_init(),初始堆栈空间、任务环境(寄存器) 4、挂就绪队列:acoral_resume_thread(),按一定的规则挂入就绪队列,等待任务启动 5、启动调度:acoral_sched(),选择当前执行任务

调度任务

确定任务调度的时机:即何时何地调用调度程序 acoral_sched() • 调度点  Scheduling Point,调用调度程序的具体位置 • 主要的调度点:中断服务结束时,任务因等待资源而被阻塞(挂起)时,周期开始或周期结束时,高优先级任务达到时、时间片结束时,关调度等状态打开时,主动调度与被动调度

主动调度:当前执行任务的时间片完

被动调度:某个事件触发的调度,如周期到达、高优先级任务就绪、突发事件等等

判断是否可调度

1、调度开始标志 acoral_ start_sched  任务初始化完?2、是否需要调度标志 acoral_need_sched  当进行一些操作导致需要调度时标记 3、是否中断执行中 类似高优先级任务正执行 4、调度锁 禁止调度标识,类似关中断

如何获取最高优先级任务

排队、查找算法速度都慢,采用优先级数组(位图)

优先级数组位图调度

任务切换

当前任务挂起,高优先级任务执行

普通模式下的任务切换:切换任务

中断模式下的任务切换:旧任务先被中断保存现场,若新任务优先级更高,中断退出时切换任务

普通模式任务切换 中断模式任务切换1 中断模式任务切换2

事务机制

中断

中断处理:

(1)中断 CPU 当前执行 (2)保护被中断进程现场。 (3)分析中断原因,转去相应的中断处理程序。在多个中断请求同时发生时,处理优先级最高的中断源发出的中断请求。 (4)执行中断处理程序 (5)恢复被中断进程的现场 (6)CPU 继续执行原来被中断的进程。

中断服务程序的主要内容 保存上下文 保存中断服务程序将要使用的所有寄存器的内容,用于退出之前进行恢复现场 多设备共享中断 为确定产生该中断信号的设备,需要轮询这些设备的中断状态寄存器 具体的中断处理 恢复保存的上下文 执行中断返回指令,恢复被中断程序执行

acoral 中断

三种模式(类型)  实时中断(通用) 直接调用中断处理程序,不经过:HAL→hal_all→intr→ 中断处理程序 专家中断(专用,异常 ) 需要用户在中断处理程序中自己处理中断响应相关的操作,如清中断位等:特殊中断 普通中断 不需要任何中断硬件相关的操作,只需编写中断要做什么

acoral中断处理流程

时钟

时钟源: RTC(实时时钟,系统时基,独立供电);定时器/计数器(系统时钟)

看门狗:在嵌入式操作系统中,硬件看门狗(Watchdog Timer,WDT)是一种独立于主处理器的硬件电路模块,通过定时器机制监控主处理器的工作状态。

  • 工作原理:主处理器需定期(在定时器溢出前)向看门狗硬件发送 “喂狗” 信号(如写入特定寄存器),若因程序跑飞、死锁等故障导致未及时 “喂狗”,定时器溢出后看门狗会强制触发系统复位(如向主处理器发送复位信号)。
  • 核心作用:通过硬件层面的独立监控,确保系统在软件故障时能自动恢复,避免因异常状态导致系统长时间瘫痪或失控

喂狗:将计数值赋给 WTCNT 寄存器;关看门狗:清 WTCON 寄存器

看门狗定时器原理
时钟管理
  1. 时间过程 定时器 → 脉冲信号 → 时钟中断 → HAL层 → 内核层 → ticks处理 acoral_Ticks_entry

  2. 时间片 时钟中断 → ticks处理:任务执行时间 +1 → 时间片到? → 调度

  3. 延迟操作 任务挂起 → 延时设置 → 时钟中断 → ticks处理:延时-1 → 延时=0? → 重就绪

  4. 定时管理

内存管理

内存空间划分:代码区,静态数据区和动态数据区 堆(heap):一种链式结构;动态分配 栈(stack):一种线性结构;每个任务有私有“栈” • 静态分配:发生在编译和连接时,全局变量和静态变量;开始运行就分配,运行结束才释放 • 动态分配:发生在程序调入和执行时,局部变量和返回值等;需要时分配,使用完就释放 栈:函数的参数和返回值、局部变量、... 堆:malloc 和 free 分配/释放的内存,如指针。 内存泄漏:malloc 分配,但缺少 free 释放

RTOS 内存管理:不使用内存管理或只进行基本的内存管理,不使用虚拟存储技术,内存保护

RTOS 内存分配方案

1、一旦分配之后,不允许释放分配的内存,应用在硬实时嵌入式应用

2、使用一个最佳匹配算法,允许释放之前分配的内存块,但不合并相邻空闲块

应用对象:动态创建任务的小型实时系统;不能用在分配和释放随机字节堆栈空间的应用程序

DSA:整个内存按用户需求进行分区

3、使用 malloc()和 free()

4、使用一个最佳匹配算法,将相邻的空闲内存块合并成一个更大的块(包含一个合并算法),特别适用于移植层代码

TLSF(二级间隔表动态内存分配算法)算法思想

acoral 两级内存管理

acoral两级内存管理

第一级:改进的伙伴系统 划分要分配的内存块大小,每个内存块分配 2N 大小内存,解决内存外碎片和内碎片问题 第二级:根据第一级确定的大小进行具体物理内存分配,固定块和可变大小可选 使用方法: 应用程序  直接使用第一级管理模式 内核  可直接使用第二级管理模式

伙伴关系管理算法 ☆

伙伴关系管理算法1 伙伴关系管理算法2

每层需要三个结构:内存状态位图块 bitmap[m] [n]、空闲内存块链表数组 free_list[m] [n]、空闲内存块链表头 free_cur 指出了本层第一个空闲位图块内存状态位图块每位:0 代表无空闲,1 代表有 1 个空闲伙伴

伙伴关系管理算法3 伙伴关系管理算法4

每个基本内存块有一个控制结构 level = -1 :该基本内存块尚未分配出去 level > 0 :属于第 level 层 bitmap[m] [n]的某一位为 1:1~m-1 层,偶数块使用,level > 0;

存储初始化过程
存储初始化过程

内存回收:回收准备:状态;回收地址;... → 支持回收操作 获取基本内存块序号,依回收内存块的起始地址,获取该内存块所属层数,进入临界区进行合法性检查:地址、伙伴是否回收、已经回收、...顶层处理:回收内存,合并伙伴;不向上回收;非顶层:回收内存;判断,若伙伴未用:向上递归合并伙伴;否则不向上处理

acoral 第二级内存管理

原则:固定块和可变大小可选

固定大小内存管理

内存资源池储存管理 针对频繁使用的内存:如 TCB、ECB(事件控制块)、... 方法:事先对常用结构等分配一些固定内存块,形成资源池,以指针形式分配或回收

任意大小内存管理

需要多少分配多少。“一分为二”:将一块分为两块,一块分配给用户使用,剩下一块留作后续使用,同时改变大小标志 问题:不断调用 acoral_malloc2()会产生大量内存碎片

任务交互

任务间的协调机制:同步、互斥。资源访问的控制机制:互斥。 任务间通信机制:邮箱、消息、共享存储、管道、RPC、全局变量、.... 事件(组):用于同步 异步信号:用于同步 邮箱、消息队列或管道:用于消息通信 全局变量、共享内存、Sockets、远程过程调用:同步与通信

互斥机制

互斥量

申请

互斥量申请流程

释放

互斥量释放流程

信号量

用于基本的互斥与同步

同步机制

利用信号量实现。

通信机制

邮箱
邮箱通信机制
消息

接收

消息接收机制

接收

消息队列接收

第七章 调度算法

速率单调调度算法 RMS

假设条件:所有任务都是周期任务;任务的周期越小,优先级越高;任务之间相互独立:不进行通信,也不需要同步;不存在临界区。

实时静态优先级算法,用于周期性实时任务的调度,周期越短,优先级越高。周期任务理解为每一个周期来一个任务实例进入就绪状态。

可调度的 CPU 使用率上限为 ln2,偏低。

**系统可调度:每个任务 Ti 都可在其截止时间 Di 之前完成。**任务集 T 可调度的充分条件是:CPU 的利用率 ≤ n*(2^1/n-1),n 为任务个数。

非周期任务的处理方式:后台方式执行非周期任务;周期性地查询非周期任务

例 1
任务执行时间周期时间
T114
T215
T3110
RMS调度算法示例1

Ei 为执行时间,Pi 为周期时间。

例 2

初始时所有任务同时到达

任务执行时间周期时间
T125
T2315
T3420
RMS调度算法示例2

Ui:2/5 + 3/15 + 4/20 = 0.8

最早截止时间优先算法 EDF

假设条件:所有任务不必都是周期任务,任务的相对截止时间等于任务的周期:Di = Pi。

任务集 T 可调度的充要条件是 CPU 的利用率 ≤ 1(C1/T1)+(C2/T2) +... + (Cn/Tn) ≤ 1。理论可调度上限为 100%。

对于非周期性任务,只要每个任务的执行时间 (Ci) 满足 (Ci= Di - Ai)((Di) 为截止时间,(Ai) 为到达时间),且系统能动态响应截止时间变化,则可调度。

例 3
任务执行时间周期时间
T125
T2310
T3415
EDF调度算法示例

最低松弛度优先算法 LLF

最好的单处理器动态调度算法

松弛度=必须完成时间 − 剩余执行时间 − 当前时间

死锁

定义:一组任务中,每个任务都无限等待该组中另一任务占用的资源,而永远的不到资源的现象

死锁产生:需要满足四个条件 资源独占:每个资源只能给一个任务使用 不可抢占:资源只能由占有者自愿释放 请求与保持:每个任务请求资源,同时也占有资源 循环等待:存在一个任务对资源的等待环路

优先级反转

优先级继承

优先级继承机制

继承的缺点:当低优先级任务 A 继承高优先级任务 B 的优先级后,若任务 A 同时被另一高优先级任务 C 阻塞,系统可能因循环等待资源而陷入僵局

天花板

指控制访问临界资源的信号量的优先级天花板

优先级天花板机制

第八章 内核移植

概述

移植:将程序代码从一种运行环境转移到另一种运行环境 内核移植:将内核代码从一种硬件平台转移到另一种硬件平台上运行。将已在某一特定 CPU(或 SOC 芯片)上运行的 RTOS 内核在另一 CPU(或 SOC 芯片)上运行起来。移植工作大部分是和硬件相关,需要针对具体 CPU 或芯片进行有区别的代码编写。

为何需要移植

基本内核庞大,不符合应用需要,如 Linux。厂家只提供了一种环境的 Demo。

应用环境以前不支持某种 RTOS;从裸板开始;硬件可裁剪性:对不同应用,工程师们设计的硬件电路会有所不同,导致原代码可能无法正确运行 → 必须结合自己的硬件电路,对已有的内核代码进行修改移植。

移植的内容

简单过程:内核配置、内核编译和内核下载 通用过程:硬件抽象层 HAL 移植(针对不同目标板改写相关代码),项目移植(处理规则不一致的问题)

HAL 移植

与硬件相关的代码

• 启动:启动过程、... • 中断:中断环境保存/恢复、中断屏蔽、开/关中断、时钟中断等操作 • 任务切换:任务环境保存/恢复 • 内存:不同 CPU 支持的内存不一致,不同 RTOS 管理方式也不一致 • 驱动程序:设备的控制接口等

注意事项

规范化: • 启动文件:必须有 start 名字的启动文件,后缀随编译器等变化 • 头文件:针对可能移植的接口,需要定义两个头文件 —— 需要移植的、不必移植的 • 命名规范:对每类需要移植的接口,规范命名,如硬件相关 acoral 中采用 HAL_XXX

项目移植

项目移植的类别

同 OS 下软件项目移植;不同 OS 间软件项目移植;针对不同硬件平台的软件项目移植。 移植的基本限制:相互之间比较类似的需求/项目。

步骤

生成对应开发板的项目

• 创建一个项目环境 Proj:类似于利用 Eclipse 创建项目环境;但对许多嵌入式项目,相关的文件夹(如 include、lib、src、drivers、...)等必须手工创建 •芯片相关的文件移植:针对 S3C2410,需要将 HAL 下 S3C2410 相关文件夹移到 Proj 环境中(拷贝) • 驱动相关的文件移植:针对 S3C2410,需要将 drivers 下 S3C2410 相关文件夹移到 Proj 环境中

调整/修改项目内容

• 驱动文件的变更:保留相同外设的驱动(其中可能需要根据 CPU 的支持情况改写部分代码),增加原环境中不存在的外设驱动 • 内核文件的变更:参照前文 —— 可能需要配置相关环境文件 • 示例:基于无线网络的信息显示系统 —— 从 Intel 环境移植到 ARM 环境

编译运行内核

• 编译内核:用 Ubuntu 的 GCC 编译移植过来的 aCoral 内核,其中包含利用 aCoral 的简单工具进行相关配置 • 烧写内核:将编译好的内核烧写到目标板上。连接串口:minicom;安装烧写工具:DNW;烧写与运行 aCoral