引言
从20世纪80年代,国际已经有一些IT组织和公司开始进行商用嵌入式实时操作系统和专业实时操作系统的研究。软件实现的实时操作系统,国外有VxWorks、LynxOS、嵌入式Linux、TRON和μC/OSII。
国外的研究目前主要集中在硬件操作系统的局部模块,基于整体的硬件实时操作系统设计和实现方面的研究比较少,而实时操作系统的各个模块之间有着复杂的信息交互和联系。因此,实时操作系统的最优软硬件划分以及实现一个硬件实时操作系统IP核值得深入研究。
国内的软件实时操作系统主要有两类:一类是中国自主研发的实时操作系统,比如开源的RTThread、电子科大和科银公司开发的Delta OS等;另一类是基于国外操作系统二次开发,比如中科红旗Linux、深圳蓝点Linux。
但是国内目前的研究集中在任务调度和中断处理的硬件化上面,任务间的通信和同步还有待研究。
鉴于国内和国外的研究现状,硬件实时操作系统只是实现了实时操作系统的一部分,这里设计的硬件实时操作系统,可以替代传统的小型嵌入式实时操作系统,比如μC/OS、RTX、FreeRTOS等。
1 技术方案
硬件实时操作系统是在ARM+FPGA的平台上实现的,利用ARM的FSMC总线接口实现ARM和FPGA的连接,可以认为FPGA就是挂在总线上的一个外设,用寄存器的方式配置硬件实时操作系统:在FPGA上实现抢占式调度器,以及基于此调度器的任务管理、信号量、消息邮箱、消息队列、互斥信号量、事件标志组。在ARM上配置寄存器,执行任务以及实现任务的上下文切换。这样基本已经完成一个小型嵌入式实时操作系统所需的所有组件。
硬件实时操作系统的基本配置是:同时支持创建8个任务、8个信号量、8个消息邮箱、8个消息队列、8个互斥信号量、8个事件标志组,而想要支持更多的组件和任务,只需在FPGA上做扩展。图1是硬件实时操作系统的状态切换图,图2是硬件实时操作系统的主体框图。
图1 硬件实时操作系统状态切换图
图2 硬件实时操作系统主体框图
1.1 抢占式调度器
实现抢占式调度器要抓住3个关键点:
① 当一个任务提交信号量,发送消息给一个高优先级的任务时,当前的任务就会被停止,去执行高优先级的任务;
② 每个时钟节拍中断,如果有高优先级的任务就绪,则高优先级任务会抢占低优先级的任务;
③ 当ISR提交信号量或发送消息给一个更高优先级的任务,中断返回时,不会返回到当前任务,而是返回到高优先级任务。
FPGA实现抢占式调度器的一个核心工作就是快速从任务就绪列表里查找到需要执行的最高优先级任务,这里采用优先级编码器来实现,方法略——编者注。
这里要特别注意一点,空闲任务是永远就绪的,其优先级最低,没有其他任务执行时,就执行空闲任务。
针对此硬件实时操作系统,ARM上只需做好以下两点:
① 任务级任务切换,主要是实现高优先级向低优先级的任务切换;
② 中断级任务切换,在中断退出的时候判断是否有更高优先级的任务就绪,如果有,就切换到高优先级任务。
1.2 任务管理
任务管理部分主要实现任务的延时时间设置、任务挂起、任务恢复3个功能。对寄存器的描述略——编者注。
在FPGA部分通过设置Task_REG8 = 1可启动任务管理,这里每个任务在FPGA上的实现都是一个单独的进程,有助于充分发挥硬件实时操作系统的性能,而不是将所有的任务放到一个进程里实现。
ARM部分只需简单地设置寄存器,就可完成对任务的设置。配置了任务寄存器以后,FPGA上相应的任务管理就会按照配置方式执行,ARM端读取HW_REG3寄存器就可以得到当前需要执行的最高优先级任务。
① 任务挂起,也就是将任务从就绪列表中删除
Task_REG3 = 0;//设置任务0
Task_REG2= 0xffff;//将任务挂起
② 任务恢复,也就是将任务加到就绪列表中
Task_REG3 = 0;//设置任务0
Task_REG2 = 0;//任务恢复
1.3 信号量
信号量是为了给共享资源建立一个标志,该标志表示该信号量共享资源的占用情况。寄存器描述略——编者注。
在FPGA信号量的实现中,硬件实时操作系统除了提供信号量所需的调度功能外,还提供信号量等待列表中最高优先级任务的查找,采用优先级编码器实现,ARM端读取寄存器Sem_REG4得到等待列表中需要执行的最高优先级任务。
ARM部分主要提供以下3个函数,用于信号量寄存器的初始化和实现:
void OSSemCreate(uint16_t ucSemID, uint16_t uiSemCnt);
//此函数用于初始化信号量
void OSSemPost(uint16_t ucSemID);//此函数用于释放信号量
1.4 消息邮箱
消息邮箱主要用于两个任务间消息的传递。寄存器描述略——编者注。
在FPGA部分消息邮箱的实现中,硬件实时系统除了提供消息邮箱所需的调度功能外,还提供消息邮箱等待列表中最高优先级任务的查找,采用优先级编码器实现,ARM端读取寄存器Mbox _REG7得到等待列表中需要执行的最高优先级任务。
ARM部分主要提供以下3个函数,用于消息邮箱寄存器的初始化和实现:
void OSMboxCreate(uint16_t ucMboxID);
//此函数用于初始化信号量,用于创建消息邮箱
void *OSMboxPend(uint16_t uiMboxID,uint16_t uiMboxTime, uint16_t uiPendTaskID);//此函数用于请求消息邮箱
OSMboxPost(uint16_t uiMboxID, void*Pmsg);//此函数用于发送消息
1.5 消息队列
消息队列的实现方法类似于消息邮箱,只不过对于消息队列需要做一个环形队列,用于消息的FIFO或LIFO,这里的环形队列没有在FPGA上实现,用软件实现会更加灵活一些,寄存器描述略——编者注。
在FPGA部分消息队列的实现中,硬件实时系统除了提供消息队列所需的调度功能外,还提供消息队列等待列表中最高优先级任务的查找,采用优先级编码器实现,ARM端读取寄存器Q_REG6得到等待列表中需要执行的最高优先级任务。
ARM部分主要提供以下3个函数,用于消息队列寄存器的初始化和实现:
void OSQCreate (void **start, uint16_t uiSize, uint16_t uiQueueID);//用于创建消息队列
void *OSQPend(uint16_t uiQID,uint16_t uiQTime, uint16_t uiPendTaskID);//用于请求消息队列
uint8_t OSQPost(uint16_t uiQID, void*Pmsg);//用于发送消息
1.6 事件标志组
在实际的应用中,常常需要根据多个信号量组合作用的结果来决定任务的运行方式,为此提供了事件标志组。寄存器描述略——编者注。
在FPGA部分事件标志组的实现中,硬件实时系统除了提供事件标志组所需的调度功能外,还提供事件标志组等待列表中最高优先级任务的查找,采用优先级编码器实现,ARM端读取寄存器Flag_REG1得到等待列表中需要执行的最高优先级任务。
ARM部分主要提供以下3个函数,用于事件标志组寄存器的初始化和实现:
void OSFlagCreate(uint16_t ucFlagID);//此函数用于初始化事件标志组
void OSFlagPend(uint16_t uiFlagID,uint16_t uiFlagTime, uint16_t uiPendTaskID, uint16_t uiFlag);//此函数用于请求事件标志
void OSFlagPost(uint16_t uiFlagID, uint16_t uiFlag);//此函数用于发送事件标志
1.7 互斥信号量
当低优先级的任务占有互斥信号量时,恰好此时高优先级的任务要使用这个资源,那么硬件实时操作系统会提升低优先级任务的优先级,防止发生优先级翻转。寄存器描述略——编者注。
在FPGA部分互斥信号量的实现中,硬件实时系统除了提供互斥信号量所需的调度功能外,还提供互斥信号量等待列表中最高优先级任务的查找,采用优先级编码器实现,ARM端读取寄存器Mutex_REG8得到等待列表中需要执行的最高优先级任务。
ARM部分主要提供以下3个函数,用于互斥信号量寄存器的初始化和实现:
void OSMutexCreate(uint16_t uiMutexID, uint8_t uNewPrioty);//此函数用于初始化互斥信号量
void OSMutexPend(uint16_t uiMutexID, uint16_t uiMutexTime, uint16_t ucPendTaskID);//此函数用于请求信号量
void OSMutexPost(uint16_t uiMutexID);//此函数用于释放信号量
2 技术实施方式
系统硬件平台选用的是ARM+FPGA的方案,ARM采用的是ST公司STM32F103VET6,FPGA采用的是Altera公司的EP4CE6E22C8。
2.1 ARM和FPGA的FSMC通信
ARM和FPGA的硬件连接采用FSMC(Flexible Static Memory Controller)总线,如图3所示。
图3 FPGA和ARM硬件连接图
FSMC支持多种存储器的连接,比如SRAM、NAND Flash、NOR Flash和PSRAM,其与FPGA的通信采用类似SRAM的通信时序。
FPGA读和写操作程序略——编者注。
结合STM32手册中写操作的时序图,FPGA端在片选信号NEx为低电平,读信号NOE和写信号NWE也是低电平的情况下完成对FPGA中数据的读操作。这里采用类似串行通信的方法,设置每个ID号可以访问8个16位的数据空间。举例说明略——编者注。
2.2 系统时钟节拍中断
调度器的时钟节拍是由FPGA产生的,每ms产生一次,ARM接收到FPGA发出的外部中断信号以后,从外部中断服务程序中读取当前需要执行的最高优先级任务。
2.3 硬件实时操作系统初始化和配置
系统开始多任务以前,配置好每个任务的优先级和堆栈空间,并配置好启动任务。开始执行任务寄存器初始化、信号量寄存器初始化、邮箱寄存器初始化、消息队列寄存器初始化,过程略——编者注。
2.4 任务程序设计、任务间同步和通信程序设计
① 任务的程序设计与小型嵌入式实时操作系统是一样的,需要设计成死循环,在合适的地方加入任务的切换,防止阻塞低优先级任务的执行。
static void AppTaskLEDb(void *p_arg){
while(1){
_Task_1();
OSTaskSw(0, 300);
//延时300ms,并切换到别的任务执行
}
}
中断级的任务切换在CortexM3内核上同任务级的任务切换函数是一样的。
② 任务间的同步和通信机制在使用上与普通的小型嵌入式实时操作系统相同,以信号量为例:
OSSemCreate(8, 1);//创建二值信号量
OS_SemPend(SemID, 0xffff, Task_ID);//添加用户程序
OS_SemPost(SemID);
3 硬件实时操作系统性能测试
为了说明此硬件实时操作系统的性能,这里与μC/OSII、μC/OSIII、FreeRTOS、RTX以及embOS五个小型嵌入式实时操作系统做了对比,测试条件如下:①STM32F103VET6,CortexM3内核,72 MHz;
②软件用MDK4.54,1级优化,运行相同的任务;
③大部分测试都是测10 000次,2 ms测试一次,然后求平均值。
鉴于这些RTOS在使用上还是有些诧异的,不可能统一测试条件,这里尽量保证在同一条件下测试。测试结果如表1所列。
结语
通过测试,可以发现HWOS在某些方面相对于其他的RTOS表现不错,但有些方面还有待改进。测试时曾用这个硬件实时操作系统提供的内核服务,成功运行了UCGUI的多任务,说明HWOS具有较高的实用价值。
表1 5种RTOS测试结果