王啸等
摘 要: 在微控制器中使用实时内核可以简化嵌入式应用开发。简单介绍了μC/OS?Ⅲ实时内核和Cortex?M3内核的相关内容,将μC/OS?Ⅲ实时内核移植到F28M35x多内核片上系统微控制器中,并阐述了μC/OS?Ⅲ实时内核中任务的创建和调度原理,最终在目标板上运行并进行多任务切换。
关键词: μC/OS?Ⅲ; 嵌套向量中断控制器; 实时内核; 任务切换
中图分类号: TN919?34; TP316.2 文献标识码: A 文章编号: 1004?373X(2015)21?0159?03
Transplantation of μC/OS?Ⅲ real?time kernel on F28M35x device
WANG Xiao, MEI Jialun, CHEN Yue
(Ningbo CSR Times Transducer Techinique Co.,Ltd, Ningbo 315020, China)
Abstract: Application of real?time kernel in microcontroller can simplify the development of embedded application. The related contents of μC/OS?Ⅲ real?time kernel and Cortex?M3 kernel are introduced briefly in this paper, in which the μC/OS?Ⅲ real?time kernel is transplanted into SOC microcontroller of F28M35x dual?core device. The principles of task creation and dispatch in μC/OS?Ⅲ real?time kernel are elaborated. It was operated on target board and switched among multitasks.
Keywords: μC/OS?Ⅲ; nested vectored interrupt controller; real?time kernel; task switch
0 引 言
μC/OS?Ⅲ(Micro C OS Three,微型的C语言编写的操作系统第3版)是一个可升级的、可固化的、基于优先级的实时内核,Micrium公司于2011年8月公开原码,它具备良好的移植性,可以在多种微控制器中运行,加快了嵌入式软件应用开发。相比上一代μC/OS?Ⅱ,μC/OS?Ⅲ可以将多个任务设置在同一优先级上,并按时间片轮转调度,且任务数量是无限制的[1]。而随着ARM在嵌入式领域的不断发展,Cortex?M3器件在嵌入式领域可谓风生水起,它高效的NVIC(Nested Vectored Interrupt Controller)、高性能的RISC(Reduced Instruction Set Computer)以及固定的存储器位置意味着以它为内核的微控制器都可以方便地移植软件,因此在Cortex?M3上使用μC/OS?Ⅲ实时内核是极为方便的[2]。
1 F28M35x器件和μC/OS?Ⅲ
F28M35x器件内部集成了Cortex?M3内核和DSP?C28内核,可以通过核间通信交互协作[3]。高达132 KB的片上RAM、完善的外设和高速的时钟意味着它可以胜任许多任务:从通信到实时控制。M3内核高效的架构和快速的中断响应,使其适合使用嵌入式实时内核[4]。Cortex?M3配备的MPU还具备特权级和用户级操作,增加安全性[5]。
μC/OS?Ⅲ和Cortex?M3是密切相连的,主要包括NVIC(嵌套向量中断控制器)、PendSV(可挂起的系统服务请求)、SysTick(系统节拍定时器)等。NVIC是与M3内核紧密相联的中断控制器,它支持中断嵌套、动态优先级、中断屏蔽等,移植μC/OS?Ⅲ离不开它。PendSV典型的应用场合是上下文切换,它通过操作系统挂起中断,其优先级被设置为所有中断中最低,所有其他的中断服务都执行完毕时它才会被执行,最终实现任务切换。而SysTick作为系统的心跳,会寻找优先级最高的任务,在多任务调度中起着关键的作用[6]。
在Micrium网站可以找到μC/OS?Ⅲ源代码,配合TI提供的Mware库和Code Composer Studio IDE及controlSUITE,移植工作就可以轻松展开。
2 μC/OS?Ⅲ移植工作
2.1 文件结构
μC/OS?Ⅲ工程中的文件可以分为5个部分:实时内核相关、CPU相关、板级支持、芯片级支持、常用库支持。为了让芯片正常工作,需要修改板级的代码如时钟配置和初始化。其次,对于不同编译器、不同微控制器,内核和CPU部分的代码也需要调整。μC/OS?Ⅲ还提供了独立于编译器和CPU的数据类型、函数接口等,方便修改。此外,字符串处理、数学库等也独立提供,方便不同平台移植。
2.2 内核相关
与内核相关的文件名都以os开头,其最重要的核心内容在os_cpu_a.asm中,也是修改的首要对象。内核最重要的工作是负责任务调度。在创建好任务并开始运行μC/OS?Ⅲ时,CPU首先要选择最高优先级且已就绪的任务来执行,这个事件由OSStartHighRdy()来执行,它在OSStart()中调用一次。内容包括:将PendSV中断优先级设为最低,将进程栈指针PSP清零准备首次上下文切换,将主栈指针MSP设为为其分配的内存地址,挂起PendSV中断并开启中断。注意它只运行一次。修改后的内容如图1所示。其中NVIC寄存器和分配的堆栈地址宏是事先定义的,在CCS(Code Composer Studio)中用.word关键词,此外,全局符号用.global,外部引用用.ref关键词。
图1 与内核相关的改动
在这之后就开始了多任务调度模式。在Cortex?M3中,上下文切换只需手动保存和恢复R4?R11和PSP寄存器,xPSR,PC,LR,R12,R0?R3由硬件自动管理[7]。由于PendSV的优先级已经被设为最低,因此可利用它的缓期执行特点来切换任务,当执行一个系统调用如延时或时间片轮转调度时可触发上下文切换,它会在其他重要的任务都完成后才会执行动作。因为当其他中断在执行时如果产生了上下文切换,将产生错误中断。而PendSV的机制会确保这一切准确无误且不会占用太多CPU资源。修改方式类似OSStartHighRdy()。
在uC/OS?Ⅲ中,任务调度由OSSched()来进行,它不断找出优先级最高且就绪的任务,并挂起PendSV中断来调度。它在系统延时、事件同步中都会被调用到,而中断到任务的调度则在OSIntExit()中,即退出中断时引用,最终也是通过挂起PendSV来调度的。
2.3 CPU相关
与CPU相关的改动主要在cpu_a.asm中。这里定义了开关中断、临界区函数等内容。临界区又叫关键代码段,在执行时绝对不能被打断,因此中断必须被关闭。将中断信息保存起来然后在退出临界区前再恢复,才能保证系统正确执行。这些由CPU_SR_Save和CPU_SR_Restore来执行,它们是成对使用的。修改后的代码如图2所示。
图2 与CPU相关的改动
任务调度过程中,可以利用Cortex?M3的指令CLZ查找优先级最高的任务,而不必采用以往查表的方式。CLZ指令可找出一个字的第一个有效位的位数,将它写成一段汇编指令如图2所示,它在OS_PrioGetHighest中引用,用于优先级调度。
此外,在cpu.h中给出处理器的数据类型、字长、栈、临界区等定义。Cortex?M3字长为32位,堆栈类型为满递减堆栈[8](FD)。
2.4 板级支持
在bsp.c中包含了板级初始化的内容,包括配置时钟、配置SysTick中断、配置LED的GPIO,如图3所示。在TI提供的例程中可以找到完善的初始化方法,它们更加简洁。注意在此处即可打开SysTick中断,周期为1 ms。中断入口为OS_CPU_SysTickHandler,将它写入到启动文件的中断向量表中。这些内容修改完以后,再选择自己手头板载的LED灯管脚来配置。在TI的TMDXDOCKH52C1开发板上LED灯使用了PC6,PC7引脚。打开GPIOC时钟并将引脚配置为输出。如果使用了CCS提供的启动文件,要将中段向量地址手动传入到RAM中,可以使用IntFlashVTable()来实现。
完成所有修改以后就可以编译工程了。
3 任务调度
在创建自己的任务以前先了解一下任务优先级的概念。在μC/OS?Ⅲ中任务的优先级在创建任务时被传入,其值越大优先级越低,因此优先级0为最高优先级,空闲任务的优先级为优先级最大值减去1。优先级最大值默认为10。
图3 板级初始化
接下来需要了解任务是如何调度的。通常来说在使用系统延时OSTimeDlyHMSM或OSTimeDly时,等待同步事件如信号量到来,即任务进入阻塞状态时系统会进行任务调度,开始执行已经就绪的任务中优先级最高的任务。此外,系统内部时基任务OSTickTask也可以用于任务切换,它在创建时被设置的默认优先级为7,用户可以修改它的优先级,通常来说它的优先级应该设置为比重要任务的优先级稍低,但高于那些希望被抢占的任务。例如有一个低优先级的任务是一个死循环而没有阻塞,高优先级的任务在就绪时希望去抢占这个低优先级的任务,在μC/OS?Ⅲ中就是由OSTickTask这个任务来实现的,但OSTickTask的优先级应该要高于那个低优先级的任务[9]。
现在分别创建TaskLED1,TaskLED2,TaskUART三个任务,分别控制2盏LED灯和输出OSTaskCtxSwCtr任务切换值,并赋予不同优先级,如图4所示。可以看到灯开始闪烁并且串口有信息输出,可见任务调度是成功的。在μC/OS?Ⅲ中可以创建足够多的任务,只要内存足够使用[10]。学会了任务创建和任务调度以后,操作系统最基础的使用方法就已经掌握了。
4 结 语
本文对μC/OS?Ⅲ实时内核进行了深入探讨并阐述了核心内容,通过将其移植到F28M35x器件平台中实现多任务调度,了解了μC/OS?Ⅲ的使用原理。由于μC/OS?Ⅲ可在众多器件中移植,因而应用的开发将变得十分容易,可以简化软件框架的部署,将更多精力用于应用层设计,为工程开发提供了更多的选择。
参考文献
[1] 宫辉,龚光华,黄土琛.从μC/OS?Ⅱ到μC/OS?Ⅲ的各种改进[J].单片机与嵌入式系统应用,2012,12(10):79?81.
[2] LABROSSE J J. μC/OS?Ⅲ: the real?time kernel [M]. US: Texas Instruments, 2015.
[3] Texas Instruments. SYS/BIOS inter?processor communication (IPC) 1.25 user′s guide [R]. US: Texas Instruments, 2012.
[4] Texas Instruments. TI SYS/BIOS v6.35 real?time operating system user′s Guide [R]. US: Texas Instruments, 2013.
[5] Texas Instruments. Concerto F28M35x technical reference ma?nual [R]. US: Texas Instruments, 2015.
[6] ARM. Cortex?M3 technical reference manual [R]. Cambridge: ARM, 2010.
[7] YIU J. ARM Cortex?M3权威指南[M].2版.北京:清华大学出版社,2014.
[8] LABROSSE J J. Hardware?accelerated RTOS: μC/OS?Ⅲ HW?RTOS and the R?IN32M3 [R]. US: Texas Instruments, 2014.
[9] 黄土琛,宫辉,邵贝贝.μC/OS?Ⅲ对任务调度的改进[J].单片机与嵌入式系统应用,2012,12(11):78?80.
[10] MANOJ K R B, SATYANARAYANA G S R, SEETARAMANJANEYULU B. Scheduling latency comparison of two open?source RTOSs on CORTEX?M3 [C]// Proceedings of 2014 IEEE International Conference on Embedded Systems. Coimbatore: IEEE, 2014: 59?62.