当前位置:文档之家› ucosii实验指导书——freesscale

ucosii实验指导书——freesscale

目录

第一章μCOS-II介绍 (2)

1.1 μCOS-II系统概述 (2)

1.2 μCOS-II的特点 (2)

1.3 μCOS-II文件及结构介绍 (3)

1.4 μCOS-II移植条件 (3)

1.5 μCOS-II移植步骤 (4)

第二章μCOS-II系统实验 (6)

2.1 μCOS-II任务基础实验 (6)

2.2 优先级反转实验 (11)

2.3 信号量实验..... (17)

2.4 内存管理实验 (22)

2.5 时间中断实验 (29)

2.6 消息队列实验 (34)

第三章嵌入式U COS-II实验 (44)

3.1 uC/OS-II 按键显示实验 (44)

3.2 uC/OS-II 中断控制实验 (46)

3.3 uC/OS-II 综合实验 (49)

第一章μCOS-II介绍

1.1 μCOS-II系统概述

μC/OS-II是一个抢占式实时多任务内核。μC/OS-II是用ANSI的C语言编写的,包含一小部分汇编语言代码,使之可以提供给不同架构的微处理器使用。至今,从8位到64位,μC/OS-II已经在40多种不同架构的微处理器上使用。世界上已经有数千人在各个领域中使用μC/OS,这些领域包括:照相机行业、航空业、医疗器械、网络设备、自动提款机以及工业机器人等。

μC/OS-II全部以源代码的方式提供给读者,大约有5500行。本教程CPU相关的部分使用的是针对基于MC9S128XS Cortex-M3内核的STM32F10x微处理器的代码。虽然μC/OS-II可以在PC机上开发和测试,但是可以很容易地移植到不同架构的嵌入式微处理器上。

1.2 μCOS-II的特点

1、源代码:μC/OS-II全部以源代码的方式提供给使用者(约5500行)。该源码清晰易读,结构协调,且注解详尽,组织有序;

2、可移植(portable):μC/OS-II的源代码绝大部分是用移植性很强的ANSI C写的,与微处理器硬件相关的部分是用汇编语言写的。μC/OS-II可以移植到许许多多不同的微处理器上,条件是:该微处理器具有堆栈指针,具有CPU内部寄存器入栈、出栈指令,使用的C编译器必须支持内嵌汇编,或者该C语言可扩展和可链接汇编模块,使得关中断和开中断能在C语言程序中实现;

3、可固化(ROMable):μC/OS-II是为嵌入式应用而设计的,意味着只要具备合适的系列软件工具(C编译、汇编、链接以及下载/固化)就可以将μC/OS-II嵌入到产品中作为产品的一部分;

4、可裁减(scalable):可以只使用μC/OS-II中应用程序需要的系统服务。可裁减性是靠条件编译实现的,只需要在用户的应用程序中定义那些μC/OS-II中的功能应用程序需要的部分就可以了;

5、可抢占性(preemptive):μC/OS-II是完全可抢占型的实时内核,即μC/OS-II总是运行就绪条件下优先级最高的任务;

6、多任务:μC/OS-II可以管理64个任务。赋予每个任务的优先级必须是不相同的,这就是说μC/OS-II不支持时间片轮转调度法(该调度法适用于调度优先级平等的任务);

7、可确定性:绝大多数μC/OS-II的函数调用和服务的执行时间具有可确定性。也就是说用户能知道μC/OS-II的函数调用与服务执行了多长时间。进而可以说,除了函数OSTimeTick()和某些事件标志服务,μC/OS-II系统服务的执行时间不依赖于用户应用程序任务数目的多少;

用程序对RAM 的需求;

9、系统服务: μC/OS-II 提供许多系统服务,比如信号量、互斥信号量、事件标志、消息邮箱、消息队列、时间管理等等;

10、中断管理: 中断可以使正在执行的任务暂时挂起。如果优先级更高的任务被该中断唤醒,则高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套层数可以达255层;

11、稳定性和可靠性: μC/OS-II 的每一种功能、每一个函数以及每一行代码都经过了考验和测试,具有足够的安全性与稳定性,能用于与人性命攸关、安全性条件极为苛刻的系统中。

1.3 μCOS-II 文件及结构介绍

μC/OS-II 的文件体系结构见图1-1,其中应用软件层是基于μC/OS-II 上的代码,μC/OS-II 包括三部分:

● 核心代码部分:这部分代码与处理器无关,包括七个源代码文件和一个头文件,这七个源代码文件

负责的功能分别是内核管理、事件管理、消息队列管理、存储管理、消息管理、信号量处理、任务调度和定时管理。 ● 设置代码部分:包括两个头文件,用来配置事件控制块的数目以及是否包含消息管理相关代码等。 ● 处理器相关的移植代码部分:这部分包括一个头文件,一个汇编文件和一个C 代码文件,在μC/OS-II

的移植过程中,用户所需要关注的就是这部分文件。

图1-1 uC/OSII 文件体系结构

1.4 μCOS-II 移植条件

移植μC/OS-II 到处理器上必须满足以下几个条件: (1) 处理器的C 编译器能产生可重入代码。

可重入代码指的是可以被多个任务同时调用,而不会破坏数据的一段代码,或者说代码具有在执行过程中打断后再次被调用的能力。

下面列举了两个函数例子,它们的区别在于保存变量temp的位置不同,左边的函数中temp作为全局变量存在,右边的函数中temp作为函数的局部变量存在,因此左边的函数是不可重入的,而右边的函数是可以重入的。

int temp;

void swap (int *x,int*y) {

temp=*x;

*X=*Y;

*y=Temp;

}void swap (int *x,int*y) {

int temp;

temp=*x;

*X=*Y;

*y=Temp;

}

(2) 用C语言就可以打开和关闭中断。

MC9S128XS处理器核包含一个CPSR寄存器,该寄存器包括一个全局的中断禁止位,控制它可以打开和关闭中断。

(3) 处理器支持中断并且能产生定时中断。

MC9S128XS处理器都支持中断并能产生定时中断。

(4) 处理器支持容纳一定量数据的硬件堆栈。

对于一些只有10根地址线的8位控制器,芯片最多可访问1K存储单元,在这样的条件下移植是比较困难的。

(5) 处理器有将堆栈指针和其他CPU寄存器读出和存储到堆栈或内存中的指令。

MC9S128XS处理器中汇编指令stmfd可以将所有寄存器压栈,对应也有一个出栈的指令ldmf d。

1.5 μCOS-II移植步骤

●移植步骤之一-- 基本的配置和定义

所有需要完成的基本配置和定义全部集中在os_cpu.h头文件中。

定义与编译器相关的数据类型。

μCOS-II为了保证可移植性,程序中没有直接使用int,unsigned int等定义,而是自己定

义了一套数据类型,如INT16U表示16位无符号整型,对于MC9S128XS这样的32位内

核,INT16U是unsigned short型,如果是16位的处理器,则是unsigned int型。

定义允许和禁止中断宏。

定义栈的增长方向。

用户规划好栈的增长方向后,定义符号OS_STK_GROWTH的值。

定义OS_TASK_SW宏。

OS_TASK_SW宏是uC/OS-II从低优先级任务切换到高优先级任务时的调用,可以采用下面两种方式定义:如果处理器支持软中断,可以使用软中断将中断向量指向OSCtxSw函数;

或者直接调用OSCrxSw函数。

●移植步骤之二-- 移植OS_CPU_A.ASM汇编代码文件

OS_CPU_A.ASM汇编代码文件有四个汇编函数需要移植。

OSStartHighRdy函数

本函数由OSStart函数调用,OSStart函数负责使就绪状态的任务开始运行,其中OSStar tHighRdy负责获取新任务的堆栈指针,并从堆栈指针中恢复新任务的所有处理器寄存器。函数要移植的原因就是因为它涉及到保存处理器寄存器到堆栈。

OSCtxSw函数

本函数由OS_TASK_SW宏调用,OS_TASK_SW宏由OSSched函数调用,OSSched

函数负责任务之间的切换;OSCtxSw函数在OSSched函数中负责保存当前任务对应的处理器寄存器到堆栈中,并将任务中需要恢复的处理器寄存器从堆栈中恢复出来。

OSIntCtxSw函数

本函数由OSIntExit函数调用,OSIntExit函数由OSTickISR调用,负责在定时中断中的任务之间的切换,前面提到的函数OSCtxSw和本函数均负责任务之间的切换,区别主要在于是否在定时中断期间负责任务切换;OSIntCtxSw函数主要保存当前任务堆栈指针,并将新任务对应的处理器寄存器从堆栈中恢复出来。

OSTickISR函数

时间节拍函数,由定时中断产生,主要负责在进入时保存处理器寄存器,完成任务的切换,退出时恢复寄存器并返回。

●移植步骤之三-- 移植OS_CPU_C.C标准C代码文件

移植μC/OS-II的第三步是移植C语言源代码文件OS_CPU_C.C,这个源文件中由6个函数需要移植:

OSTaskStkInit( )

OSTaskCreateHook( )

OSTaskDelHook( )

OSTaskSwHook( )

OSTaskStatHook( )

OSTimeTickHook( )

后面五个HooK函数,又称为钩子函数,主要用来扩展uC/OS-II功能。但必须声明,并不一定要包含任何代码。

唯一必需移植的函数是OSTaskStkInit函数,这个函数在任务创建时被调用,它负责初始化任务的堆栈结构。这个函数在大部分MC9S128XS处理器中移植时都可以采用一种形式,请参见教学系统附带光盘的示例代码。

第二章μCOS-II系统实验

2.1 μCOS-II任务基础实验

2.1.1 实验目的

?理解任务管理的基本原理,了解任务的各个基本状态及其变迁过程;

?掌握μCOS-II中任务管理的基本方法(创建、启动、挂起、解挂任务);

?熟练使用μCOS-II任务管理的基本系统调用。

2.1.2 实验设备

?硬件:Tsinghua Freescale MC9S128XS实验平台,CODEWARRIOR IDE仿真器套件,PC机;

?软件:CodeWarrior IDE for Freescale集成开发环境,Windows 98/2000/NT/XP。

2.1.3 实验内容

建立两个任务AppTask1和AppTask2:任务AppTask1不断地挂起自己,再被任务AppTask2解挂,两个任务不断地切换执行。并在串口打印相应的信息。用户可以通过串口进行观察。

2.1.4 实验原理

一个任务通常是一个无限的循环,由于任务的执行是由操作系统内核调度的,因此任务是绝不会返回的,其返回参数必须定义成void。在μC/OS-Ⅱ中,当一个运行着的任务使一个比它优先级高的任务进入了就绪态,当前任务的CPU使用权就会被抢占,高优先级任务会立刻得到CPU的控制权(在系统允许调度和任务切换的前提下)。μC/OS-Ⅱ可以管理多达64个任务,但目前版本的μC/OS-Ⅱ有两个任务已经被系统占用了(即空闲任务和统计任务)。必须给每个任务赋以不同的优先级,任务的优先级号就是任务编号(ID),优先级可以从0到OS_LOWEST_PRIORITY。优先级号越低,任务的优先级越高。μC/OS-Ⅱ总是运行进入就绪态的优先级最高的任务。

2.1.5 本实验中所用到的μC/OS-II相关函数

1. OSTaskCreate()

建立一个新任务。任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立。中断处理程序中不能建立任务。一个任务可以为无限循环的结构。

函数原型:INT8U OSTaskCreate(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio);

参数说明:task是指向任务代码首地址的指针。

Pdata指向一个数据结构,该结构用来在建立任务时向任务传递参数。

返回值:

OSTaskCreate()的返回值为下述之一:

●OS_NO_ERR:函数调用成功。

●OS_PRIO_EXIST:具有该优先级的任务已经存在。

●OS_PRIO_INV ALID:参数指定的优先级大于OS_LOWEST_PRIO。

●OS_NO_MORE_TCB:系统中没有OS_TCB可以分配给任务了。

2. OSTaskSuspend()

无条件挂起一个任务。调用此函数的任务也可以传递参数OS_PRIO_SELF,挂起调用任务本身。当前任务挂起后,只有其他任务才能唤醒被挂起的任务。任务挂起后,系统会重新进行任务调度,运行

任务的挂起是可以叠加到其他操作上的。例如,任务被挂起时正在进行延时操作,那么任务的唤醒就需要两个条件:延时的结束以及其他任务的唤醒操作。又如,任务被挂起时正在等待信号量,当任务从信号量的等待对列中清除后也不能立即运行,而必须等到被唤醒后。

函数原型:INT8U OSTaskSuspend ( INT8U prio);

参数说明:prio为指定要获取挂起的任务优先级,也可以指定参数OS_PRIO_SELF,挂起任务本身。此时,下一个优先级最高的就绪任务将运行。

返回值:

OSTaskSuspend()的返回值为下述之一:

●OS_NO_ERR:函数调用成功。

●OS_TASK_ SUSPEND_IDLE:试图挂起μC/OS-II中的空闲任务(Idle task)。此为非法操作。

●OS_PRIO_INV ALID:参数指定的优先级大于OS_LOWEST_PRIO或没有设定OS_PRIO_SELF的

值。

●OS_TASK_ SUSPEND _PRIO:要挂起的任务不存在。

3. OSTaskResume()

唤醒一个用OSTaskSuspend()函数挂起的任务。OSTaskResume()也是唯一能“解挂”挂起任务的函数。

函数原型:NT8U OSTaskResume ( INT8U prio);

参数说明:prio指定要唤醒任务的优先级。

返回值:

OSTaskResume ()的返回值为下述之一:

●OS_NO_ERR:函数调用成功。

●OS_TASK_RESUME_PRIO:要唤醒的任务不存在。

●OS_TASK_NOT_SUSPENDED:要唤醒的任务不在挂起状态。

●OS_PRIO_INV ALID:参数指定的优先级大于或等于OS_LOWEST_PRIO。

2.1.6 实验参考程序

static void AppAppTask1(void *pdata)

{

pdata=pdata;

printf("Hello World\n"); /* Print "Hello World" */

for(;;)

{

Flash_Led(7);

OSTimeDlyHMSM(0,0,1,0);

printf("appAppTask1: i will Suspend by myself.\n");

OSTaskSuspend(TASK_1_PRIO);

printf("appAppTask1: i Resumed by AppTask2 .\n");

}

static void AppAppTask2(void *pdata)

{

pdata=pdata;

for(;;)

{

OSTimeDly(100);

printf("appAppTask2: i am executing.\n");

if( OSTaskResume(1) == OS_ERR_NONE )

{

printf("appAppTask2: i Resumed AppTask1\n");

}

Flash_Led(6);

OSTimeDlyHMSM(0,0,0,500);

}

}

static void AppTaskCreate (void) //使1-f的任务处于就绪态,一旦OSstart(),优先级最高的任务获得CPU的使用权

{

INT8U err;

OSTaskCreateExt(AppAppTask1,

(void *)0,

(OS_STK *)&AppAppTask1Stk[TASK_STK_SIZE-1],

TASK_1_PRIO,

TASK_1_PRIO,

(OS_STK *)&AppAppTask1Stk[0],

TASK_STK_SIZE,

(void *)0,

OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

OSTaskNameSet(TASK_1_PRIO, "led", &err);

OSTaskCreateExt(AppAppTask2,

(OS_STK *)&AppAppTask2Stk[TASK_STK_SIZE-1],

TASK_2_PRIO,

TASK_2_PRIO,

(OS_STK *)&AppAppTask2Stk[0],

TASK_STK_SIZE,

(void *)0,

OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

OSTaskNameSet(TASK_2_PRIO, "lcd", &err);

OSTaskCreateExt(AppAppTask3,

(void *)0,

(OS_STK *)&AppAppTask3Stk[TASK_STK_SIZE-1],

TASK_3_PRIO,

TASK_3_PRIO,

(OS_STK *)&AppAppTask3Stk[0],

TASK_STK_SIZE,

(void *)0,

OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

OSTaskNameSet(TASK_3_PRIO, "App_Sensor", &err);

}

2.1.7 实验操作步骤

1. 准备实验环境

使用CODEWARRIOR IDE仿真器连接Tsinghua Freescale MC9S128XS实验平台的主板JTAG接口;使用Tsinghua Freescale MC9S128XS实验平台附带的交叉串口线,连接实验平台主板上的COM0和PC机的串口(一般PC只有一个串口,如果有多个请自行选择,笔记本没有串口设备的可购买USB转串口适配器扩充);使用Tsinghua Freescale MC9S128XS实验平台附带的电源适配器,连接实验平台主板上的电源接口。

2. 串口接收设置

在PC机上运行windows自带的超级终端串口通信程序,或者使用实验平台附带光盘内设置好了的超级终端,设置超级终端:波特率19200、1位停止位、无校验位、无硬件流控制,或者使用其它串口通信程序。(注:超级终端串口的选择根据用户的PC串口硬件不同,请自行选择,如果PC机只有一个串口,一般是COM1)

3. 打开实验例程

1)双击打开实验例程目录\03-Examples\uCOS-II实验\2.1_Task_test\project目录下的uCOS-STM32.Uv2例程,编译链接工程;

2)打开Flash 菜单>Download,将程序下载到开发板的Flash 中,运行,观察串口输出的情况。

4. 观察实验结果

在PC机上观察超级终端程序主窗口,可以看到如下界面:任务波特率19200和AppTask2将被轮流调用。

1)参考源代码,添加一个任务,使三个任务轮流调用。

2)利用任务控制函数,例如:OSTaskSuspend(),OSTaskResume(),来完成任务的轮流调用。

2.2 优先级反转实验

2.2.1 实验目的

? 理解互斥、优先级等概念;

? 掌握在基于优先级的可抢占嵌入式实时操作系统的应用中,出现优先级反转现象的原理。 ? 通过本实验,掌握如何避免优先级的反转。

2.2.2 实验设备

? 硬件:Tsinghua Freescale MC9S128XS 实验平台,CODEWARRIOR IDE 仿真器套件,PC 机; ? 软件:CodeWarrior IDE for Freescale 集成开发环境,Windows 98/2000/NT/XP 。

2.2.3 实验内容

1)设计3个应用任务AppTask1~AppTask3,其优先级逐渐降低,任务AppTask1的优先级最高。 2)除任务AppTask2外,其它应用任务都要使用同一种资源,该资源必须被互斥使用。为此,创建一个信号量mutex 来模拟该资源。虽然μC/OS -Ⅱ在创建信号量时可以选择采用防止优先级反转的策略,但在本实验中我们不使用这种策略。

3)应用任务的执行情况如图2-1所示:

任务1

任务2 任务3

图2-1

注意:图中的栅格并不代表严格的时间刻度,而仅仅表现各个任务启动和执行的相对先后关系。

2.2.4 实验原理

在本实验中,要体现嵌入式实时内核的优先级抢占调度的策略,并显现由于共享资源的互斥访问而出现的优先级反转现象。

务阻塞,并等待低优先级任务执行的现象。高优先级任务需要等待低优先级任务释放资源,而低优先级任务又正在等待中等优先级任务,这种现象就被称为优先级反转。两个任务都试图访问共享资源是出现优先级反转最通常的情况。为了保证一致性,这种访问应该是顺序进行的。如果高优先级任务首先访问共享资源,则会保持共享资源访问的合适的任务优先级顺序;但如果是低优先级任务首先获得共享资源的访问,然后高优先级任务请求对共享资源的访问,则高优先级任务被阻塞,直到低优先级任务完成对共享资源的访问。

2.2.5 本实验中所用到的μC/OS-II相关函数

1. OSSemCreate()

该函数建立并初始化一个信号量,信号量的作用如下:

●允许一个任务和其他任务或者中断同步

●取得设备的使用权

●标志事件的发生

函数原型:OSSemCreate( INT16U value);

参数说明:value参数是所建立的信号量的初始值,可以取0到65535之间的任何值。

返回值:OSSemCreate()函数返回指向分配给所建立的信号量的控制块的指针。如果没有可用的控制块,OSSemCreate()函数返回空指针。

2. OSSemPend()

该函数用于任务试图取得设备的使用权、任务需要和其他任务或中断同步、任务需要等待特定事件的发生的场合。如果任务调用OSSemPend()函数时,信号量的值大于零,OSSemPend()函数递减该值并返回该值。如果调用时信号量值等于零,OSSemPend()函数将任务加入该信号量的等待队列。OSSemPend()函数挂起当前任务直到其他的任务或中断设置信号量或超出等待的预期时间。如果在预期的时钟节拍内信号量被设置,μC/OS-Ⅱ默认让最高优先级的任务取得信号量并回到就绪状态。一个被OSTaskSuspend()函数挂起的任务也可以接受信号量,但这个任务将一直保持挂起状态直到通过调用OSTaskResume()函数恢复该任务的运行。

函数原型:Void OSSemPend ( OS_EVNNT *pevent, INT16U timeout, int8u *err );

参数说明:

pevent 是指向信号量的指针。该指针的值在建立该信号量时可以得到。(参考OSSemCreate()函数)。

Timeout 允许一个任务在经过了指定数目的时钟节拍后还没有得到需要的信号量时恢复就绪状态。如果该值为零表示任务将持续地等待信号量,最大的等待时间为65535个时钟节拍。这个时间长度并不是非常严格的,可能存在一个时钟节拍的误差。

Err 是指向包含错误码的变量的指针。

返回值:

OSSemPend()函数返回的错误码可能为下述几种:

●OS_NO_ERR :信号量不为零。

●OS_TIMEOUT :信号量没有在指定数目的时钟周期内被设置。

●OS_ERR_PEND_ISR :从中断调用该函数。虽然规定了不允许从中断调用该函数,但μC/OS-Ⅱ仍

然包含了检测这种情况的功能。

●OS_ERR_EVENT_TYPE :pevent 不是指向信号量的指针。

3. OSemPost()

该函数用于设置指定的信号量。如果指定的信号量是零或大于零,OSSemPost()函数递增该信号量的值并返回。如果有任何任务在等待该信号量,则最高优先级的任务将得到信号量并进入就绪状态。任务调度函数将进行任务调度,决定当前运行的任务是否仍然为最高优先级的就绪任务。

函数原型:INT8U OSSemPost(OS_EVENT *pevent);

参数说明:pevent 是指向信号量的指针。该指针的值在建立该信号量时可以得到。(参考OSSemCreate()函数)。

返回值:

OSSemPost()函数的返回值为下述之一:

●OS_NO_ERR :信号量被成功地设置

●OS_SEM_OVF :信号量的值溢出

●OS_ERR_EVENT_TYPE :pevent 不是指向信号量的指针

4. OSTimeDly()

该函数用于将一个任务延时若干个时钟节拍。如果延时时间大于0,系统将立即进行任务调度。延时时间的长度可从0到65535个时钟节拍。延时时间0表示不进行延时,函数将立即返回调用者。延时的具体时间依赖于系统每秒钟有多少个时钟节拍(由文件SO_CFG.H中的OS_TICKS_PER_SEC宏来设定)。

函数原型:void OSTimeDly ( INT16U ticks);

参数说明:ticks为要延时的时钟节拍数。

返回值:无

2.2.6实验参考程序

static void AppTask1(void *pdata)

{

INT8U err;

pdata=pdata;

for(;;)

{

printf("AppTask1 is waitting a event.\n");

OSTimeDly(200); /* Delay 200 clock tick */

printf("The event of AppTask1 come.\n");

printf("AppTask1 is try to get semaphores.\n");

OSSemPend(EventSem1,0,&err); /* Acquire semaphores */ switch(err)

{

case OS_ERR_NONE:

printf("AppTask1 has got the semaphores.\n");

Flash_Led(7);

break;

default:

printf("AppTask1 is suspended.\n");

}

OSTimeDly(200); /* Delay 200 clock tick */ }

static void AppTask2(void *pdata)

{

INT8U err;

pdata=pdata;

for(;;)

{

Flash_Led(6);

OSSemPost(EventSem1);

printf("AppTask2 release semaphores.\n"); /* Release semaphores */

OSTimeDly(1000); /* Delay 1000 clock tick */

}

}

static void AppTaskCreate (void) //使1-f的任务处于就绪态,一旦OSstart(),优先级最高的任务获得CPU的使用权

{

INT8U err;

OSTaskCreateExt(AppAppTask1,

(void *)0,

(OS_STK *)&AppAppTask1Stk[TASK_STK_SIZE-1],

TASK_1_PRIO,

TASK_1_PRIO,

(OS_STK *)&AppAppTask1Stk[0],

TASK_STK_SIZE,

(void *)0,

OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

OSTaskNameSet(TASK_1_PRIO, "led", &err);

OSTaskCreateExt(AppAppTask2,

(void *)0,

(OS_STK *)&AppAppTask2Stk[TASK_STK_SIZE-1],

TASK_2_PRIO,

TASK_2_PRIO,

(OS_STK *)&AppAppTask2Stk[0],

TASK_STK_SIZE,

(void *)0,

OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

OSTaskNameSet(TASK_2_PRIO, "lcd", &err);

OSTaskCreateExt(AppAppTask3,

(void *)0,

(OS_STK *)&AppAppTask3Stk[TASK_STK_SIZE-1],

TASK_3_PRIO,

TASK_3_PRIO,

(OS_STK *)&AppAppTask3Stk[0],

TASK_STK_SIZE,

(void *)0,

OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

OSTaskNameSet(TASK_3_PRIO, "App_Sensor", &err);

}

2.2.7 实验操作步骤

1. 准备实验环境

使用CODEWARRIOR IDE仿真器连接Tsinghua Freescale MC9S128XS实验平台的主板JTAG接口;使用Tsinghua Freescale MC9S128XS实验平台附带的交叉串口线,连接实验平台主板上的COM0和PC机的串口(一般PC只有一个串口,如果有多个请自行选择,笔记本没有串口设备的可购买USB转串口适配器扩充);使用Tsinghua Freescale MC9S128XS实验平台附带的电源适配器,连接实验平台主板上的电源接口。

2. 串口接收设置

在PC机上运行windows自带的超级终端串口通信程序,或者使用实验平台附带光盘内设置好了的超级终端,设置超级终端:波特率19200、1位停止位、无校验位、无硬件流控制,或者使用其它串口通信程序。(注:超级终端串口的选择根据用户的PC串口硬件不同,请自行选择,如果PC机只有一个串口,一般是COM1)

3. 打开实验例程

1)将目录\03-Examples\uCOS-II实验\2.2_Priority_test下的文件main.c拷贝至03-Examples\uCOS-II实验\2.1_Task_test\src;

2)双击打开实验例程目录\03-Examples\uCOS-II实验\2.1_Task_test\project目录下的uCOS-STM32.Uv2例程,编译链接工程;

3)打开Flash 菜单>Download,将程序下载到开发板的Flash 中,运行,观察串口输出的情况。

4. 观察实验结果

5.练习题

利用μC/OS-Ⅱ在创建信号量时的防止优先级反转策略,看实验结果,是否能解决优先级反转问题。

2.3 信号量实验

2.3.1 实验目的

?掌握在基于嵌入式实时操作系统μC/OS-II的应用中,任务使用信号量的一般原理。

?通过经典的哲学家就餐实验,了解如何利用信号量来对共享资源进行互斥访问。

2.3.2 实验设备

?硬件:Tsinghua Freescale MC9S128XS实验平台,CODEWARRIOR IDE仿真器套件,PC机;

?软件:CodeWarrior IDE for Freescale集成开发环境,Windows 98/2000/NT/XP。

2.3.3 实验设计

五个哲学家任务(ph1、ph2、ph3、ph4、ph5)主要有两种过程:思考(即睡眠一段时间)和就餐。每个哲学家任务在就餐前必须申请并获得一左一右两支筷子,就餐完毕后释放这两支筷子。五个哲学家围成一圈,每两人之间有一支筷子。一共有五支筷子,在该实验中用了五个互斥信号量来代表。如图所示:

2.3.4 本实验中所用到的μC/OS-II相关函数

参考实验2.2.

2.3.5实验参考程序

void AppTask1(void *Id)

{

while(1)

{

OSTimeDly(500);

OSSemPend(sem1, 0, &err);

OSSemPend(sem5, 0, &err);

sprintf(str," philosopher1 is eating!\n");

printf(str);

OSTimeDly(1000);

sprintf(str," philosopher1 finishes eating!\n");

printf(str);

OSSemPost(sem5);

}

}

void AppTask2 (void *Id)

{

while(1)

{

OSTimeDly(900);

OSSemPend(sem1, 0, &err);

OSSemPend(sem2, 0, &err);

sprintf(str," philosopher2 is eating!\n");

printf(str);

OSTimeDly(1000);

sprintf(str," philosopher2 finishes eating!\n");

printf(str);

OSSemPost(sem1);

OSSemPost(sem2);

}

}

void AppTask3 (void *Id)

{

while(1)

{

OSTimeDly(600);

OSSemPend(sem2, 0, &err);

OSSemPend(sem3, 0, &err);

sprintf(str," philosopher3 is eating!\n");

printf(str);

OSTimeDly(1000);

sprintf(str," philosopher3 finishes eating!\n");

printf(str);

OSSemPost(sem2);

OSSemPost(sem3);

}

}

void Task4 (void *Id)

{

while(1)

{

OSTimeDly(700);

OSSemPend(sem3, 0, &err);

OSSemPend(sem4, 0, &err);

sprintf(str," philosopher4 is eating!\n");

printf(str);

OSTimeDly(1000);

sprintf(str," philosopher4 finishes eating!\n");

printf(str);

OSSemPost(sem3);

}

}

void Task5 (void *Id)

{

while(1)

{

OSTimeDly(800);

OSSemPend(sem4, 0, &err);

OSSemPend(sem5, 0, &err);

sprintf(str," philosopher5 is eating!\n");

printf(str);

OSTimeDly(1000);

sprintf(str," philosopher5 finishes eating!\n");

printf(str);

OSSemPost(sem4);

OSSemPost(sem5);

}

}

void TaskInit (void *Id)

{

char Id1 = '1';

char Id2 = '2';

char Id3 = '3';

char Id4 = '4';

char Id5 = '5';

/*

* create the first Semaphore in the pipeline with 1

* to get the task started.

*/

UART_sem = OSSemCreate(1);

sem1 = OSSemCreate(1);

sem2 = OSSemCreate(1);

sem3 = OSSemCreate(1);

sem4 = OSSemCreate(1);

sem5 = OSSemCreate(1);

/*

* create the tasks in uC/OS and assign decreasing

* priority to them

*/

OSTaskCreate(AppTask1, (void *)&Id1, &Stack1[STACKSIZE - 1], 5); OSTaskCreate(AppTask2, (void *)&Id2, &Stack2[STACKSIZE - 1], 9); OSTaskCreate(AppTask3, (void *)&Id3, &Stack3[STACKSIZE - 1], 6); OSTaskCreate(Task4, (void *)&Id4, &Stack4[STACKSIZE - 1], 7);

OSTaskCreate(Task5, (void *)&Id5, &Stack5[STACKSIZE - 1], 8);

OSTaskDel(OS_PRIO_SELF); // Delete current task

}

2.3.6 实验操作步骤

1. 准备实验环境

使用CODEWARRIOR IDE仿真器连接Tsinghua Freescale MC9S128XS实验平台的主板JTAG接口;使用Tsinghua Freescale MC9S128XS实验平台附带的交叉串口线,连接实验平台主板上的COM0和PC机的串口(一般PC只有一个串口,如果有多个请自行选择,笔记本没有串口设备的可购买USB转串口适配器扩充);使用Tsinghua Freescale MC9S128XS实验平台附带的电源适配器,连接实验平台主板上的电源接口。

2. 串口接收设置

在PC机上运行windows自带的超级终端串口通信程序,或者使用实验平台附带光盘内设置好了的超级终端,设置超级终端:波特率19200、1位停止位、无校验位、无硬件流控制,或者使用其它串口通信程序。(注:超级终端串口的选择根据用户的PC串口硬件不同,请自行选择,如果PC机只有一个串口,一般是COM1)

3. 打开实验例程

1)将目录\03-Examples\uCOS-II实验\2.3_Semaphore_test下的文件main.c拷贝至03-Examples\uCOS-II实验\2.1_Task_test\src;

2)双击打开实验例程目录\03-Examples\uCOS-II实验\2.1_Task_test\project目录下的uCOS-STM32.Uv2例程,编译链接工程;

3)打开Flash 菜单>Download,将程序下载到开发板的Flash 中,运行,观察串口输出的情况。

4. 观察实验结果

在PC机上观察超级终端程序主窗口,可以看到如下界面:

相关主题
文本预览
相关文档 最新文档