北航ARM9实验报告实验4多任务综合实验.docx
《北航ARM9实验报告实验4多任务综合实验.docx》由会员分享,可在线阅读,更多相关《北航ARM9实验报告实验4多任务综合实验.docx(12页珍藏版)》请在冰豆网上搜索。
北航ARM9实验报告实验4多任务综合实验
实验四多任务综合实验
一、实验目的
学习周期任务、任务的同步和任务间通信。
二、实验内容
1.运行实验十,删除任务四、任务定义和OSTaskCreate(Task4…),任务三for循环体内仅保留以下两句BSPprintf(0,“runtask3\n”);OSTimeDly(3000),在超级终端上观察任务运行情况。
2.使用系统定时中断实现周期任务,任务1、2、3进入for循环就挂起,在定时钩子函数中定时1秒、2秒和4秒后将其恢复。
3.创建信号量管理数组实现任务间同步,在主函数中定义一个INT16U的两维数组a[2][3],不同的任务往数组内写不同的值,连同任务号一起打印在超级终端上。
4.创建消息邮箱实现任务间通信,Task1记录任务执行的次数,通过消息邮箱在Task2里显示。
5.附加题文件的使用
三、实验设备
硬件:
ARM嵌入式开发平台、用于ARM920T的JTAG仿真器、PC机Pentium100以上。
软件:
PC机操作系统Win2000或WinXP、ARMADS1.2集成开发环境、仿真器驱动程序、超级终端通讯程序。
四、实验原理
1、任务间通信的管理:
事件控制块ECB。
2、同步与互斥:
为了实现资源共享,一个操作系统必须提供临界区操作的功能。
μC/OS采用关闭/打开中断的方式来处理临界区代码,从而避免竞争条件,实现任务间的互斥。
3、信号量:
信号量在多任务系统中的功能,实现对共享资源的互斥访问(包括单个共享资源或多个相同的资源),实现任务之间的行为同步。
4、邮箱:
一个任务或ISR可以通过邮箱向另一个任务发送一个指针型的变量,该指针指向一个包含了特定“消息”(message)的数据结构;
5、消息队列:
消息队列可以使一个任务或ISR向另一个任务发送多个以指针方式定义的变量。
图4.1任务、ISR和消息邮箱的关系
五、实验步骤
1.以实验十为模板。
2.将任务函数内的OSTimeDly()删除,在打印语句之前悬挂任务1~3,OSTaskSuspend(Taskn_Prio),按以下路径ucos-ii->arch->os_cpu_c.c找到钩子函数voidOSTimeTickHook(void),用计数器控制恢复任务操作,编写OSTaskResume(Taskn_Prio);
3.信号量管理声明信号量OS_EVENT*Fun_Semp;
在Main函数里创建信号量Fun_Semp=OSSemCreate
(1);
在各个Task里执行下列操作
OSSemPend(Fun_Semp,0,&err);
………….
OSSemPost(Fun_Semp);
定义变量INT8Uerr;
4.定义事件控制块指针OS_EVENT*Str_Box,
在main函数里创建消息邮箱,Str_Box=OSMboxCreate((void*)
在Task1里发送消息Times+=1;s=&Times;OSMboxPost(Str_Box,s);
在Task2里请求消息邮箱ss=OSMboxPend(Str_Box,0,&err);
printf("%d\n",*ss);
5.文件的使用
文件使用的关键是加载文本文件,用记事本创建test.txt文件,文件的内容不包含汉字。
运行实验十三,此时LCD上没有任何显示。
打开超级终端,按回车键,显示/sys>用mkdir创建ucos子目录,在ucos下再创建fj子目录,用cd进入/sys/ucos/fj>,在该目录下执行命令dltest.txt–d,按回车键,加载test.txt。
再运行文件十三,在LCD上即可观察你编写的文本文件。
六、实验程序
(1)多任务源程序
#include"../ucos-ii/includes.h"/*uC/OSinterface*/
#include"../ucos-ii/add/osaddition.h"
#include"../inc/drivers.h"
#include"../inc/macro.h"
#include"../inc/lcd320.h"
#include"../inc/sys/lib.h"
#include"../src/gui/gui.h"
#include
#include
OS_EVENT*MboxSem;
OS_EVENT*Fun_Semp;
OS_EVENT*Str_Box;
///******************任务定义***************///
#defineSYS_Task_Prio1
voidSYS_Task(void*Id);*/
OS_STKtask1_Stack[STACKSIZE]={0,};//Main_Test_Task堆栈
voidTask1(void*Id);//Main_Test_Task
#defineTask1_Prio12
OS_STKtask2_Stack[STACKSIZE]={0,};//test_Test_Task堆栈
voidTask2(void*Id);//test_Test_Task
#defineTask2_Prio15
OS_STKtask3_Stack[STACKSIZE]={0,};//test_Test_Task堆栈
voidTask3(void*Id);//test_Test_Task
#defineTask3_Prio17
externU32LCDBufferII2[LCDHEIGHT][LCDWIDTH];
INT16Ua[2][3];
int*s,*ss,Times=0;
INT8Uerr;
//BOOLEANac_key=1;
#definerUTRSTAT0(*(volatileunsigned*)0x50000010)
#defineRdURXH0()(*(volatileunsignedchar*)0x50000024)
/**************已经定义的OS任务*************
#defineSYS_Task_Prio1
#defineTouch_Screen_Task_Prio9
#defineMain_Task_Prio12
#defineKey_Scan_Task_Prio58
#defineLcd_Fresh_prio59
#defineLed_Flash_Prio60
***************************************/////////
///*****************事件定义*****************///
/////////////////////////////////////////////////////
//Mainfunction.//
////////////////////////////////////////////////////
intmain(void)
{
ARMTargetInit();//dotarget(uHALbasedARMsystem)initialisation//
OSInit();//neededbyuC/OS-II//
Fun_Semp=OSSemCreate
(1);
Str_Box=OSMboxCreate((void*)0);
OSTaskCreate(Task1,(void*)0,(OS_STK*)&task1_Stack[STACKSIZE-1],Task1_Prio);
OSTaskCreate(Task2,(void*)0,(OS_STK*)&task2_Stack[STACKSIZE-1],Task2_Prio);
OSTaskCreate(Task3,(void*)0,(OS_STK*)&task3_Stack[STACKSIZE-1],Task3_Prio);
OSAddTask_Init(0);
BSPprintf(0,"StartinguCOS-II...\n");
OSStart();//starttheOS//
//neverreached//
return0;
}//main
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
voidTask1(void*Id)
{
for(;;)
{
OSTaskSuspend(Task1_Prio);
OSSemPend(Fun_Semp,0,&err);
a[0][0]=1;
printf("\n");
Times+=1;
s=&Times;
OSMboxPost(Str_Box,s);
BSPprintf(0,"runtask1:
a[0][0]=%d\n",a[0][0]);
OSSemPost(Fun_Semp);
}
}
voidTask2(void*Id)
{
for(;;)
{
OSTaskSuspend(Task2_Prio);
OSSemPend(Fun_Semp,0,&err);
ss=OSMboxPend(Str_Box,0,&err);
printf("\n");
a[0][1]=2;
BSPprintf(0,"runtask2:
a[0][1]=%d次数为:
%d\n\n",a[0][1],*ss);
OSSemPost(Fun_Semp);
}
}
voidTask3(void*Id)
{
for(;;)
{
OSTaskSuspend(Task3_Prio);
OSSemPend(Fun_Semp,0,&err);
a[0][2]=3;
BSPprintf(0,"runtask3:
a[0][2]=%d\n",a[0][2]);
printf("\n");
printf("\n");
OSSemPost(Fun_Semp);
}
}
【钩子函数】
voidOSTimeTickHook(void)
{staticinti=0;
i++;
if(i%1000==0)
OSTaskResume(Task1_Prio);
if(i%2000==0)
OSTaskResume(Task2_Prio);
if(i%4000==0)
{OSTaskResume(Task3_Prio);
i=0;}
}
(2)文件的使用源程序
#include"../ucos-ii/includes.h"/*uC/OSinterface*/
#include"../ucos-ii/add/osaddition.h"
#include"../inc/drivers.h"
#include"../inc/sys/lib.h"
#include"../src/gui/gui.h"
#include
#include
///******************任务定义***************///
OS_STKMain_Stack[STACKSIZE]={0,};//Main_Test_Task堆栈
voidMain_Task(void*Id);//Main_Test_Task
#defineMain_Task_Prio12
OS_STKtest_Stack[STACKSIZE]={0,};//test_Test_Task堆栈
voidtest_Task(void*Id);//test_Test_Task
#definetest_Task_Prio15
/**************已经定义的OS任务*************
#defineSYS_Task_Prio1
#defineTouch_Screen_Task_Prio9
#defineMain_Task_Prio12
#defineKey_Scan_Task_Prio58
#defineLcd_Fresh_prio59
#defineLed_Flash_Prio60
***************************************/////////
///*****************事件定义*****************///
/////////////////////////////////////////////////////
//Mainfunction.//
////////////////////////////////////////////////////
intmain(void)
{
ARMTargetInit();//dotarget(uHALbasedARMsystem)initialisation//
OSInit();//neededbyuC/OS-II//
OSInitUart();
initOSFile();
#ifUSE_MINIGUI==0
initOSMessage();
initOSList();
initOSDC();
initOSCtrl();
LoadFont();
#endif
loadsystemParam();
//createthetasksinuC/OSandassignincreasing//
//prioritiestothemsothatTask3attheendof//
//thepipelinehasthehighestpriority.//
LCD_printf("CreatetaskonuCOS-II...\n");
OSTaskCreate(Main_Task,(void*)0,(OS_STK*)&Main_Stack[STACKSIZE-1],Main_Task_Prio);
//OSTaskCreate(test_Task,(void*)0,(OS_STK*)&test_Stack[STACKSIZE-1],test_Task_Prio);
OSAddTask_Init
(1);
LCD_printf("StartinguCOS-II...\n");
LCD_printf("Enteringgraphmode...\n");
LCD_ChangeMode(DspGraMode);
OSStart();//starttheOS//
//neverreached//
return0;
}//main
charTextFilename[]="/sys/ucos/fj/test.txt";
intreadline(char*str,intn,FILE*pfile)
{
inti;
for(i=0;iif(fread(str,1,1,pfile)!
=1)
return0;
if(*str=='\n'){
str++;
*str=0;
returni;
}
str++;
}
returni;
}
voidMain_Task(void*Id)//Main_Test_Task
{
charstr[256];//文件缓冲区
FILE*pfile;//定义文件结构指针
ClearScreen();//清屏
LCD_ChangeMode(DspTxtMode);//改变显示模式
LCD_Cls();//文本模式下清屏
pfile=fopen(TextFilename,"r");//打开文件
if(pfile==NULL){//文件打开失败
LCD_printf("Can'tOpenfile!
\n");
for(;;)
OSTimeDly(1000);
}
while(readline(str,sizeof(str),pfile)){//以行的方式读文件
LCD_printf(str);//向lcd输出文件内容
}
fclose(pfile);//关闭文件
for(;;)
OSTimeDly(1000);
}
七、实验思考题
1、用钩子函数实现周期任务有何特点?
答:
钩子函数的定时周期为1ms,利用计数器,根据不同计数值,设定不同任务的定时周期,当到了定时器周期后,调用OSTaskResume(Taskn_Prio)函数,恢复相应的任务。
2、用信号量是如何实现任务间同步的?
答:
创立一个信号量pevent=OSSemCreate(b),然后在相应的任务里,OSSemPend(pevent,timeout,&err),取得一个信号量的使用权,OSSemPend()函数挂起当前任务,直到其他的任务或中断置位信号量或超出等待的时限。
如果在预期的时钟节拍内信号量被置位,那么uc/os-II默认最高优先级的任务取得信号量,并恢复执行。
然后执行相应的任务代码,执行完后,编写函数OSSemPost(),释放信号量的使用权,如果指定的信号量是0或大于0,OSSemPost()函数则递增该信号量并返回。
如果有任何任务在等待信号量,那么最高优先级的任务将得到信号量并进入就绪态。
如果被唤醒的任务是最高优先级的就绪态的任务,任务调度函数将进行任务调度。
3、简述消息邮箱实现任务间通信的过程。
答:
首先在主函数里面建立个创建一个邮箱,Str_Box=OSMboxCreate((void*)0),然后再任务1中,向邮箱发送一个消息,OSMboxPost(Str_Box,s),在任务2中,首先接收来自邮箱的消息,然后判断邮箱的状态如果err==OS_NO_ERR,表明接收到消息,则显示相应的消息,如果没接收到,则可能有两种情况,第一种邮箱为满,将其内容(某消息的地址)返回,第二种邮箱为空,当前任务将被阻塞,直到邮箱中有了消息或等待超时。
4、简述文件加载到FLASH过程。
答:
(1)在PC硬盘创建一个命名为test.txt的文件,里面存入英文字符。
(2)打开超级终端,并运行此实验,此时LCD上没有显示,监视超级终端,按回车键,显示/sys>,用mkdir创建ucos子目录,在ucos下再创建fj子目录,用cd进入/sys/ucos/fj>,在该目录下执行命令dltest.txt–d,按回车键,此时超级终端显示《《《《《《《《,然后传送加载刚才创建的test.txt的文件,再运行实验,此时LCD上显示test.txt中的字符串。