②调整和修改头文件OS_CFG.H,以裁减或修改μC/OS_II的系统服务,减少资源损耗。例如#defineOS_MBOXEN_0即禁止使用邮箱相关的代码。
③编写C语文件OS_CPU.C。由于本次设计中未用到其他几个函数,因此这里主要完成函数OS-TaskStkInit()的编写。OS-TaskStkInit()用来初始化任务的堆栈结构,使其看起来象刚发生过中断并将所有的寄存器保存到堆栈的情形一样。
④编写汇编语言文件OS_CPU.ASM。本文件包括4个子函数程序:OSStartHighRdy()(运行最高优先级任务)、OSCtxSw()(任务级的任务切换)、OS-IntCtxSw()(中断级的任务切换)和OSTickISR()(μC/OS_II的时间节拍中断函数),这是μC/OS-II移植中的重点和难点,这几个函数的合理实现,是保证μC/OS-II运行的基础。上述工作完成后,μCOS_II就可以运行了。
应用软件设计
系统任务的构成及优先级分配
本测控终端要完成的任务包括:①16路模拟量的采集;②2路频率采集;③32路状态量采集;④16路控制量输出;⑤与上位机的实时CAN总线通信;⑥自检测。根据上述实现功能划分系统的任务如表1所示,对任务优先级的分配,这里主要考虑任务的实时性,对实时性要求高的任务分配较高的优先级,使其得到优先调度。

优先级最高的是开始任务(TaskStart),这是系统启动后运行的第一个任务。在该任务中要完成系统及相关外设的初始化,并进行必要的自检测,然后创建其余的各个任务。在完成其余各个任务的创建之后,该任务要删除自己,要系统资源让给其它任务,整个系统开始正常运行。该任务的示意代码如下:
/*系统及外设的初始化*/
/*系统自检测*/
/*创建各个任务*/
StartCpuTimer2();; /*起动时间片*/
OSStatInit(); /*统计任务初始化*/
创建智能终端的各个应用任务;
KickDog(); /*WatchDog复位*/
OSTaskDel(OS_PRIO_SELF); /*删除开始任务*/
除了TaskStart()之外,其余各个任务模块的结构都是一个无限循环体,图2给出了一般任务的任务流程图。各任务的运行采用事件驱动方式,用户创建任务后,初始化为挂起状态,等待中断或其他任务发相应的事件来驱动该任务。

图2任务流程图
任务的通信与同步
μC/OS-II提供了五种用于数据共享和任务通信的方法:信号量、邮箱、消息队列、事件标志及互斥型信号量。信号量可以控制共享资源的使用权,也可以协调外部事件与任务的执行,提供了任务间通信、同步和互斥的最快通信,μC/OS-II提供了3种类型的信号量,即二进制型、计数型和互斥型。事件标志可使任务与多个事件同步,若与多个事件的任何一个同步,称为独立型同步,若与多个事件都同步,称之为关联型同步。邮箱是一种通信机制,它可以使一个任务或中断服务子程序向另一个任务发送一个指针型的变量,该指针指向一个包含了特定消息的数据结构。消息队列是另一种通信机制,它可以使一个任务或中断服务子程序向另一个任务发送以指针定义的变量,具体应用不同,每个指针指向的数据结构也不同。互斥型信号量是一种特殊的二进制型信号量,主要用于解决内在的互斥问题,减少实际应用中所必需的优先级翻转。
在设计测控终端软件时,充分利用了μC/OS-II提供的这些通信机制,来协调各个独立任务的运行。这里以通信模块为例介绍通信机制在设计中的应用。通信模块共包含四个任务TaskUnpack()、TaskPack()、TaskCANRX()和TaskCANTX()和一个中断Intecan(),任务间的通信流程如图3所示。在采集模块中如果发现系统某个信号发生异常则各采集模块就会发送Qstate,从而使打包任务处于就绪状态。终端对上位机数据的接收采用中断方式,在中断服务程序中发送标志量给任务TaskCANRX(),使其处于就绪态。在接收任务函数中通过判断自定义的数据包头决定接收数据的类型,如果接收的数据是开关量控制命令,则发送邮箱标志MboxUnpack给解包任务,如果接收的数据是发送状态量请求命令,则发送标志量FlagCANTX给发送任务。另外,在打包任务和发送任务处理中,为了防止对共享数据区Data_BusToSend[x]误操作,我们使用了共享冲突信号量MutexSendEMPCMu-texSendDI和MutexSendBus。:其执行表示意性代码如下: