APP下载

面向ARM Cortex-M系列MCU的RT-Thread驻留方法

2022-02-21许明宇王宜怀

现代电子技术 2022年4期
关键词:小灯线程嵌入式

许明宇,王宜怀,汪 恒

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

0 引言

RT-Thread是上海睿赛德公司于2006年开始发布的一款面向嵌入式人工智能与物联网国产实时操作系统(Real Time Operating System,RTOS),具有自主知识产权。基于优先级、可抢占的调度算法,该系统服务包括线程管理、实时调度管理、中断管理和系统时钟管理等,已在国内逐步推广应用。

基于微控制器进行RTOS应用程序开发时,操作系统内核源程序与用户程序作为一个整体进行编译、链接生成机器码,具有编译时间较长、功能分割模糊、程序调试不便等缺点。若能实现RTOS的机器码与用户程序的物理隔离、有机连接并先后下载到FLASH中,则可以缩短应用开发编译时间,降低编程难度,方便用户程序的调试。已有学者进行了初步探索,文献[4-5]在PC机上实现了XP系统在EPROM中固化;文献[6]在VxWorks653操作系统下实现了一种分区启动的方案。但对于嵌入式实时操作系统的驻留方法研究少见报道。RTOS的驻留可以实现RTOS与应用程序的物理隔离,对降低RTOS下应用开发门槛十分有益,可以有效降低嵌入式人工智能与物联网终端的开发难度。

要实现某一种实时操作系统在一类微控制器芯片上的驻留,首先要将该实时操作系统移植到相应的芯片上。关于实时操作系统的移植方法已有较多的文献可供借鉴,文献[7]基于Cortex-M3内核的STM32F103移植了µC/OS-Ⅱ,并设计实现了蛇形机器人。文献[8]将mbed OS移植到Cortex M0+内核的MKL36Z64VLH4以及Cortex M4内核的MSP432上。此外,文献[9]实现了µC/OS-Ⅲ的移植,文献[10]实现了MQX的移植。

ARM Cortex-M是安谋公司推出的面向微控制器领域的微处理器,被广泛应用于嵌入式系统领域。本文以ARM Cortex-M系列的STM32L431微控制器为蓝本研究RT-Thread的驻留方法。

为了增加普适性,本文研究基于通用嵌入式计算机(General Embeded Computer,GEC)架构,把RT-Thread驻留于基本输入/输出系统(Basic Input/Output System,BIOS)中,实现BIOS与User程序的物理隔离。首先给出通用嵌入式计算机架构简介;然后给出在GEC架构下将RT-Thread驻留在BIOS中的方法,主要包括存储区域的分割、BIOS到User的衔接以及操作系统服务接口映射机制等;最后给出实践样例,检验该方法的可行性。

1 通用嵌入式计算机架构

为了提高嵌入式应用的编程颗粒度并提高可移植性,借鉴通用计算机的概念与做法,将基本输入输出系统(BIOS)与用户程序(User)分离,构建出通用嵌入式计算机(GEC),如图1所示,为实现RT-Thread的驻留提供技术基础。在硬件方面,通用嵌入式计算机由MCU硬件最小系统及其功能组件构成;在软件方面,其软件由BIOS与User两个部分构成,类似于通用计算机。本文以此为基础进行RT-Thread驻留方法研究,将RTThread包含在BIOS内,以提高其可移植性和用户程序的可复用性。

图1 GEC架构

1.1 BIOS功能概述

BIOS是先于User固化在MCU中的一段程序,主要包括硬件抽象层、设备描述、RT-Thread内核和API调用接口。

硬件抽象层将GPIO、UART、SPI等抽象成与硬件无关的驱动构件供设备描述。

设备描述是在硬件驱动构件的基础上,对具体开发板上的小灯、传感器等设备进行功能描述,形成对应的设备驱动构件。

RT-Thread内核即驻留的操作系统,包含内存管理、线程管理、同步与互斥等操作系统服务。

API调用接口将硬件驱动构件、设备驱动构件和操作系统服务的实现隐藏起来,将其以接口的形式供User程序调用。

1.2 User功能概述

User程序主要包括设备描述、软件构件和用户程序。设备描述是对未在BIOS中进行描述的设备进行补充,通过API调用接口调用硬件驱动构件来实现。软件构件是与硬件无关的C库函数,比如整数转字符串。用户程序即最终实现的嵌入式应用,主要通过调用软件构件、设备驱动构件以及通过API调用接口调用BIOS中的操作系统服务、设备驱动构件和硬件驱动构件来实现。

1.3 GEC架构启动流程

在GEC架构下,芯片上电后先运行BIOS程序,然后由BIOS跳转到User程序运行。BIOS程序从Reset_Handler开始运行,首先将全局变量拷贝到RAM中并初始化,然后初始化系统时钟,接着进入BIOS的main函数进行外设模块初始化,最后跳转到User程序。User程序也从Reset_Handler开始运行,User的Reset_Handler先将API表的地址赋值给一个全局函数指针数组(初始化API向量表),然后进入User的main函数,最后在main函数中启动RT-Thread。GEC架构启动流程如图2所示。

图2 GEC架构启动流程

2 RT-Thread驻留于BIOS内的基本方法

要实现RT-Thread在GEC架构下的驻留,需要对存储空间进行合理划分,并设计符合软件工程的可复用、可移植的接口函数。

2.1 存储空间划分

ARM Cortex-M系列的微控制器使用的是哈佛结构,代码和数据使用2个不同的存储器,分别为FLASH和RAM。FLASH中存放代码、常量和默认的中断向量表,RAM中存放全局变量、静态变量和局部变量。要实现RT-Thread的驻留,需要合理划分BIOS和User的存储空间,使其代码不重叠,变量不冲突。

2.1.1 FLASH空间划分

在非GEC框架下,MCU的FLASH空间通常划分为中断向量表段(.vector)、代码段(.text)和常量段(.rodata)三段。中断向量表段存放中断处理程序的入口地址,代码段存放程序的机器码,常量段存放程序中使用到的常量数据。GEC框架中将FLASH划分为BIOS和User两部分,User部分按上述的三段式划分,BIOS部分则在三段式基础上又切分出API向量表段,用来存放向User提供的接口函数地址,也就是七段式划分。BIOS部分的FLASH按紧凑原则分配,即需要多少就分配多少空间,这样可以尽可能多地把空间留给User,从而装入更大空间需求的应用层程序,实现更多的应用层功能。FLASH空间的划分如图3所示,括号内是以STM32L431RC芯片为例划分地址的示例。

图3 FLASH空间划分

BIOS程序的FLASH空间应遵循紧凑原则,避免分配过大或过小,过大会导致FLASH空间浪费甚至牺牲User程序功能来满足程序的需要,过小会使得程序编译不通过。

2.1.2 RAM空间划分

RAM也需要划分成BIOS和User两部分,一般来说,它们都由已初始化的全局静态变量数据段(data段)、未初始化的全局静态变量数据段(bss段)、堆空间(heap段)和栈空间(stack段)组成。由于RT-Thread使用静态全局变量定义了操作系统的线程堆空间,这一部分占用了BIOS的bss段,所以BIOS的RAM需要划分足够大的空间供线程的创建。因为BIOS占用了较大的RAM空间导致User可用空间减少,因此在资源紧凑的MCU上考虑使用共享栈分配方式对RAM进行划分,即BIOS和User使用相同的栈空间但其他部分不共享,如图4所示,起始地址和结束地址后括号内的数表示STM32L431RC芯片的RAM地址分配。

图4 RAM共享栈分配方式

由于BIOS和User使用共享栈空间进行RAM分配,所以User实际的RAM空间是与BIOS的堆和栈重叠的。BIOS中的功能应尽可能少地使用new或malloc申请空间,避免数据冲入User的data段和bss段。此外,由于RT-Thread的线程堆定义在BIOS的bss段,所以需要给BIOS分配较多的RAM空间。

2.2 API向量表

合理划分存储空间后,RT-Thread就可以驻留在BIOS中,但要在User中使用操作系统提供的内存管理、线程管理等功能,还需要获得对应功能的函数地址。为此,在BIOS中设计了API向量表来登记接口函数的入口地址并固化在FLASH的指定地址,User通过读取该地址获取API向量表。生成API向量表主要包括接口函数定义、接口函数声明和接口函数登记三部分。

1)接口函数定义。该方式与一般的函数没有区别,主要包含函数名、返回值类型、参数和函数体等,并且除了RT-Thread相关的函数外还可以包含各类硬件驱动构件函数和软件构件函数。

2)接口函数声明。接口函数定义完成之后,需要在头文件中声明该函数,通常头文件名称与其所在源文件同名。函数声明需要给出改接口的函数名、返回值、参数和函数功能说明,从而提高代码可读性和可维护性。

3)接口函数登记。接口函数完成定义和声明后,需要将其入口地址登记到API向量表中。登记的方法借鉴中断向量表的定义,对所有的接口函数进行编号,并将函数名按编号有序地存放在指定区域中,这个区域就是API向量表。API向量表通常使用数组来表示(如BIOS_API),接口函数的编号与数组的下标一致,即0号函 数 对 应BIOS_API[0],1号 对 应BIOS_API[1],以 此类推。

2.3 User获取接口函数

在BIOS跳转到User程序运行后,需要获取API向量表首地址并对其记录的接口函数地址进行重映射后,才能调用BIOS提供的操作系统服务接口。

2.3.1 获取API向量表首地址

API向量表首地址以宏定义的形式在User程序中给出,当BIOS程序跳转到User程序后,会在User的Reset_Handler中将宏定义的值赋值给一个全局函数指针数值变量,从而实现获取BIOS中API向量表的地址。

2.3.2 接口函数重映射

获取到API向量表后,还不能直接调用API,因为表中的每一条记录都只是一个函数地址,并没有与之对应的返回值和参数类型信息,因此需要对这些地址记录进行重映射。重映射使用宏定义的方式将地址记录映射成函数指针,并且函数指针的参数和返回值类型必须与登记的相同,从而保证程序调用时的正确性。表1给出了部分RT-Thread的系统服务接口函数的重映射,重映射形式如下:

表1 部分对外接口函数重定向表

格式:

#define函数名((接口函数指针表达形式)(API向量表数组[接口函数序号]))

示例:

3 RT-Thread驻留测试

实验使用STM32L431RC芯片在STM32CubeIDE开发环境下进行测试。测试程序分为BIOS和User两个部分,BIOS中实现了RT-Thread的驻留并先固化到FLASH中,User调用驻留的操作系统服务接口和硬件驱动接口实现具体应用。

3.1 FLASH和RAM实际划分

STM32L431RC片内FLASH大小为256 KB,共128个扇区,每个扇区大小为2 KB。在驻留了RT-Thread后,BIOS共分配14个扇区,其中2个扇区分配给API向量表,另外12个扇区分配给BIOS的vector段、text段和rodata段。片内RAM大小为64 KB,前16 KB分配给BIOS的data段、bss段和heap段,后48 KB分配给User和共享栈空间。具体的空间分配如表2所示。

表2 STM32L431RC中BIOS和User空间划分表

3.2 驻留测试实验设计

驻留测试实验利用三色灯和串口输出对RT-Thread的互斥量、事件机制、信号量和延时函数等系统服务接口进行测试。实验中设计红、绿、蓝三色小灯线程,分别控制三色灯的三种颜色,并且蓝灯线程优先级小于红灯和绿灯,4个系统服务的测试设计如下:

1)互斥量

每个小灯线程使用串口向PC机发送点亮或熄灭状态,并且使用互斥量控制串口输出,即必须有一个线程发送完消息后其他线程才可以占用串口。

2)事件机制

三个小灯按红、绿、蓝顺序依次进入就绪队列,绿灯线程设置了绿灯事件,必须等待事件触发才能执行点亮小灯操作,绿灯事件由蓝灯线程点亮蓝灯后触发。

3)信号量

每个小灯线程在执行点亮操作前,需要获取一个最大数量为2的三色灯信号量,该信号量使得只能有两个小灯同时点亮,即只能是红蓝、红绿或蓝绿合成色小灯。

4)延时函数

每个线程点亮小灯后会等待5 s,然后熄灭小灯再尝试获取三色灯信号量点亮小灯。

按线程进入点亮、等待和阻塞状态的顺序进行分析,点亮状态是获得三色灯信号量点亮小灯,等待状态是暂未获得三色灯信号量进入等待,阻塞是绿灯线程等待绿灯事件。从上电后每隔5 s的理论情况如图5所示。

图5 三色灯混合实验运行效果

上电后第一个5 s情况与后面不同,5 s后是5~15 s情况的循环,整体上是三色灯在紫色和黄色之间切换。

3.3 测试实验结果

测试程序上电后,按GEC架构启动流程进行,首先执行BIOS程序,然后跳转到User程序启动操作系统,接着启动红、绿、蓝三个小灯线程。小灯线程启动后各自执行对应颜色灯的点亮,并从串口向PC机发送消息。PC机使用串口调试助手接收到的消息如图6所示。

图6 测试实验运行流程

在实验中使用STM32CubeIDE编译该测试程序,与非GEC架构下不使用驻留技术的工程相比,耗时减少了约12,编译时间节约效果显著。

4 结 语

本文以Arm Cortex-M内核的STM32L431芯片为例,给出了在通用嵌入式计算机GEC架构下RT-Thread实时操作系统的驻留方法,可有效降低RTOS下应用程序的开发难度,解决了在微控制器上使用RTOS编写应用的编译时间较长、功能分割模糊、程序调试不便等问题,为嵌入式人工智能与物联网终端的快速开发提供了技术基础。驻留RT-Thread的关键要点主要有:FLASH空间的合理划分,RAM的合理应用,利用API接口向量表实现RTOS服务函数映射、BIOS及User的有机衔接等。实验在苏州大学自主研发的集成开发环境AHLGEC-IDE下进行,得到了良好效果,测试用例可以在苏州大学嵌入式学习社区官网获得。本文方法可以为其他实时操作系统的驻留提供借鉴。后续将在此基础上进行RTOS下用户程序统一性研究,以实现不同RTOS下应用程序的可移植性。

猜你喜欢

小灯线程嵌入式
小灯与外婆
我的小灯
搭建基于Qt的嵌入式开发平台
浅谈linux多线程协作
嵌入式软PLC在电镀生产流程控制系统中的应用
欧曼GTL牵引车小灯电路及控制逻辑
无线电力小灯的制作
Altera加入嵌入式视觉联盟
倍福 CX8091嵌入式控制器
基于上下文定界的Fork/Join并行性的并发程序可达性分析*