中文引用格式: 王磊,王宜怀,姚望舒,等. MQXLite操作系统在ARM Cortex-M0+/M4上的移植研究与实现[J].电子技术应用,2015,41(11):27-30.
英文引用格式: Wang Lei,Wang Yihuai,Yao Wangshu,et al. The study and implementation of porting MQXLite RTOS to ARM Cortex-M0+/M4[J].Application of Electronic Technique,2015,41(11):27-30.
0 引言
MQXLite操作系统是飞思卡尔公司维护的一款开源的嵌入式实时操作系统,是已有十几年稳定实践运行经验的标准版MQX(Message Queue eXecutive)嵌入式实时操作系统的轻量级版本,专门针对ARM Cortex-M系列中资源有限的MCU开发,目前仅支持M0+/M4内核的MCU,具有内核精简、资源占用低(低于4K RAM)、执行效率高等特点[1]。
目前的MQXLite集成在飞思卡尔公司的图形化快速程序设计工具——处理器专家(Processor Expert,PE)里,作为其中的一个组件提供,使用独立的PE软件套件或是集成了PE的开发环境(CodeWarrior或Kinetis Design Studio)可以方便地构建一个基于MQXLite的工程,实现MQXLite在PE支持芯片上的移植。但此种移植方式过度依赖于PE软件,移植的通用性与灵活性不足,不利于工程在PE不支持的芯片平台上移植。
针对此缺陷,本文对PE中生成的MQXLite代码进行了整理与修改,提出了一种改良版的MQXLite组织架构,使得其脱离PE可独立配置,并利用此架构构建了一个通用的工程框架模板“AMQXLITEFW”。在此框架下,分别实现了MQXLite在M0+内核的飞思卡尔KW01芯片及M4内核的德州仪器CC3200芯片上的移植,拓展了MQXLite的适用平台。
1 移植研究
1.1 MQXLite的组织架构
通过分析MQXLite源码包的构成,并与PE中生成的完整MQXLite工程代码相比较,可以得出PE下MQXLite组织架构的各部分组成如下:
KERNEL:MQXLite的微内核,是标准版MQX内核的精简。具有基于优先级的抢占式任务调度、中断处理及任务间的同步与通信(轻量级)等核心功能。
PSP:处理器支持包(Processor Support Package,PSP),包含了MQXLite操作系统的上下文切换、中断控制等与芯片内核密切相关的功能。
LDD:PE中提供的逻辑设备驱动(Logic Device Drivers,LDD),用来实现对外设I/O的访问。
BSP:板级支持包(Board Support Package,BSP),包含与具体芯片及电路板相关的时钟、中断初始化等内容,通过图形化的参数配置后,由PE自动生成。
TASK:应用任务,用于实现具体的应用功能。
在此架构中,KERNEL及PSP的代码都源于MQXLite的源码包,其中KERNEL部分是通用代码,而PSP中穿插有部分LDD及PE生成代码;LDD及BSP部分的代码则完全是通过配置PE自动生成,因不同的目标芯片及实际电路板的具体情况而异;TASK中的应用任务代码根据实际需求编写,部分与特定平台相关的应用任务也会调用PE生成的LDD代码。
由此可见,此架构下的MQXLite与PE被紧密地捆绑在了一起。利用此架构,虽然可以在PE的帮助下快速便捷地完成MQXLite在部分目标芯片上的移植,但若想将MQXLite移植到PE不支持的芯片平台上,实现起来较为困难。
可行的解决方案是设法将MQXLite从PE中独立出来,使其能够脱离PE单独配置,并根据目标芯片选用第三方的驱动程序来访问外设I/O,这样就增强了MQXLite的移植灵活性与通用性,拓展了MQXLite的适用芯片平台。基于以上思想,本文对此架构中的组成内容进行了适当的修改,提出了一种改良版的MQXLite组织架构,架构中各组成部分如下:
KERNEL:使用MQXLite源码包中提供的KERNEL代码。
PSP:使用MQXLite源码包中提供的PSP代码,用自行编写的通用代码替换PE生成代码。
DRIVER:使用第三方驱动而不是PE中的LDD来实现对外设I/O的访问。
BSP:自行编写通用的时钟、中断初始化函数,并利用宏常量的方式传递参数,方便根据具体芯片及电路板的情况来进行配置修改。
TASK:保留应用任务代码不变,只在调用到外设I/O驱动时将LDD驱动替换为Driver中的第三方驱动程序。
两种组织架构的对比如图1所示。相比PE下的MQXLite组织架构,此改良版的架构有独立、通用、灵活的特点。
1.2 通用的工程框架模板
为了供移植时参考,本文结合上文提出的改良版MQXLite组织架构与本实验室提出的基于标准版MQX的工程框架“AMQXFW”,提出了一个面向MQXLite的通用工程框架模板“AMQXLiteFW”,其在Kinetis Design Studio 3.0(KDS 3.0)集成开发环境下的工程组成如图2所示[2]。
工程框架中的MQXLite文件夹存放操作系统的相关文件,包含6个子文件夹:app、bsp、psp、kernel、include及config。其中app对应组织架构中的“TASK”,bsp即架构中的“BSP”,include、kernel及psp共同组成了“KERNEL”及“PSP”;config则存放了MQXLite的配置文件,用于MQXLite内核功能的裁剪。
该工程框架模板组织结构清晰,内容简单明了,便于工程的移植。
2 移植实现
利用上文提出的AMQXLiteFW通用工程框架模板及相应的第三方驱动程序,可以方便地实现MQXLite在任何ARM Cortex-M0+/M4内核芯片上的移植。下面从启动流程、中断系统、系统定时器及应用任务这几个方面介绍移植的过程。
2.1 启动流程
使用MQXLite的工程需要一个新的复位向量函数Reset_Handler(),以便于在通用的初始化操作之前完成一些与操作系统相关的额外设置。此函数用汇编语言编写,位于boot.S文件中,主要实现如下功能:
(1)重置外设中断状态。通过对NVIC相关寄存器的操作来关闭所有外设中断并清除所有挂起中断标志。其中由于M0+内核与M4内核所支持的最大外设中断数目不同(M0+:32,M4:240),所以在移植时可根据目标MCU的类型宏定义来条件编译不同的代码。
(2)切换栈指针。芯片复位后默认使用主栈指针(Main Stack Pointer,MSP),而操作系统在运行应用任务时使用进程栈指针(Process Stack Pointer,PSP),只有在进入异常或中断时才使用MSP。所以在复位向量函数中需要将CONTROL寄存器的第1位置1,实现从MSP到PSP的切换。此部分M0+内核与M4内核一致,无需修改。
(3)FPU相关设置。若目标芯片为M4内核且具有浮点运算单元FPU并决定在MQXLite中使用,则对系统控制块SCB的CPACR及FPCCR寄存器进行设置,开启芯片的FPU协处理器,并关闭硬件在进入异常时对FPU相关寄存器的自动压栈操作。
结束以上操作后,跳转到无操作系统下的通用启动流程,然后进入应用主函数main(),在其中调用_mqxlite_
init()及_mqxlite()函数来初始化并启动MQXLite操作系统。
2.2 中断系统
MQXLite的中断处理过程分为两个相对独立的部分:内核ISR与用户ISR。内核ISR函数_int_kernel_isr用汇编语言编写,以便能快速的响应中断,它完成PSP与MSP之间的切换与上下文的保存,实现硬件中断到用户ISR的映射;用户ISR则通常用C语言编写,与无操作系统下的中断服务例程一致,用于处理各种中断事件[3]。
鉴于这种情况,MQXLite在维护ROM中的硬件中断向量表之外,还维护了一个存储在RAM中的用户中断向量表。在移植时,需要将硬件中断向量表中的系统定时器中断向量及所有外设中断向量都预设为内核ISR函数,以作为它们的通用入口,接着在应用任务中调用_int_install_isr()函数将对应外设的用户ISR注册到用户中断向量表中。这样当中断到来时,首先会进入内核ISR,然后再查找用户中断向量表,转到相应的用户ISR,实现外设硬件中断到用户编写的中断服务例程之间的映射。整个中断处理流程如图3所示。
内核ISR与处理器所用内核有关,位于dispatch.S文件中。此文件可直接从MQXLite源码包中获取,并已针对M0+内核及M4内核提供了不同版本,移植时根据需要进行替换即可。用户ISR在移植时可保持与无操作系统下的外设ISR代码基本一致。
2.3 系统定时器
MQXLite使用Cortex-M内核中共有的Systick定时器作为系统定时器,为操作系统提供系统节拍,用于任务的调度,其初始化代码调用了PE中的LDD驱动。为了摆脱PE,在AMQXLiteFW框架中使用了自行编写的更为简单通用的systick_init()函数来代替LDD驱动实现Systick定时器的初始化,然后调用_int_install_isr()函数将MQXLite内核中的滴答处理例程_time_notify_kernel()注册到Systick的中断向量中,实现MQXLite操作系统与Systick定时器的关联。在移植时只需根据具体应用需求,修改bsp.h头文件中宏定义BSP_ALARM_FREQUENCY的值(单位:Hz),即可改变系统定时器的节拍频率。
2.4 应用任务
MQXLite不支持动态任务创建,所以需要在编译时静态地为所有任务预先分配好任务栈空间,并在任务模板列表MQX_template_list中登记任务的相关属性。
MQXLite只支持基于优先级的抢占式先入先出任务调度方式。为了触发任务,在此框架中会固定地创建自启动任务task_main,用于外设硬件模块初始化及其他任务的创建。此任务执行完后会自我阻塞,操作系统开始根据优先级的高低对就绪队列中的任务进行调度[4]。
在移植应用任务时,为了协调任务间的执行顺序,既可以使用轻量级的事件、信号量、消息队列等任务同步组件函数,也可以在任务循环体最后调用_time_delay_
ticks()等延时函数来主动放弃CPU的占用权[5]。
3 移植测试
为了检验提出的AMQXLiteFW框架及移植流程的通用性与有效性,本文在KW01及CC3200这两款不同内核、不同厂商的MCU上进行了MQXLite的移植测试。
3.1 KW01移植测试
KW01为飞思卡尔公司推出的基于ARM Cortex-M0+内核的Sub-GHz无线MCU,可工作在290~1 020 MHz的无线频率范围内,最高主频48 MHz,拥有128 KB的ROM及16 KB的SRAM。由于在PE V3.0.0之前并不支持这款芯片,所以利用本文提出的框架及本实验室自行编写的KW01外设驱动程序来构建MQXLite移植测试工程。
测试工程程序分为两个部分:发送节点程序与接收节点程序。发送节点程序通过ADC内部通道采集芯片温度及电源电压等信息,在收到问询帧后回发相关数据。接收节点程序对从串口接收到的PC端命令进行无线转发,并将收到的无线数据通过串口上传到PC端。
移植完成后在KDS 3.0开发环境里编译工程并下载到测试节点中进行测试,PC端软件运行结果可看出使用MQXLite的芯片运行正常,实现了目标功能。
3.2 CC3200移植测试
CC3200是德州仪器公司推出的基于ARM Cortex-M4内核的WiFi无线MCU,支持Wi-Fi 802.11 b/g/n及TCP/IP协议栈,主频80 MHz,最高拥有256 KB的SRAM。此芯片的生产厂商并非飞思卡尔公司,故PE对其并不支持,测试工程利用本文提出的框架及德州仪器公司提供的外设驱动程序,尝试将MQXLite操作系统移植到此芯片中。
测试程序将CC3200配置为AP模式,与存储在外部Flash中的网页进行交互,根据网页上传来的信息控制测试板上指示灯的亮灭,并从串口输出网页上发送过来的字符串信息。
移植完成后在IAR 7.2 IDE里编译工程并下载到测试板,PC或手机连接到CC3200的WiFi热点,通过浏览器访问内置网页进行通信与控制测试,测试结果与预期目标一致,说明MQXLite移植成功。
4 总结
移植测试的结果验证了本文提出的AMQXLiteFW框架的可移植性与通用性。此框架使得MQXLite可以脱离PE移植到任何厂商的ARM Cortex-M0+/M4芯片上,为MQXLite在不同平台上的移植提供了借鉴。此外,为了进一步提高此框架的通用性,还可以继续研究修改MQXLite的相关代码,使其兼容ARM Cortex微控制器软件接口标准(CMSIS),并统一外设驱动的接口,使得工程更便于移植。
参考文献
[1] Freesca1e Semiconductor.MQXLite Real-Time Operating System User Guide. Rev 1.1[EB/OL].(2014-4-2).http://cache.freescale.com/files/soft_dev_tools/doc/user_guide/MQXLITEUG.pdf.
[2] 王宜怀,朱仕浪,姚望舒.嵌入式实时操作系统MQX应用开发技术-ARM Cortex-M微处理器[M].北京:电子工业出版社,2014.
[3] 石晶,王宜怀,苏勇,等.基于ARM Cortex-M4的MQX中断机制分析与中断程序框架设计[J].计算机科学,2013,40(6):41-44.
[4] ZHAO T,LONG D.Analysis on task scheduling operating mechanism of embedded real-time operating system MQX[C].Mechatronic Sciences, Electric Engineering and Computer(MEC),Proceedings 2013 International Conference on.IEEE,2013:1844-1847.
[5] 周航慈,吴光文.基于嵌入式实时操作系统的程序设计技术[M].北京:北京航空航天大学出版社,2006.