ucosII嵌入式实时操作系统实验.docx
《ucosII嵌入式实时操作系统实验.docx》由会员分享,可在线阅读,更多相关《ucosII嵌入式实时操作系统实验.docx(19页珍藏版)》请在冰豆网上搜索。
ucosII嵌入式实时操作系统实验
嵌入式实时操作系统实验报告
多任务的创建及运行
系别计算机与电子系
专业班级电子0901班
学生姓名高傲
指导教师黄向宇
提交日期2012年4月1日
一、实验目的
1.熟悉并掌握基于uC/OS-II的开发工具、工程管理工具
2.了解uC/OS-II的文件结构、文件之间的依赖关系。
3.掌握创建多任务的方法及对任务进行相关操作的技巧。
二、实验内容
1.建立并熟悉BorlandC编译及调试环境
2.使用课本配套光盘中的例程运行并修改,观察多任务的运行状态,尝试对其中的任务进行挂起并恢复、删除及查询等操作,观察运行结果.
3.完成课后练习题,P92页13-17题,至少完成其中任意两题。
三、实验原理
1.编译环境
TurboC是Borland公司开发的DOS下16位C语言集成开发工具。
有2.0和3.0版本,2.0只支持C语言编译不支持鼠标操作,而3.0版本可以支持C/C++两种语言编译,而且还支持鼠标和//注释方式;TC2.0是80年代开发的,使用了很多年一直到现在WINDOWS系统才逐渐退出舞台。
TurboC2.0不仅是一个快捷、高效的编译程序,同时还有一个易学、易用的集成开发环境。
使用TurboC2.0无需独立地编辑、编译和连接程序,就能建立并运行C语言程序。
因为这些功能都组合在Turbo2.0的集成开发环境内,并且可以通过一个简单的主屏幕使用这些功能。
一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:
Delphi的make,VisualC++的nmake,Linux下GNU的make。
⏹Make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作。
⏹而makefile文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。
⏹makefile文件是许多编译器--包括WindowsNT下的编译器--维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改makefile文件而已。
2.uC/OS-II文件体系
uC/OS-II包括三个部分:
1)核心代码部分,这部分代码与处理器无关,包括七个源代码文件和一个头文件,这七个源代码文件负责的功能分别是内核管理、事件管理、消息队列管理、存储管理、消息管理、信号量处理、任务调度和定时管理。
2)设置代码部分,包括两个头文件,用来配置事件控制块的数目以及是否包含消息管理相关代码等。
3)处理器相关的移植代码部分,这部分包括一个头文件,一个汇编文件和一个C代码文件,在uC/OS-II的移植过程中,用户所需要关注的就是这部分文件。
3.uC/OS-II任务的创建,OSTaskCreate()
想让µC/OS-Ⅱ管理用户的任务,用户必须要先建立任务。
用户可以通过传递任务地址和其它参数到以下两个函数之一来建立任务:
OSTaskCreate()或OSTaskCreateExt()。
OSTaskCreate()与µC/OS是向下兼容的,OSTaskCreateExt()是OSTaskCreate()的扩展版本,提供了一些附加的功能。
用两个函数中的任何一个都可以建立任务。
任务可以在多任务调度开始前建立,也可以在其它任务的执行过程中被建立。
在开始多任务调度(即调用OSStart())前,用户必须建立至少一个任务。
任务不能由中断服务程序(ISR)来建立。
OSTaskCreate()的代码如程序清单L4.1所述。
从中可以知道,OSTaskCreate()需要四个参数:
task是任务代码的指针,pdata是当任务开始执行时传递给任务的参数的指针,ptos是分配给任务的堆栈的栈顶指针(参看4.02,任务堆栈),prio是分配给任务的优先级。
程序清单L4.1OSTaskCreate()
INT8UOSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT8Uprio)
{
void*psp;
INT8Uerr;
if(prio>OS_LOWEST_PRIO){
(1)
return(OS_PRIO_INVALID);
}
OS_ENTER_CRITICAL();
if(OSTCBPrioTbl[prio]==(OS_TCB*)0){
(2)
OSTCBPrioTbl[prio]=(OS_TCB*)1;(3)
OS_EXIT_CRITICAL();(4)
psp=(void*)OSTaskStkInit(task,pdata,ptos,0);(5)
err=OSTCBInit(prio,psp,(void*)0,0,0,(void*)0,0);(6)
if(err==OS_NO_ERR){(7)
OS_ENTER_CRITICAL();
OSTaskCtr++;(8)
OSTaskCreateHook(OSTCBPrioTbl[prio]);(9)
OS_EXIT_CRITICAL();
if(OSRunning){(10)
OSSched();(11)
}
}else{
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio]=(OS_TCB*)0;(12)
OS_EXIT_CRITICAL();
}
return(err);
}else{
OS_EXIT_CRITICAL();
return(OS_PRIO_EXIST);
}
}
挂起任务,OSTaskSuspend()
有时候将任务挂起是很有用的。
挂起任务可通过调用OSTaskSuspend()函数来完成。
被挂起的任务只能通过调用OSTaskResume()函数来恢复。
任务挂起是一个附加功能。
也就是说,如果任务在被挂起的同时也在等待延时的期满,那么,挂起操作需要被取消,而任务继恢复任务,OSTaskResume()
在上一节中曾提到过,被挂起的任务只有通过调用OSTaskResume()才能恢复。
OSTaskResume()函数的代码如程序清单L4.17所示。
因为OSTaskSuspend()不能挂起空闲任务,所以必须得确认用户的应用程序不是在恢复空闲任务[L4.17
(1)]。
注意,这个测试也可以确保用户不是在恢复优先级为OS_PRIO_SELF的任务(OS_PRIO_SELF被定义为0xFF,它总是比OS_LOWEST_PRIO大)。
续等待延时期满,并转入就绪状态。
任务可以挂起自己或者其它任务。
获得有关任务的信息,OSTaskQuery()
用户的应用程序可以通过调用OSTaskQuery()来获得自身或其它应用任务的信息。
实际上,OSTaskQuery()获得的是对应任务的OS_TCB中内容的拷贝。
用户能访问的OS_TCB的数据域的多少决定于用户的应用程序的配置(参看OS_CFG.H)。
由于µC/OS-Ⅱ是可裁剪的,它只包括那些用户的应用程序所要求的属性和功能。
改变任务的优先级,OSTaskChangePrio()
在用户建立任务的时候会分配给任务一个优先级。
在程序运行期间,用户可以通过调用OSTaskChangePrio()来改变任务的优先级。
换句话说,就是µC/OS-Ⅱ允许用户动态的改变任务的优先级。
四、实验步骤
1.准备实验环境
先在C盘上建一个名称为bc31的目录,然后到互联网上下载一个BorlandC++3.1并安装到目录bc31中(因为书中的代码是用BorlandC++3.1编译的),接着再把实验程序文件夹Software复制到C盘上。
BC31实验环境的建立步骤如下:
2.打开实验例程
1)运行C:
\SOFTWARE\SOFTWARE\uCOS-II\例2-9\Bc31\TEST.exe,观察运行结果;
运行结果如下:
2)分析整个实验文件目录结构及实验参考程序。
实验文件目录结构:
一个实验例程包含一个bc31文件,bc31文件又包含有5个代码有关文件:
LST,OBJ,SOURCE,TEST,WORK等。
其中OBJ里面包含有源程序编译后的相关文件。
SOURCE里面包含了源文件和相关的配置文件,可以在里面修改源文件,TEST里面含有编译后的测试文件和MAKETEST可以对修改后的源程序进行编译,而后生成新的可执行文件TEST.exe。
(具体做法为先删掉旧文件,修改好文件确认无误后用MAKETEST再进行编译即可生成新的可执行文件)。
3)按照课后习题要求编写程序并编译运行
1.课后习题第13题源程序:
#include"includes.h"
#defineTASK_STK_SIZE512//任务堆栈长度
OS_STKMyTaskStk[TASK_STK_SIZE];//定义任务堆栈区
OS_STKYouTaskStk[TASK_STK_SIZE];//定义任务堆栈区
OS_STKHisTaskStk[TASK_STK_SIZE];//定义任务堆栈区
INT16Skey;//用于退出uCOS_II的键
INT8Ux=0,y=0;//字符显示位置
INT8Utime=0;
voidMyTask(void*data);//声明任务
voidYouTask(void*data);//声明任务
voidHisTask(void*data);
/************************主函数*********************************************/
voidmain(void)
{
char*s_M="M";//定义要显示的字符
OSInit();//初始化uCOS_II
PC_DOSSaveReturn();//保存Dos环境
PC_VectSet(uCOS,OSCtxSw);//安装uCOS_II中断
OSTaskCreate(MyTask,//创建任务MyTask
s_M,//给任务传递参数
&MyTaskStk[TASK_STK_SIZE-1],//设置任务堆栈栈顶指针
0);//使任务MyTask的优先级别为0
OSStart();//启动uCOS_II的多任务管理
}
/***********************任务MyTask*******************************************/
voidMyTask(void*pdata)
{
char*s_Y="Y";//定义要显示的字符
#ifOS_CRITICAL_METHOD==3
OS_CPU_SRcpu_sr;
#endif
pdata=pdata;
OS_ENTER_CRITICAL();
PC_VectSet(0x08,OSTickISR);//安装uCOS_II时钟中断向量
PC_SetTickRate(OS_TICKS_PER_SEC);//设置uCOS_II时钟频率
OS_EXIT_CRITICAL();
OSStatInit();//初始化uCOS_II的统计任务
OSTaskCreate(YouTask,//创建任务MyTask
s_Y,//给任务传递参数
&YouTaskStk[TASK_STK_SIZE-1],//设置任务堆栈栈顶指针
2);//使任务MyTask的优先级别为2
for(;;)
{
if(x>50)
{
x=0;
y+=2;
}
PC_DispChar(x,y,//显示字符的位置
*(char*)pdata,
DISP_BGND_BLACK+DISP_FGND_RED);
x+=1;
//如果按下Esc键则退出uCOS_II
if(PC_GetKey(&key)==TRUE)
{
if(key==0x1B)
{
PC_DOSReturn();
}
}
OSTimeDlyHMSM(0,0,2,0);//等待
}
}
voidYouTask(void*pdata)
{
char*s_Y="H";//定义要显示的字符
OSTaskCreate(HisTask,//创建任务MyTask
s_Y,//给任务传递参数
&HisTaskStk[TASK_STK_SIZE-1],//设置任务堆栈栈顶指针
3);//使任务MyTask的优先级别为0
for(;;)
{
if(x>50)
{
x=0;
y+=2;
}
PC_DispChar(x,y,//显示字符的位置
*(char*)pdata,
DISP_BGND_BLACK+DISP_FGND_WHITE);
x+=1;
//如果按下Esc键则退出uCOS_II
if(PC_GetKey(&key)==TRUE)
{
if(key==0x1B)
{
PC_DOSReturn();
}
}
OSTimeDlyHMSM(0,0,4,0);//等待
}
}
/************************任务YouTask*****************************************/
voidHisTask(void*pdata)
{
char*s_Y="G";//定义要显示的字符
OSTaskCreate(MyTask,//创建任务MyTask
s_Y,//给任务传递参数
&MyTaskStk[TASK_STK_SIZE-1],//设置任务堆栈栈顶指针
4);//使任务MyTask的优先级别为4
for(;;)
{
if(x>50)
{
x=0;
y+=2;
}
PC_DispChar(x,y,//显示字符的位置
*(char*)pdata,
DISP_BGND_BLACK+DISP_FGND_WHITE);
x+=1;
//如果按下Esc键则退出uCOS_II
if(PC_GetKey(&key)==TRUE)
{
if(key==0x1B)
{
PC_DOSReturn();
}
}
OSTimeDlyHMSM(0,0,6,0);//等待
}
}
2.课后习题第15题源程序:
#include"includes.h"
#defineTASK_STK_SIZE512//任务堆栈长度
OS_STKMyTaskStk[TASK_STK_SIZE];//定义任务堆栈区
OS_STKYouTaskStk[TASK_STK_SIZE];//定义任务堆栈区
OS_STKHerTaskStk[TASK_STK_SIZE];//定义任务堆栈区
INT16Skey;//用于退出uCOS_II的键
INT8Ux=0,y=0;//字符显示位置
voidMyTask(void*data);//声明任务
voidYouTask(void*data);//声明任务
voidHerTask(void*data);//声明任务
/************************主函数*********************************************/
voidmain(void)
{
char*s_M="M";//定义要显示的字符
OSInit();//初始化uCOS_II
PC_DOSSaveReturn();//保存Dos环境
PC_VectSet(uCOS,OSCtxSw);//安装uCOS_II中断
OSTaskCreate(MyTask,//创建任务MyTask
s_M,//给任务传递参数
&MyTaskStk[TASK_STK_SIZE-1],//设置任务堆栈栈顶指针
0);//使任务MyTask的优先级别为0
OSStart();//启动uCOS_II的多任务管理
}
/***********************任务MyTask*******************************************/
voidMyTask(void*pdata)
{
char*s_Y="Y";//定义要显示的字符
char*s_H="H";//定义要显示的字符
char*s="YouandHerTasksdeletethemselveattherighttime";
#ifOS_CRITICAL_METHOD==3
OS_CPU_SRcpu_sr;
#endif
pdata=pdata;
OS_ENTER_CRITICAL();
PC_VectSet(0x08,OSTickISR);//安装uCOS_II时钟中断向量
PC_SetTickRate(OS_TICKS_PER_SEC);//设置uCOS_II时钟频率
OS_EXIT_CRITICAL();
OSStatInit();//初始化uCOS_II的统计任务
OSTaskCreate(YouTask,//创建任务YouTask
s_Y,//给任务传递参数
&YouTaskStk[TASK_STK_SIZE-1],//设置任务堆栈栈顶指针
1);//使任务YouTask的优先级别为1
OSTaskCreate(HerTask,//创建任务HerTask
s_H,//给任务传递参数
&HerTaskStk[TASK_STK_SIZE-1],//设置任务堆栈栈顶指针
2);//使任务HerTask的优先级别为2
for(;;)
{
if(x>18)
{
while(OSTaskDelReq
(1)!
=OS_TASK_NOT_EXIST&&OSTaskDelReq
(2)!
=OS_TASK_NOT_EXIST)
{
PC_DispStr(10,6,//显示字符的位置
s,
DISP_BGND_BLACK+DISP_FGND_RED);
OSTimeDly
(1);
}
}
if(x>50)
{
x=0;
y+=2;
}
PC_DispChar(x,y,//显示字符的位置
*(char*)pdata,
DISP_BGND_BLACK+DISP_FGND_RED);
x+=1;
//如果按下Esc键则退出uCOS_II
if(PC_GetKey(&key)==TRUE)
{
if(key==0x1B)
{
PC_DOSReturn();
}
}
OSTimeDlyHMSM(0,0,4,0);//等待
}
}
/************************任务YouTask*****************************************/
voidYouTask(void*pdata)
{
#ifOS_CRITICAL_METHOD==3
OS_CPU_SRcpu_sr;
#endif
char*s1="YouTask:
Imustdeletemyself";
char*s2="YouTask:
Ihavedeletemyself";
pdata=pdata;
for(;;)
{
if(OSTaskDelReq(OS_PRIO_SELF)==OS_TASK_DEL_REQ)
{
PC_DispStr(10,10,//显示字符的位置
s1,
DISP_BGND_BLACK+DISP_FGND_BLUE);
OSTimeDlyHMSM(0,0,10,0);
PC_DispStr(10,12,//显示字符的位置
s2,
DISP_BGND_BLACK+DISP_FGND_BLUE);
OSTaskDel(OS_PRIO_SELF);
}
if(x>50)
{
x=0;
y+=2;
}
PC_DispChar(x,y,//显示字符的位置
*(char*)pdata,
DISP_BGND_BLACK+DISP_FGND_BLUE);
x+=1;
OSTimeDlyHMSM(0,0,4,0);//等待
}
}
/************************任务HerTask*****************************************/
voidHerTask(void*pdata)
{
#ifOS_CRITICAL_METHOD==3
OS_CPU_SRcpu_sr;
#endif
char*s3="HerTask:
Imustdeletemyself";
char*s4="HerTask:
Ihavedeletemyself";
pdata=pdata;
for(;;)
{
if(OSTaskDelReq(OS_PRIO_SELF)==OS_TASK_DEL_REQ)
{
PC_DispStr(10,14,//显示字符的位置
s3,
DISP_BGND_BLACK+DISP_FGND_YELLOW);