2.2 μC/OS-II的组成部分
μC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。
(1)核心部分(Os Core.c)
是操作系统的处理核心,包括操作系统初始化、操作系统运行、中断退出的前导、时钟节拍、任务调度、事件处理等多部分。能够维持系统基本工作的部分都在这里。
(2)任务处理部分(Os-task.c)
任务处理部分中的内容都是与任务的操作密切相关的。包括任务的建立、删除、挂起、恢复等等。因为μC/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。
(3)时钟部分(Os-time.c)
μC/OS-II中的最小时钟单位是time tick(时钟节拍)。任务延时等操作是在这里完成的。
(4)任务同步和通信部分
为事件处理部分,包括信号量、邮箱、邮箱队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。
(5)与CPU的接口部分
是指μC/OS-II针对所使用的CPU的移植部分。由于μC/OS-II是一个通用性的操作系统,对于关键问题的实现,是需要根据具体CPU的具体内容和要求作相应的移植。主要包括中断级任务切换的底层实现、任务级任务切换的底层实现、时钟节拍的产生和处理、中断的相关处理部分等内容。
2.3 μC/OS-II操作系统移植 2.3.1 OS_CPU.H文件的移植
OS_CPU.H 包括了用#defines 定义的与处理器相关的常量、宏和类型定义。OS_CPU.H的程序结构如下所示。
6
#if-def OS_CPU_GLOBALS #define OS_CPU_EXT #else
#define OS_CPU_EXT extern
#en dif /* 数据类型 (与编译器相关) */ type def unsigned char BOOLEAN;
type def unsigned char INT8U; /* 无符号8位整数 */
type def signed char INT8S; /* 有符号8位整数 */
type def unsigned int INT16U; /* 无符号16位整数 */
type def signed int INT16S; /* 有符号16位整数 */
type def unsigned long INT32U; /* 无符号32位整数 */
type def signed long INT32S; /* 有符号32位整数 */
type def float FP32; /* 单精度浮点数 */
type def double FP64; /* 双精度浮点数 */
type def unsigned char OS_STK; /* 堆栈入口宽度为8位 */
/* 与处理器相关的代码
*/
#define OS_ENTER_CRITICAL() EA = 0 /* 禁止中断 */
#define OS_EXIT_CRITICAL() EA = 1 /* 允许中断 */
#define OS_STK_GROWTH 0 /* 定义堆栈的增长方向 */
#define OS_TASK_SW() Oscitant()
(1)与编译器相关的数据类型
因为不同的微处理器有不同的字长,所以μC/OS-Ⅱ的移植包括了一系列的类型定义以确保其可移植性。尤其是,μC/OS-Ⅱ代码从不使用 C 的 short,int 和 long 等数据类型,因为其是与编译器相关的,不可移植。相反的,将其定义成整型数据结构既是可移植的又是直观的。为了方便, μC/OS-Ⅱ虽然不使用浮
7
点数据,但还是定义浮点数据类型。μC/OS-Ⅱ和用户的应用程序就可以估计出声明为该数据类型的变量的数值范围是 0~65535。将 μC/OS-Ⅱ移植到32 位的处理器上也就意味着 INT16U 实际被声明为无符号短整型数据结构而不是无符号整型数据结构。但是,μC/OS-Ⅱ所处理的仍然是INT16U。
用户必须将任务堆栈的数据类型告诉给μC/OS-Ⅱ。这个过程是通过为OS_STK声明正确的 C 数据类型来完成的。MCS-51 系列单片机的堆栈成员是 8 位的,并且用户的编译文件指定字符型为8位数,所以应将OS_STK声明为无符号字符型数据类型。
(2)OS_ENTER_CRITICAL()和 OS_EXIT_CRITICAL()
与所有的实时内核一样,μC/OS-Ⅱ需要先禁止中断再访问代码的临界段,并且在访问完毕后重新允许中断。这就使得μC/OS-Ⅱ能够保护临界段代码免受多任务或中断服务例程(ISR)的破坏。中断禁止时间是商业实时内核公司提供的重要指标之一,因为它将影响到用户的系统对实时事件的响应能力。虽然 μC/OS-Ⅱ尽量使中断禁止时间达到最短,但是μC/OS-Ⅱ的中断禁止时间还主要依赖于处理器结构和编译器产生的代码的质量的。通常每个处理器都会提供一定的指令来禁止/允许中断,因此用户的C编译器必须要有一定的机制来直接从C中执行这些操作。有些编译器能够允许用户在C源代码中插入汇编语言声明。这样就使得插入处理器指令来允许和禁止中断变得很容易。其它一些编译器实际上包括语言扩展功能,可以直接从 C 中允许和禁止中断。μC/OS-Ⅱ 定义两个宏来禁止和允许中断:OS_ENTER_CRITICAL() 和
OS_EXIT_CRITICAL()。
OS_ENTER_CRITICAL() 用来关中断,OS_EXIT_CRITICAL()用来开中断。执行这两个宏的最简单的方法是在 OS_ENTER_CRITICAL()中调用处理器指令来禁止中断,以及在 OS_EXIT_CRITICAL()中调用允许中断指令。本移植过程就是通过这种方法来禁止允许中断的。在本移植对象中,所选用的 MCS-51 系列单片机是通过中断允许寄存器(IE)来控制中断的。IE的最高位EA为CPU中断标志位,当 EA=0 时为关中断,当EA=1时为开中断。由于该部分与处理器相关,固应对它们进行宏定义,以便移植。
(3)OS_STK_GROWTH
8
绝大多数的微处理器和微控制器的堆栈是从高地址往低地址增长的。但是某些处理器是从低地址向高地址增长的。μC/OS-Ⅱ被设计成两种情况都可以处理,只要在结构常量OS_STK_GROWTH中指定堆栈的生长方式即可。
1)置OS_STK_GROWTH为0表示堆栈从低地址向高地址增长。 2)置OS_STK_GROWTH为1表示堆栈从高地址向低地址增长。 (4)OS_TASK_SW()
OS_TASK_SW()是一个宏,它是在 μC/OS-Ⅱ从低优先级任务切换到最高优先级任务时被调用的。OS_TASK_SW()总是在任务级代码中被调用的。另一个函数OSIntExit()被用来在 ISR 使得更高优先级任务处于就绪状态时,执行任务切换功能。任务切换只是简单的将处理器寄存器保存到将被挂起的任务的堆栈中,并且将更高优先级的任务从堆栈中恢复出来。
在μC/OS-Ⅱ中,处于就绪状态的任务的堆栈结构看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。为切换任务可以通过执行 OS_TASK_SW()来产生中断。大部分的处理器会提供软中断或是陷阱(TRAP)指令来完成这个功能。ISR 或是陷阱处理函数(也叫做异常处理函数)的向量地址必须指向汇编语言函数OSCtxSw()。
2.3.2 OS_CPU_C.C 文件的移植
μC/OS-Ⅱ的移植实例需要编写六个简单的C函数: 1)OSTaskStkInit(); 2)OSTaskCreateHook(); 3)OSTaskDelHook(); 4)OSTaskSwHook(); 5)OSTaskStatHook(); 6)OSTimeTickHook();
唯一必要的函数是OSTaskStkInit(),其它五个函数必须得声明但没必要包含代码。
9
3 系统硬件设计
3.1 方案研究
(1)方案一
使用ISD语音芯片和LED点阵模块构成。其具有下列特点:①具有高的语音录放质量及实用性,可重复使用;②抗干扰能力强,稳定性好;③信号易于处理、传送和自动控制;④便于现场录制播放,播放语音显示效果好⑤安装方便,维护简单,工作可靠性高。ISD语音芯片可以采用美国ISD(Information Storage Devices)公司的ISD4004系列芯片,这类芯片采用直接模拟存储专利技术,把语音信号以原始的模拟形式直接存储在片内EEPROM存储器中,无需进行A/D 转换和压缩处理等,从而减少了失真、大大提高了录放音质量,并具有抗断电、音质好、使用方便、可反复录放、无需专用的语音开发工具、能随意列改内容和耗电省等优点,很适合于现场录放音系统。
比较两个方案后可以发现,方案二更适合于用作本系统的实施方案。尽管方案二不需要A/D,但考虑到系统扩充等因素,单片机可以选用STC89C52RC。
(2)方案二
利用8031单片机作为CPU来进行总体控制,当汽车到达某站时,汽车司机通过键盘来控制本系统进行工作,并且,系统将使用状态指示电路,向司机指示出当前的行驶方向及站号(如与实际方向不符,司机可通过键盘来调整)。原理图框图如图2.1所示。
语音输入输出电路 语音合成电路 8031小系统 LED点阵显示电路 键盘 状态指示电路 图3.1 原理框图
10