涂 撰, 赵 标
(1.上海交通大学 船舶海洋与建筑工程学院,上海200240;2.上海船舶运输科学研究所 研发中心,上海200135)
嵌入式实时操作系统RT-Thread是由国内开发人员主创的稳定的开源实时操作系统,它得益于中国开源社区的发展,已经历了6年的开发,得到了来自全国各地嵌入式工程师的鼎力支持。现在它不仅是一款开源意义的实时操作系统,也是一款产品级的实时操作系统。该系统已经被国内十多所企业所采用,是一款能够稳定持续运行的操作系统,具有良好的应用前景。
嵌入式实时操作系统RT-Thread采用面向对象的设计风格,但不同于一般的面向对象系统,它并不是利用C++实现的,而是采用了C语言的方式实现面向对象编程。这样的系统内核简洁、高效、稳定和易于移植。它不仅是单一的实时操作系统内核,还包含了一系列完整的嵌入式组件,如:Fin SH Shell命令行工具、分布式文件系统(Distributed File System,DFS)、优化的网络协议栈l wip、图形用户界面RTGUI和完整的C运行库等。
NXP公司推出的32位RISC处理器LPC2378采用了ARM7 TDMI内核,具有丰富而独特的外设,功能强大,大大减少了系统电路中除处理器以外的元器件配置,能够最小化系统成本,性价比高,十分适合于如工业控制、Internet设备、网络和调制解调设备等嵌入式应用。因此,将嵌入式实时操作系统RT-Thread移植到LPC2378芯片具有现实意义。
随着在嵌入式系统的应用开发中广泛的采用嵌入式实时操作系统,使得实时系统(Real-Ti me Operating System,RTOS)有了很快的发展。常见的嵌入式实时操作系统主要有free RTOS、u C/OS-II、Vx Wor ks、QNX等。表1中列举了u C/OS-II、free RTOS、Vx Works和RT-Thread的比较。
表1 RT-Thread与其他RTOS的比较
RT-thread的源代码可由官方网站获取,或者通过Google SVN下载。目前RT-Thread最新的稳定版本是1.0.0,最新的测试版本为1.1.0beta1。RT-thread源代码的目录结构见图1。
板级支持包(Boar d Support Package,BSP)和libcpu文件夹中的内容均与中央处理器(Central Pr ocessing Unit,CPU)类型和硬件平台有关,因此是移植RT-Thread的重点。其他部分都与硬件平台无关。
RT-Thread有多种开发环境,如scons命令行、GNU的GCC编译环境和ARM公司的MDK开发工具等。个人可以根据各自习惯选择合适的开发环境。RT-Thread发展到0.3.0以后,主要的编译器切换到了ARM公司的Real View ARM Co mpiler,因此推荐采用ARM公司的MDK作为开发工具。
RT-Thread在LPC2378上的移植是通过Real View MDK工具进行的。首先在RT-Thread源码的bsp目录下新建l pc2378目录,将与LPC2378相近的芯片(如l pc2478)目录内容拷贝到新建目录下。在Real View MDK中新建立1个工程文件,保存在bsp/l pc2378目录下。创建工程时CPU选择NXP的LPC2378芯片,可以使用工具自动生成的启动文件。由于需要修改部分代码以适应RT-Thread,因此建议不采用自动生成文件,导入自己编写的启动代码。
修改启动文件start_rvds.s,主要是修改对中断请求(Interr upt Request,IRQ)代码的处理,由 RTThread操作系统截获,重新实现。实现代码如下:IRQ_Handler PROC
图1 RT-Thread 1.0.0版本的目录结构
rt_h w_context_s witch_interr upt_do为中断结束后实现上下文切换的函数。在启动代码中,还要对目标板进行看门狗初始化,关闭系统中断,配置芯片时钟、内存映射方式等。
上下文切换文件context_r vds.s,由于ARM体系结构的相似性,基本不用修改。
trap.c文件与ARM体系结构的中断模式有关,但是需要重新实现的只有rt_hw_trap_irq函数。该函数用于判断IRQ来自芯片的何种外设。通过总的中断向量寄存器获取当前中断向量,并跳转到相应的中断服务程序,具体实现如下所示。对于不同芯片这里的实现略有不同。
修改interr upt.c文件,根据不同的芯片类型对于中断管理略有不同。需要实现的函数如下:rt_h w_interrupt_handle,默认的IRQ处理函数,一般可以只输出一些提示信息,如点灯或者串口打印等;rt_hw_interr upt_init,中断初始化函数;rt_h w_interr upt_mask,中断屏蔽函数,参数为中断号;rt_h w_interr upt_u mask,中断禁止屏蔽函数,参数同为中断号;rt_hw_interrupt_install,中断服务程序安装函数,将中断服务程序安装到对应的中断向量上。
cpu.c文件,主要是CPU复位函数和关闭函数,可以根据LPC2378芯片手册修改,也可不修改,直接为空函数。
stack.c文件,“手工”设置线程的初始栈,使调度器明确切换线程的入口地址和参数地址。同样,由于ARM体系结构的相似性,基本不用修改。
最后是操作系统心跳时钟的移植。操作系统心跳时钟以及相关硬件的初始化工作在BSP包中实现,其内容就是初始化1个硬件定时器并启动它,同时编写好定时器中断服务程序,在中断服务程序中调用rt_tick_increase函数,告知操作系统内核心跳了1次。
完成操作系统内核移植后,更重要的工作就是编写与目标板对应的设备驱动程序。RT-Thread与Vx-Works一样,在设备驱动程序和上层应用之间提供了1个中间层,用于管理I/O类设备,称为I/O设备管理模块。
I/O管理模块实现了对设备驱动程序的封装,设备驱动程序的实现与I/O管理模块独立,提高了模块的可移植性。应用程序通过I/O管理模块提供的标准接口访问底层设备,设备驱动程序的升级不会对上层应用产生影响。这种方式降低了代码的复杂性,提高了系统的可靠性。
在RT-Thread中,设备也被认为是1类对象,每个设备对象都是由基对象派生而来,每个具体设备都可以继承其父类对象的属性,并派生出其私有属性。图2为设备对象的继承和派生关系示意图[3]。
图2 设备对象的继承和派生关系示意图
该数据结构就是RT-Thread的设备基对象。实现设备的驱动函数就是实现数据结构中的接口函数的具体化。
1.实现str uct rt_device中的公共接口函数,以串口设备为例:
rt_serial_init函数实现init接口功能,即设备初始化;
rt_serial_open函数实现open接口功能,即打开设备;
rt_serial_close函数实现close接口功能,即关闭设备;
rt_serial_read函数实现read接口功能,即读取设备数据;
rt_serial_write函数实现write接口功能,即向设备发送数据;
rt_serial_control函数实现contr ol接口功能,即设置设备参数。
所有函数不一定都要实现,比如rt_serial_close,可以只是1个空函数,返回rt_err_t类型数据即可。
2.根据自己的具体设备对象定义设备数据类型中的私有数据,用于特定的需要。
3.扩展设备对象。
1)利用str uct rt_device作为父类,增加属性进行派生,如以串口设备为例:
2)定义自己的数据类型,将str uct rt_device中的void*private指向该数据类型。
4.利用rt_device_register函数将设备注册到RT-Thread的设备框架中。
5.对于需要使用中断等异步方式的设备驱动,还需要编写相应中断服务程序。在init接口函数中挂接相应的中断向量。
RT-Thread最开始由main函数调用rtthread_startup函数,完成对目标板的中断向量初始化、心跳时钟定时器的初始化、系统内核的初始化、相关组件的初始化、外围设备的初始化、调用用户接口函数和空闲任务的初始化等。在rt_system_scheduler_start函数开始任务调度以前,用户必须确认操作系统至少建立1个除idle任务以外的任务才能保证内核的顺利调度,无论这个任务是系统自身组件的任务(如tshell),还是用户自己的任务。在用户接口函数rt_application_init中,用户可以根据需要创建自己的应用程序。
完成了RT-Thread在LPC2378芯片的移植之后,编写了1个CAN-Et her net网关的多任务应用程序,一方面可以进行RT-Thread移植后的稳定测试;另一方面也为RT-Thread在产品化方面做研究。图3显示了串口终端输出的内容,通过Fin SH Shell指令,可以观察内核的运行情况和各个任务的运行信息。通过程序的测试,表明RT-Thread已能在LPC2378芯片稳定运行。
图3 RT-Thread CAN-以太网网关多任务程序串口输出
嵌入式实时操作系统RT-Thread与其他国外成熟的操作系统相比,还是1个新系统。但是随着中国开源社区的发展,越来越多的开发人员参与到RT-Thread的更新维护中,越来越多的企业公司选择RTThread作为操作系统平台,这必将推动RT-Thread在国内稳定、持续的发展,对于企业和RT-Thread开源社区都将形成双赢的局面。同时,将RT-Thread移植到LPC2378芯片,可以为RT-Thread和LPC2378的产品设计开发起到抛砖引玉的作用。
[1] 朱传宏,张丽全.嵌入式实时操作系统RT-Thread在SEP4020上的移植[J].计算机与数字工程,2010(11):93-96.
[2] 邱炜.嵌入式实时操作系统RT_thread的设计与实现[D].西安:西安电子科技大学,2007.
[3] 杜春雷.ARM体系结构与编程[M].北京:清华大学出版社,2003.
[4] 马忠梅,马广云,徐英慧,等.ARM嵌入式处理器结构与应用基础[M].北京:航空航天大学出版社,2002.