GEC架构下RTOS对外接口函数重映射机制①

2020-03-22 07:42刘长勇王宜怀孙亚军
计算机系统应用 2020年8期
关键词:调用应用程序定义

刘长勇,王宜怀,孙亚军

1(武夷学院 数学与计算机学院,武夷山 354300)

2(苏州大学 计算机科学与技术学院,苏州 215006)

3(认知计算与智能信息处理福建省高校重点实验室,武夷山 354300)

为了提升编程颗粒度、提高可移植性,借鉴通用计算机的概念与做法,把基本输入输出系统(Basic Input and Output System,BIOS)与用户程序分离开来,实现彻底的工作分工,形成了通用嵌入式计算机(General Embedded Computer,GEC)[1].GEC 架构将嵌入式软件系统分为BIOS 工程程序(简称BIOS)和USER 工程程序(简称USER)两部分,BIOS 先于USER 固化于微控制器(Microcontroller Unit,MCU)内的非易失存储器(如Flash)中,为实时操作系统(Real-Time Operating System,RTOS)的驻留提供了空间.实时操作系统能提供精确的实时控制和任务管理功能,保证系统的实时性需求[2].通过将RTOS 驻留在BIOS 中,降低用户的编程难度、简化程序的串口写入以及方便用户调用,同时也可以很好地帮助用户解决因RTOS 在不同开发环境的编译困难而造成的烦恼.

同时,为了充分发挥RTOS的功能,方便用户使用,提高用户程序的可移植性,通过提供对外函数接口的形式是一种比较好的做法.对外函数接口(也称为应用程序编程接口,API)是软件库提供的一组可访问的接口,软件库通过API 向外提供服务,开发人员通过使用API 实现代码复用,提高生产效率[3].因此,在对外函数接口设计上,要充分考虑其可用性[4,5]、稳定性[6]和安全性[7,8].目前,对外函数接口的研究已取了一定的研究成果,主要集中在API 使用规约[9–11]、API 推荐研究[12,13]、API 文档研究[14,15]、API 组合模式的应用[16]等方面,但有关RTOS的驻留及其对外函数接口研究方面文献较少.为此,本文首先给出通用嵌入式计算机架构下RTOS的BIOS 驻留方法,剖析了RTOS 对外函数接口设计方法,提出了接口函数重映射机制,最后在mbedOS 下进行应用实践.实践表明,将RTOS 驻留在BIOS 中,能有效地节省用户程序的编译时间,同时通过对外接口函数的重映射,能有效地提升了应用程序的可靠性性和开发效率,易于用户调用,也使应用程序易于复用,为嵌入式人工智能与物联网终端程序的开发提供了技术基础.

1 RTOS的BIOS 驻留方法简介

在GEC 架构中,虽然嵌入式软件系统分为BIOS和USER 两部分,但最终程序代码和各种变量数据都是放在同一个MCU的Flash和RAM 中,要将RTOS 驻留在BIOS 中,实现RTOS与应用程序的物理隔离,就必须对MCU的Flash和RAM 空间进行合理的划分,这样才能确保代码不重叠,变量使用不越界,从而保证RTOS 能得到正常运行,而又不影响USER的执行.因此,要考虑RTOS 驻留的硬件载体,即MCU的Flash和RAM 空间大小的因素.对Flash 空间的划分可采用分割独享方式,一部分给BIOS 程序使用,另一部分给USER 程序使用,两者使用的空间不重叠.对RAM 空间的划分则需要考虑MCU的RAM 空间大小,当RAM空间足够大时,可采用分割独享方式,BIOS和USER 各单独使用不重叠的空间;当RAM 空间较小时,可采用重叠共享方式,即BIOS 使用的空间和USER 使用的空间部分重叠共享,这样可以提高RAM 空间的利用率.在实现RTOS 驻留的过程中,还需要考虑如何合理划分Flash 空间,使USER 程序占用的空间尽量大;重叠共享方式分配RAM 空间时,如何避免出现数据越界与冲突;RTOS的调度会依赖于系统服务调用,何时将这些调用权移交给RTOS 等问题.

2 RTOS 对外函数接口设计方法

虽然RTOS 已驻留在BIOS 中,但要发挥其作用,还需将RTOS的功能函数设计成对外函数接口表,然后通过映射形成对外函数映射表,这样才能向USER 提供服务.也就是说,USER 可以通过对外函数映射表实现对RTOS 提供的接口函数的调用.

2.1 设计RTOS 对外函数接口的必要性

在GEC 架构下,将RTOS 提供的函数进行对外接口的设计,不仅能够发挥RTOS的功能,而且还能方便用户使用,提高USER 程序的可复用性.因此,RTOS 向用户提供接口函数是非常必要的.

(1)提高应用程序的可复用性.由于USER是通过对外函数映射表实现对RTOS 提供的对外接口函数调用的.因此,当在BIOS 中驻留不同的RTOS 时,只要向USER 提供相同功能的接口就可以,即使这些接口的名称发生的改变,也不会影响USER的调用,USER 程序不需要修改,提高了USER 程序的可复用性.

(2)提升应用程序的稳定性和可靠性.由于RTOS已经驻留在BIOS 中,它所提供的对外函数功能已经在BIOS 中通过编译、测试和验证,变成了一段可靠的、稳定的机器码.因此,在USER 程序中可以放心地调用RTOS 提供的对外函数,不用担心会出现的代码错误,从而提升了应用程序的稳定性和可靠性.

(3)缩短应用程序的开发时间.由于RTOS 提供了原型级的对外函数调用接口,用户可以直接使用,无需花大量精力深入理解RTOS的工作原理和调度机制,不需要知道具体的实现细节,只需关注用户程序的编写,大大地提高了开发效率.

(4)方便应用程序调用.由于RTOS 提供的对外函数已经变成了机器码驻留于BIOS 内,用户难以调用,通过对这些函数进行重映射,最终向USER 提供函数调用原型接口,用户就可以像调用普通函数一样方便使用这些函数.

2.2 RTOS 对外函数接口机制

要实现RTOS 对外函数接口,首先需要在BIOS中对函数进行重定义、声明、注册,形成对外函数接口表;其次要在USER 中通过映射获取对外函数接口表的入口地址,形成对外函数映射表,并重定向函数名称,最后在USER 中实现对函数的调用,其过程如图1所示.

图1 对外函数接口的设计与实现过程示意图

(1)对外函数的二次封装

对外函数不仅可以包含RTOS的功能函数,而且还可以包括各类构件函数,本文主要介绍如何封装RTOS提供的对外接口函数.RTOS 一般都具备线程管理、同步与通信、中断管理等基本功能,相应的提供了线程类、事件类及操作系统启动函数等,在这些类中提供了大量的成员函数,都是采用C++实现的.由于这些成员函数的执行依赖于类对象的创建及其成员变量,而不是使用绝对地址的方式来实现对类中的某个成员函数的调用.因此,必须在BIOS 程序中对这些函数进行重定义,二次封装成C 语言可以调用的函数形式,这样才能实现在USER 中调用它们.对外函数的二次封装(或称重定义)主要包括函数名、函数的返回值类型、函数的参数、函数体以及为了便于理解程序而加入的功能说明和代码注释等.其格式如下:

格式:void 重定义函数名(参数表列)

例如,mbedOS的延时函数名为Thread::wait,通过二次封装重定义为thread_wait.

(2)对外函数的声明

对外函数重定义好之后,一般应在与之同名的.h头文件中进行声明,函数的声明要给出函数名、函数的返回值类型、函数的参数以及函数的功能说明,即使用者通过函数的声明就能了解函数的功能和使用方法,而不需要查看函数的具体实现.

格式:void 重定义函数名(参数表列);

(3)对外函数的注册

当对外函数定义和声明之后,还要对函数进行注册才能形成对外函数接口表.借鉴中断向量表的定义做法,可以给所有的或部分的函数编号,并将函数名(即函数的入口地址)集中在一起按编号有序地放在一个统一的区域中,形成对外函数接口表.在对外函数接口表中,对外接口函数的入口地址用32 位的二进制表示,可以看作和定义成long 类型的数据,一般采用汇编语言编写一个SVC 中断来注册.对外函数接口表采用数组(如BIOS_API)存储,其入口地址就是数组名或数组的首地址,函数的编号与数组的下标元素的序号一一对应,其中,0 号表示对外函数的数量,1 号函数对应BIOS_API[1],2 号函数对应BIOS_API[2],依此类推,换句话说,可以通过数组元素来访问这些对外函数.同时,为了便于扩充或更新对外函数的个数,还预留了一些缺省的函数名(如DefaultFUN).

3 接口函数重映射机制

当RTOS 提供的对外函数经过重定义、声明、注册,形成对外函数接口表后,USER 程序还需进一步通过重映射机制形成对外函数映射表,才能最后在USER中实现对函数的调用.

3.1 对外函数接口表的映射

当RTOS的对外函数接口表形成之后,此时RTOS提供的函数已经变成了一段机器码,必须先将BIOS的对外函数接口表映射成USER的对外函数映射表,获得存放对外函数接口表的数组首地址,这样USER 程序才能使用它.为了与BIOS_API 数组的元素一一对应,USER 程序的对外函数映射表也采用数组(如USER_API),用它来存放对外函数接口表的地址.这样,当USER 使用USER_API 时就相当于使用BIOS_API,也就是说,USER 通过USER_API 就可以访问BIOS 提供的对外函数.

在USER 中,采用SVC 中断的方式来实现对外函数接口表的映射.因此,在BIOS 中先要将SVC 中断重定向为用户的SVC_IRQ,接着在USER 中调用svc1_init函数触发BIOS 中的SVC_IRQ 中断,然后由SVC_IRQ中断触发实际的SVC 封装函数SVC_HandlerS,最后在这个汇编程序SVC_HandlerS 中实现将BIOS 提供的对外函数接口表的入口地址映射到对外函数映射表中,汇编函数SVC_HandlerS 实现流程如图2所示.

3.2 对外函数的重定向

当对外函数映射表形成之后,此时USER 就可以通过USER_API 数组访问函数,如USER_API[1]访问的是1 号对外函数.但采用USER_API[i]这种形式对具体要访问的对外函数的类型、函数名、参数以及功能等不够清晰明了.因此,类似中断向量重定向的做法,也可以重定向对外函数,重新给USER_API[i]取另外一个用户熟悉的函数名,这个函数名可以与对外函数名同名,也可以是不同名的,这样就可以为用户提供函数原型级接口,易于用户记住和使用,图3描述了从RTOS的原型函数到最终实现用户实际调用函数的映射关系.函数重定向宏定义的一般形式如下:

图2 汇编函数SVC_HandlerS 实现流程

图3 对外函数映射关系示意图

#define 函数重定向名 ((对外函数声明指针表达形式)(全局数组[对外函数编号]))

例如:

#define delay ((void (*)(uint_32 millisec))(USER_API[4]))

3.3 对外函数的调用

当对外函数重定向之后,就可以利用重定向后的名字来调用函数.例如,当USER 调用delay 函数时,实际上是指向了USER_API[4],而USER_API[4]对应BIOS_API[4],BIOS_API[4]存放的是thread_wait 函数的入口地址,而thread_wait 函数实际上就是Thread::wait 函数.因此,可以认为USER 通过调用delay 函数达到调用Thread::wait 函数的目的.

4 mbedOS 下的应用实践

2014 年ARM 公司推出了mbedOS,它是一种专为物联网 (IoT)中的“物体”设计的开源嵌入式实时操作系统[17].本文选用mbedOS 进行应用实践,测试工程在Kinetis Design Studio 3.0.0 IDE 集成开发环境和金葫芦AHL-A 系列Cortex-M0+内核的KL36 微控制器[18](即AHL-AN100VL 型号开发板)上进行.KL36 片内Flash大小为64 KB,一般用来存放中断向量、程序代码、常数等;片内RAM为静态随机存储器SRAM,大小为8 KB,一般用来存储全局变量、静态变量、临时变量(堆栈空间)等.

4.1 mbedOS 提供的对外接口函数

使用KL36 微控制器作为mbedOS 驻留的硬件载体,考虑其Flash和RAM 空间大小的因素,在mbedOS驻留于BIOS 时,对Flash 空间采用分割独享方式划分.对RAM 空间可采用分割独享和重叠共享方式划分,如图4所示,在分割独享方式中BIOS和USER 各占一半的RAM 空间;本文采用重叠共享方式,BIOS 占全部RAM 空间,USER 占一半以上的RAM 空间,这样可以最大程度地提高RAM 空间的利用率.根据前面介绍的RTOS 对外函数接口设计方法和重映射机制,可以将mbedOS 提供的启动、线程、延时、事件、消息队列、信号量和互斥量等函数进行重定义、声明、注册、映射、重定向,最后提供给用户程序调用.mbedOS提供的对外函数原型名称、对外函数二次封装名称以及重定向函数名称之间的映射关系如表1所示,仅列举了本测试工程中使用到的对外接口函数.

图4 RAM 空间划分示意图

表1 部分对外函数重定向一览表

4.2 功能性测试

测试工程的功能是创建两个任务,实现每2 秒红灯闪烁一次,蓝灯任务每1 秒切换亮暗一次,绿灯任务当收到蓝灯任务的信号(17)时,切换绿灯亮暗.当芯片上电之后,首先启动BIOS,接着转到USER的启动,在USER的启动过程中通过映射对外函数接口表形成对外函数映射表,并重定向对外函数.然后启动mbedOS,并创建和启动蓝灯任务和绿灯任务,最后在一个无限循环中使红灯每2 s 闪烁一次,同时对蓝灯任务和绿灯任务进行调度.蓝灯任务主要完成每秒闪烁一次,并设置信号;绿灯任务主要是等待信号,当收到信号后闪烁一次.测试工程的执行流程如图5所示.

在测试工程中主要调用的对外函数有:操作系统启动函数OsStart、任务创建函数create、任务启动函数start、延时函数delay、信号设置函数signal_set和信号等待函数signal_wait 等,其功能性测试结果如图6所示,从中可以看出能精准调用这些对外函数,程序的功能得到准确的实现,说明对外函数接口设计正确.

4.3 编译时间测试

编译时间的测试是在联想笔记本电脑K49 上进行,其CPU 型号为Intel Core i7-3520M,主频2.9 GHz,内存8 GB,采用64 位的Windows 7 操作系统.测试工程针对KL36 (采用Kinetis Design Studio 3.0.0 IDE 编译环境)、S32K144 (采用S32 Design Studio for ARM v1.3 编译环境)和MSP432 (采用Code Composer Studio 6.2.0 编译环境)微控制器分别对mbedOS是否驻留BIOS的USER 程序进行编译时间测试,测试结果如表2所示.从表2中可以看出,将mbedOS 驻留在BIOS 中,USER 程序可以节约2~3 倍的编译时间,从而提高了用户程序的开发效率.

图5 测试工程执行流程

图6 功能性测试结果

表2 驻留与非驻留时USER 程序编译时间

5 结论与展望

为充分发挥实时操作系统的强大功能,本文给出了RTOS 在BIOS 中的驻留方法,在GEC 架构下提出了RTOS 对外接口函数的设计方法,剖析了接口函数重映射机制,为用户提供函数原型级的调用接口.最后以NXP的KL36 芯片为例,在mbedOS 进行应用实践,测试表明对外函数接口的设计是正确的,有效地解决了函数调用的困难,提高用户程序的可靠性,为RTOS的应用研究提供了基础.后续还将进一步探索用户程序在不同RTOS 上的可移植性问题,本文涉及到的测试工程可到苏州大学嵌入式学习社区网站(网址:http://sumcu.suda.edu.cn)的“教学培训-教学资料-mbedOS”位置,下载“SD_mbedOS_API”查看.

猜你喜欢
调用应用程序定义
以爱之名,定义成长
严昊:不定义终点 一直在路上
定义“风格”
删除Win10中自带的应用程序
谷歌禁止加密货币应用程序
基于Android Broadcast的短信安全监听系统的设计和实现
利用RFC技术实现SAP系统接口通信
三星电子将开设应用程序下载商店
微软软件商店开始接受应用程序
C++语言中函数参数传递方式剖析