实验3 任务的基本管理Word格式文档下载.docx
《实验3 任务的基本管理Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《实验3 任务的基本管理Word格式文档下载.docx(17页珍藏版)》请在冰豆网上搜索。
![实验3 任务的基本管理Word格式文档下载.docx](https://file1.bdocx.com/fileroot1/2022-12/11/893290fd-7756-4d04-a1a3-4d7a2433753e/893290fd-7756-4d04-a1a3-4d7a2433753e1.gif)
●t1时刻,Task0开始执行,它运行到t2时刻挂起自己;
●t2时刻,系统调度处于就绪状态的优先级最高任务Task1执行,它在t3时刻唤醒Task0,后者由于优先级较高而抢占CPU;
●Task0执行到t4时刻又挂起自己,内核调度Task1执行;
●Task1运行至t5时刻再度唤醒Task0;
●……
2.1.2μC/OS-Ⅱ中的任务描述
一个任务通常是一个无限的循环,由于任务的执行是由操作系统内核调度的,因此任务是绝不会返回的,其返回参数必须定义成void。
在μC/OS-Ⅱ中,当一个运行着的任务使一个比它优先级高的任务进入了就绪态,当前任务的CPU使用权就会被抢占,高优先级任务会立刻得到CPU的控制权(在系统允许调度和任务切换的前提下)。
μC/OS-Ⅱ可以管理多达64个任务,但目前版本的μC/OS-Ⅱ有两个任务已经被系统占用了(即空闲任务和统计任务)。
必须给每个任务赋以不同的优先级,任务的优先级号就是任务编号(ID),优先级可以从0到OS_LOWEST_PR10-2。
优先级号越低,任务的优先级越高。
μC/OS-Ⅱ总是运行进入就绪态的优先级最高的任务。
2.2操作系统配置
操作系统配置的目的在于根据应用的需要,对操作系统的功能和规模进行设置,以便优化对系统存储空间的使用。
配置的方法为修改uC_OS-II源代码目录中的OS_CFG.h文件,配置文件配置如下:
#defineOS_MAX_EVENTS10/*最多可以有10个事件*/
#defineOS_MAX_FLAGS5/*最多可以有5个事件标志*/
#defineOS_MAX_MEM_PART5/*最多可以划分5个内存块*/
#defineOS_MAX_QS2/*最多可以使用2个队列*/
#defineOS_MAX_TASKS3/*最多可以创建3个任务*/
#defineOS_LOWEST_PRIO14/*任务优先级不可以大于14*/
#defineOS_TASK_IDLE_STK_SIZE1024/*空闲任务堆栈大小*/
#defineOS_TASK_STAT_EN1/*是否允许使用统计任务*/
#defineOS_TASK_STAT_STK_SIZE1024/*统计任务堆栈大小*/
#defineOS_FLAG_EN0/*是否允许使用事件标志功能*/
#defineOS_FLAG_WAIT_CLR_EN1/*是否允许等待清除事件标志*/
#defineOS_FLAG_ACCEPT_EN1/*是否允许使用OSFlagAccept()*/
#defineOS_FLAG_DEL_EN1/*是否允许使用OSFlagDel()*/
#defineOS_FLAG_QUERY_EN1/*是否允许使用OSFlagQuery()*/
#defineOS_MBOX_EN0/*是否允许使用邮箱功能*/
#defineOS_MBOX_ACCEPT_EN1/*是否允许使用OSMboxAccept()*/
#defineOS_MBOX_DEL_EN1/*是否允许使用OSMboxDel()*/
#defineOS_MBOX_POST_EN1/*是否允许使用OSMboxPost()*/
#defineOS_MBOX_POST_OPT_EN1/*是否允许使用OSMboxPostOpt()*/
#defineOS_MBOX_QUERY_EN1/*是否允许使用OSMboxQuery()*/
#defineOS_MEM_EN0/*是否允许使用内存管理的功能*/
#defineOS_MEM_QUERY_EN1/*是否允许使用OSMemQuery()*/
#defineOS_MUTEX_EN0/*是否允许使用互斥信号量的功能*/
#defineOS_MUTEX_ACCEPT_EN1/*是否允许使用OSMutexAccept()*/
#defineOS_MUTEX_DEL_EN1/*是否允许使用OSMutexDel()*/
#defineOS_MUTEX_QUERY_EN1/*是否允许使用OSMutexQuery()*/
#defineOS_Q_EN0/*是否允许使用队列功能*/
#defineOS_Q_ACCEPT_EN1/*是否允许使用OSQAccept()*/
#defineOS_Q_DEL_EN1/*是否允许使用OSQDel()*/
#defineOS_Q_FLUSH_EN1/*是否允许使用OSQFlush()*/
#defineOS_Q_POST_EN1/*是否允许使用OSQPost()*/
#defineOS_Q_POST_FRONT_EN1/*是否允许使用OSQPostFront()*/
#defineOS_Q_POST_OPT_EN1/*是否允许使用OSQPostOpt()*/
#defineOS_Q_QUERY_EN1/*是否允许使用OSQQuery()*/
#defineOS_SEM_EN0/*是否允许使用信号量功能*/
#defineOS_SEM_ACCEPT_EN1/*是否允许使用OSSemAccept()*/
#defineOS_SEM_DEL_EN1/*是否允许使用OSSemDel()*/
#defineOS_SEM_QUERY_EN1/*是否允许使用OSSemQuery()*/
#defineOS_TASK_CHANGE_PRIO_EN0/*是否允许使用OSTaskChangePrio()*/
#defineOS_TASK_CREATE_EN1/*是否允许使用OSTaskCreate()*/
#defineOS_TASK_CREATE_EXT_EN1/*是否允许使用OSTaskCreateExt()*/
#defineOS_TASK_DEL_EN1/*是否允许使用OSTaskDel()*/
#defineOS_TASK_SUSPEND_EN1/*是否允许使用OSTaskSuspend()andOSTaskResume()*/
#defineOS_TASK_QUERY_EN1/*是否允许使用OSTaskQuery()*/
#defineOS_TIME_DLY_HMSM_EN0/*是否允许使用OSTimeDlyHMSM()*/
#defineOS_TIME_DLY_RESUME_EN1/*是否允许使用OSTimeDlyResume()*/
#defineOS_TIME_GET_SET_EN1/*是否允许使用OSTimeGet()和OSTimeSet()*/
#defineOS_SCHED_LOCK_EN1/*是否允许使用OSSchedLock()和OSSchedUnlock()*/
#defineOS_TICKS_PER_SEC200/*设置每秒之内的时钟节拍数目*/
2.3源程序说明
系统启动后,经过ARM2200启动代码后,进入main()函数,这是我们编写实现应用程序的起点。
首先调用OSInit()对uC/OS-II进行了初始化,接着创建了起始任务TaskStart:
OSTaskCreate(TaskStart,(void*)0,&
TaskStartStk[TASK_STK_SIZE-1],0);
TaskStart任务
TaskStart任务负责安装操作系统的时钟中断服务例程、初始化操作系统时钟,初始化串口0,并创建所有的应用任务:
voidTaskStart(void*pdata)
{
charstr[]="
uC/OS-IIisStarted\n==============================\n"
;
TargetInit();
/*目标板初始化*/
OSTaskCreate(Task0,(void*)0,&
Task0Stk[TASK_STK_SIZE-1],5);
/*创建任务Task0*/
OSTaskCreate(Task1,(void*)0,&
Task1Stk[TASK_STK_SIZE-1],6);
/*创建任务Task1*/
UART0_SendStr((uint8const*)str);
/*向串口0发送字符串*/
for(;
)
{
OSTaskSuspend(0);
/*挂起优先级为0的任务,即为TaskStart任务本身*/
}
}
TaskStart任务完成上述操作后将自己挂起,操作系统将调度当前优先级最高的应用任务Task0运行。
应用任务
应用任务Task0运行后将自己挂起,之后操作系统就会调度处于就绪状态的优先级最高的任务,具体代码如下:
voidTask0(void*pdata)
{
Task0isrunning\nTask1isSuspended\n==============================\n"
pdata=pdata;
/*避免编译警告*/
UART0_SendStr((uint8const*)str);
/*向串口0发送字符串*/
DelayTime(3000);
/*延时*/
OSTaskSuspend(5);
/*挂起优先级为5的任务,即Task0本身*/
应用任务Task1运行后将Task0唤醒,使其进入到就绪队列中:
voidTask1(void*pdata)
Task0isSuspended\nTask1isrunning\n==============================\n"
/*避免编译警告*/
for(;
OSTimeDly(1000);
OSTaskResume(5);
/*为优先级为5的任务即Task0解挂*/
3试验步骤
3.1硬件连接
将ARM开发板的JTAG口通过EasyJTAG-H或EasyJTAG连接到PC机上,ARM板的串口0连接到PC机的串口1,插上ARM开发板电源。
3.2利用周立功ARM2200工程模板建立工程
1)打开ADS1.2集成开发软件
点击开始->
所有程序->
ARMDeveloperSuitev1.2->
CodeWarriorforARMDeveloperSuite,如下图所示:
图2打开ADS1.2集成开发软件
图3ADS1.2集成开发软件界面
2)用周立功LPC2200工程模板建立工程
在D盘下建立文件夹Experiment3,点击file->
New,将弹出如下图的对话框。
工程名称
工程路径
选择工程模板类型lpc22xx
图4工程建立界面(a)
选择工程模板类型为“ARMExecutableImageforuCOSII(forlpc22xx)”,为工程命名如Experiment3,选择工程存储路径如“D:
/Experiment3”,设置完成后点击确定,工程建立完成。
下图为工程建立完成后的界面。
图5工程建立界面(b)
3)为工程添加用户程序文件
将文件夹UART0、ARM、SOURCE及文件main.C拷贝到Experiment3目录下。
在ADS1.2工程界面中点击右键,点击“AddFiles…”,将文件“D:
\Experiment3\main.c”和“D:
\Experiment3\UART0\SendStr.c”添加到工程中。
已经添加的C文件
图6添加用户程序到工程(c)
打开文件config.h,删除掉“#include“..\..\Arm_Pc\pc.h””语句,如下图所示:
将该语句删除掉
图7
4)编译程序代码
添加用户程序完成后,选择程序调试运行模式,选择在外部RAM中进行调试,即选择DebugInExram,如图21所示:
选择程序调试运行环境
程序在内部Flash中调试
程序在外部Flash中调试
程序在内部Flash中调试,并加密
程序在外部RAM中调试
图8设置程序运行环境
点击进入工程设置界面
点击编译工程
点击进入工程调试环境
图9编译程序界面(a)
点击
按钮开始编译程序,编译后界面如下,如果出现错误,要修改出错程序代码。
图10编译程序界面(b)
最后点击
下载调试,操作步骤与实验1、实验2相同。
在程序执行时,在PC机上打开串口调试助手,串口调试助手设置如下:
图11串口调试助手界面
4运行及观察应用输出信息
程序执行时,串口调试助手接收到信息如下:
图12实验输出结果
阅读程序源代码,并根据串口输出结果,分析任务的调度,任务的挂起及任务解挂过程。
5本实验中所用到的µ
C/OS-II相关函数
5.1OSTaskCreate()
建立一个新任务。
任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立。
中断处理程序中不能建立任务。
一个任务可以为无限循环的结构。
函数原型:
INT8UOSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT8Uprio);
参数说明:
task是指向任务代码首地址的指针。
Pdata指向一个数据结构,该结构用来在建立任务时向任务传递参数。
返回值:
OSTaskCreate()的返回值为下述之一:
●OS_NO_ERR:
函数调用成功。
●OS_PRIO_EXIST:
具有该优先级的任务已经存在。
●OS_PRIO_INVALID:
参数指定的优先级大于OS_LOWEST_PRIO。
●OS_NO_MORE_TCB:
系统中没有OS_TCB可以分配给任务了。
5.2OSTaskSuspend()
无条件挂起一个任务。
调用此函数的任务也可以传递参数OS_PRIO_SELF,挂起调用任务本身。
当前任务挂起后,只有其他任务才能唤醒被挂起的任务。
任务挂起后,系统会重新进行任务调度,运行下一个优先级最高的就绪任务。
唤醒挂起任务需要调用函数OSTaskResume()。
任务的挂起是可以叠加到其他操作上的。
例如,任务被挂起时正在进行延时操作,那么任务的唤醒就需要两个条件:
延时的结束以及其他任务的唤醒操作。
又如,任务被挂起时正在等待信号量,当任务从信号量的等待对列中清除后也不能立即运行,而必须等到被唤醒后。
INT8UOSTaskSuspend(INT8Uprio);
prio为指定要获取挂起的任务优先级,也可以指定参数OS_PRIO_SELF,挂起任务本身。
此时,下一个优先级最高的就绪任务将运行。
OSTaskSuspend()的返回值为下述之一:
●OS_TASK_SUSPEND_IDLE:
试图挂起μC/OS-II中的空闲任务(Idletask)。
此为非法操作。
参数指定的优先级大于OS_LOWEST_PRIO或没有设定OS_PRIO_SELF的值。
●OS_TASK_SUSPEND_PRIO:
要挂起的任务不存在。
5.3OSTaskResume()
唤醒一个用OSTaskSuspend()函数挂起的任务。
OSTaskResume()也是唯一能“解挂”挂起任务的函数。
NT8UOSTaskResume(INT8Uprio);
prio指定要唤醒任务的优先级。
OSTaskResume()的返回值为下述之一:
●OS_TASK_RESUME_PRIO:
要唤醒的任务不存在。
●OS_TASK_NOT_SUSPENDED:
要唤醒的任务不在挂起状态。
参数指定的优先级大于或等于OS_LOWEST_PRIO。
5.3OSTimeDly()
将调用该函数的任务延时一段特定的时间,延时的长短是由指定的时钟节拍数目来确定的,调用该函数后经进行一次任务调度,从而去执行一个优先级最高的就绪态任务。
任务在调用OSTimeDly()后,一旦规定的时间期满或者有其他任务通过调用OSTimeDlyResume()取消了延时,任务会立即进入就绪状态。
voidOSTimeDly(INT16Uticks)
ticks任务延时的时钟节拍数
无