嵌入式系统实训报告.docx
《嵌入式系统实训报告.docx》由会员分享,可在线阅读,更多相关《嵌入式系统实训报告.docx(44页珍藏版)》请在冰豆网上搜索。
嵌入式系统实训报告
嵌入式系统实训
课程:
嵌入式系统及应用
学号:
姓名:
班级:
教师:
计算机科学与技术学院
实训内容及安排
实训目的与要求:
嵌入式系统实训的目标是通过对嵌入式系统的体系结构和操作系统的开发培养学生嵌入式系统的能力。
实训方式:
自己设计方案,按照指导书的要求独立完成实训。
实训环境:
PC机;ARM实际系统;UCOS—Ⅱ系统;ADS1.2环境
实训内容:
说明:
实验总共分四个阶段,分别如下:
第一阶段总体分析OS_TASK.C包含的函数
第二阶段逐个分析OS_TASK.C中的函数
第三阶段画流程图
第四阶段实验总结
第一阶段总体分析OS_TASK.C包含的函数
主要内容:
OS_TASK.C(是我们在机房使用的文件,下面的也是)
基本要求:
(1)、了解OS_TASK.C包含哪些函数
(2)、了解OS_TASK.C的作用
时间:
第1天
OS_TASK.C包含的函数有:
OSTaskChangePrio()函数允许生成OSTaskCreate()函数
OS_ENTER_CRITICAL();关闭中断函数OS_EXIT_CRITICAL();打开中断函数
OSTaskStkInit()初始化函数OSTaskDelHook();可在钩子程序中加入自定程序函数
第二阶段逐个分析OS_TASK.C中的函数
主要内容:
OS_TASK.C
基本要求:
(1)、了解OS_TASK.C中各个函数的作用
(2)、分析OS_TASK.C中各个函数的代码
时间:
第2—6天
/*
*************************************************************************************************
*uC/OS-II实时控制内核
*主要的包含文件
*任务管理
*
*文件:
OS_TASK.C任务管理代码
*作者:
JeanJ.Labrosse
*中文注解:
钟常慰zhongcw@译注版本:
1.0请尊重原版内容
*************************************************************************************************
*/
#ifndefOS_MASTER_FILE//是否已经定义OS_MASTER_FILE
#include"includes.h"//包含"includes.h"文件
#endif//结束定义
/*
*************************************************************************************************
*改变一个任务的优先级(CHANGEPRIORITYOFATASK)
*描述:
改变一个任务的优先级。
*
*参数:
oldp是任务原先的优先级。
*newp是任务的新优先级。
*返回:
OS_NO_ERR任务优先级成功改变。
*OS_PRIO_INVALID参数中的任务原先优先级或新优先级大于或等于OS_LOWEST_PRIO。
(i.e.>=OS_LOWEST_PRIO)
*OS_PRIO_EXIST优先级为PIP的任务已经存在;
*OS_PRIO_ERR参数中的任务原先优先级不存在。
*注意:
参数中的新优先级必须是没有使用过的,否则会返回错误码.在OSTaskChangePrio()中还会先
*判断要改变优先级的任务是否存在。
*
*************************************************************************************************
#ifOS_TASK_CHANGE_PRIO_EN>0//允许生成OSTaskChangePrio()函数
INT8UOSTaskChangePrio(INT8Uoldprio,INT8Unewprio)
{//改变一个任务的优先级(任务旧的优先级、任务新的优先级)
#ifOS_CRITICAL_METHOD==3//允许生成OSTaskCreate()函数
OS_CPU_SRcpu_sr;
#endif
#ifOS_EVENT_EN>0//消息事件是否>0
OS_EVENT*pevent;//定义事件指针
#endif
OS_TCB*ptcb;//定义消息事件的任务控制块指针
INT8Ux;//优先级低3位值
INT8Uy;//优先级高3位值
INT8Ubitx;//优先级低3位值计算对应值
INT8Ubity;//优先级高3位值计算索引值
#ifOS_ARG_CHK_EN>0//所有参数必须在指定的参数内
//当旧任务>=最低优先级并且旧任务不是本身并且新任务>=最低优先级
if((oldprio>=OS_LOWEST_PRIO&&oldprio!
=OS_PRIO_SELF)||
newprio>=OS_LOWEST_PRIO){
return(OS_PRIO_INVALID);//参数中的任务原先优先级或新优先级大于或等于OS_LOWEST_PRIO
}
#endif
OS_ENTER_CRITICAL();//关闭中断
if(OSTCBPrioTbl[newprio]!
=(OS_TCB*)0){//确认新任务优先级未被使用,即就绪态为0
OS_EXIT_CRITICAL();//打开中断
return(OS_PRIO_EXIST);//返回新任务(优先级为PIP的任务已经存在)
}else{
OSTCBPrioTbl[newprio]=(OS_TCB*)1;//新任务优先级未被使用,保留它(为1)
OS_EXIT_CRITICAL();//打开中断
//预先计算新任务优先级任务控制块OS_TCB的某些值
y=newprio>>3;//保留优先级高3位(3-5位)
bity=OSMapTbl[y];//计算索引值
x=newprio&0x07;//保存优先级低3位(0-2位)
bitx=OSMapTbl[x];//计算对应值
2H:
\SOURCE中文源代码\OS_TASK.C
OS_ENTER_CRITICAL();//关闭中断
if(oldprio==OS_PRIO_SELF){//要改变的是否使旧任务本身
oldprio=OSTCBCur->OSTCBPrio;//如果是(正在运行的优先级(旧任务本身的优先级))
}
if((ptcb=OSTCBPrioTbl[oldprio])!
=(OS_TCB*)0){//变更的旧任务必须存在(1即就绪)
OSTCBPrioTbl[oldprio]=(OS_TCB*)0;//旧任务就绪态去除它(为0)
if((OSRdyTbl[ptcb->OSTCBY]&ptcb->OSTCBBitX)!
=0x00){
//如果该任务处于就绪态,那么必须在当前的优先级下,从就绪表中移除该任务,然后在新
//的优先级下,将该任务插入到就绪表中。
if((OSRdyTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX)==0x00){
OSRdyGrp&=~ptcb->OSTCBBitY;
}
OSRdyGrp|=bity;//利用预先计算值将任务插入到就绪表中
OSRdyTbl[y]|=bitx;
#ifOS_EVENT_EN>0//消息事件是否>0
}else{//(任务未就绪)否则,拾取任务事件指针
if((pevent=ptcb->OSTCBEventPtr)!
=(OS_EVENT*)0){//任务事件表为1(有消息)
//如果任务正在等待某一事件的发生,该函数必须将任务从事件控制块的等待列表中删除
//并在新的优先级下将事件插入到等待队列中。
任务也可能正在等待延时时间到,或是被
//挂起。
if((pevent->OSEventTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX)==0){
pevent->OSEventGrp&=~ptcb->OSTCBBitY;
}
pevent->OSEventGrp|=bity;//将任务插入到等待列表中
pevent->OSEventTbl[y]|=bitx;
}
#endif
}
OSTCBPrioTbl[newprio]=ptcb;//将任务的OS_TCB的指针存到新任务OSTCBPrioTbl[]
ptcb->OSTCBPrio=newprio;//设定新的任务优先级,并保存原有计算值
ptcb->OSTCBY=y;//高3位计算值
ptcb->OSTCBX=x;//低3位计算值
ptcb->OSTCBBitY=bity;
ptcb->OSTCBBitX=bitx;
OS_EXIT_CRITICAL();//打开中断
OS_Sched();//任务调度,最高任务优先级运行
return(OS_NO_ERR);//任务优先级成功改变
}else{//否则
OSTCBPrioTbl[newprio]=(OS_TCB*)0;//新任务就绪态去除它(为0不存在),
OS_EXIT_CRITICAL();//打开中断
return(OS_PRIO_ERR);//返回(参数中的任务原先优先级不存在)
}
}
}
#endif
/*$PAGE*/
/*
*************************************************************************************************
*建立一个新任务(CREATEATASK)
*
*描述:
建立一个新任务。
任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立.中断
*处理程序中不能建立任务.一个任务必须为无限循环结构(如下所示),且不能有返回点。
*OSTaskCreate()是为与先前的μC/OS版本保持兼容,新增的特性在OSTaskCreateExt()函数中.
*无论用户程序中是否产生中断,在初始化任务堆栈时,堆栈的结构必须与CPU中断后寄存器入栈的
*顺序结构相同.详细说明请参考所用处理器的手册。
*
*参数:
task是指向任务代码的指针。
*
*pdata指向一个数据结构,该结构用来在建立任务时向任务传递参数。
下例中说明uC/OS中的任
*务结构以及如何传递参数pdata:
*voidTask(void*pdata)
*{
*...//对参数'pdata'进行操作
*for(;;){//任务函数体.
*...
*...
*//在任务体中必须调用如下函数之一:
*//OSMboxPend()用于任务等待消息,消息通过中断或另外的任务发送给需要的任务
*//OSFlgPend()用于任务等待事件标志中的事件标志
*//OSMutexPend()任务需要独占资源
*//OSQPend()用于任务等待消息
*//OSSemPend()用于任务试图取得共享资源的使用权,任务需要与其它任务或中断
*同步及任务需要等待特定事件的发生场合
*//OSTimeDly()任务延时若干时钟节拍
*//OSTimeDlyHMSM()任务延时若干时间
*//OSTaskSuspend()挂起任务本身
3H:
\SOURCE中文源代码\OS_TASK.C
*//OSTaskDel()删除任务本身
*...
*...
*}
*ptos为指向任务堆栈栈顶的指针。
任务堆栈用来保存局部变量,函数参数,返回地址以及任务被
*中断时的CPU寄存器内容.任务堆栈的大小决定于任务的需要及预计的中断嵌套层数。
计算
*堆栈的大小,需要知道任务的局部变量所占的空间,可能产生嵌套调用的函数,及中断嵌套
*所需空间。
如果初始化常量OS_STK_GROWTH设为1,堆栈被设为从内存高地址向低地址增长,
*此时ptos应该指向任务堆栈空间的最高地址。
反之,如果OS_STK_GROWTH设为0,堆栈将从内
*存的低地址向高地址增长。
*
*prio为任务的优先级。
每个任务必须有一个唯一的优先级作为标识。
数字越小,优先级越高。
*
*返回:
OS_NO_ERR函数调用成功;
*OS_PRIO_EXIT具有该优先级的任务已经存在;
*OS_PRIO_INVALID参数指定的优先级大于OS_LOWEST_PRIO;(i.e.>=OS_LOWEST_PRIO)
*OS_NO_MORE_TCB系统中没有OS_TCB可以分配给任务了。
*
*注意:
1、任务堆栈必须声明为OS_STK类型。
*2、在任务中必须调用uC/OS提供的下述过程之一:
延时等待、任务挂起、等待事件发生(等待信
*号量,消息邮箱、消息队列),以使其他任务得到CPU。
*3、用户程序中不能使用优先级0,1,2,3,以及OS_LOWEST_PRIO-3,OS_LOWEST_PRIO-2,
*OS_LOWEST_PRIO-1,OS_LOWEST_PRIO。
这些优先级μC/OS系统保留,其余的56个优先级提供给
*应用程序。
*************************************************************************************************
*/
#ifOS_TASK_CREATE_EN>0//允许生成OSTaskCreate()函数
INT8UOSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT8Uprio)
{//建立任务(任务代码指针、传递参数指针、分配任务堆栈栈顶指针、任务优先级)
#ifOS_CRITICAL_METHOD==3//中断函数被设定为模式3
OS_CPU_SRcpu_sr;
#endif
OS_STK*psp;//初始化任务堆栈指针变量,返回新的栈顶指针
INT8Uerr;//定义(获得并定义初始化任务控制块)是否成功
#ifOS_ARG_CHK_EN>0//所有参数必须在指定的参数内
if(prio>OS_LOWEST_PRIO){//检查任务优先级是否合法
return(OS_PRIO_INVALID);//参数指定的优先级大于OS_LOWEST_PRIO
}
#endif
OS_ENTER_CRITICAL();//关闭中断
if(OSTCBPrioTbl[prio]==(OS_TCB*)0){//确认优先级未被使用,即就绪态为0
OSTCBPrioTbl[prio]=(OS_TCB*)1;//保留这个优先级,将就绪态设为0
OS_EXIT_CRITICAL();//打开中断
psp=(OS_STK*)OSTaskStkInit(task,pdata,ptos,0);//初始化任务堆栈
err=OS_TCBInit(prio,psp,(OS_STK*)0,0,0,(void*)0,0);//获得并初始化任务控制块
if(err==OS_NO_ERR){//任务控制初始化成功
OS_ENTER_CRITICAL();//关闭中断
OSTaskCtr++;//任务计数器加1
OS_EXIT_CRITICAL();//打开中断
if(OSRunning==TRUE){//检查是否有(某个)任务在运行
OS_Sched();//任务调度,最高任务优先级运行
}
}else{//否则,任务初始化失败
OS_ENTER_CRITICAL();//关闭中断
OSTCBPrioTbl[prio]=(OS_TCB*)0;//放弃任务,设此任务就绪态为0
OS_EXIT_CRITICAL();//打开中断
}
return(err);//返回(获得并定义初始化任务控制块是否成功)
}
OS_EXIT_CRITICAL();//打开中断
return(OS_PRIO_EXIST);//返回(具有该优先级的任务已经存在)
}
#endif
/*$PAGE*/
/*
*************************************************************************************************
*CREATEATASK(ExtendedVersion)
*
*描述:
建立一个新任务。
与OSTaskCreate()不同的是,OSTaskCreateExt()允许用户设置更多的细节
*内容.任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立,但中断处理
*程序中不能建立新任务。
一个任务必须为无限循环结构(如下所示),且不能有返回点。
*
*参数:
task是指向任务代码的指针。
4H:
\SOURCE中文源代码\OS_TASK.C
*
*pdataPdata指针指向一个数据结构,该结构用来在建立任务时向任务传递参数。
下例中说
*明uC/OS中的任务代码结构以及如何传递参数pdata:
(如果在程序中不使用参数pdata,
*为了避免在编译中出现"参数未使用"的警告信息,可以写一句pdata=pdata;)
*voidTask(void*pdata)
*{
*...//对参数pdata进行操作,例如pdata=pdata
*for(;;){//任务函数体.总是为无限循环结构
*...
*...
*//任务中必须调用如下的函数:
*//OSMboxPend()用于任务等待消息,消息通过中断或另外的任务发送给需要的任务
*//OSFlgPend()用于任务等待事件标志中的事件标志
*//OSMutexPend()任务需要独占资源
*//OSQPend()用于任务等待消息
*//OSSemPend()用于任务试图取得共享资源的使用权,任务需要与其它任务或中断
*同步及任务需要等待特定事件的发生场合
*//OSTimeDly()任务延时若干时钟节拍
*//OSTimeDlyHMSM()任务延时若干时间
*//OSTaskSuspend()挂起任务本身
*//OSTaskDel()删除任务本身
*...
*...
*}
*}
*ptos为指向任务堆栈栈顶的指针.任务堆栈用来保存局部变量,函数参数,返回地址以及中
*断时的CPU寄存器内容.任务堆栈的大小决定于任务的需要及预计的中断嵌套层数.计
*算堆栈的大小,需要知道任务的局部变量所占的空间,可能产生嵌套调用的函数,及
*中断嵌套所需空间.如果初始化常量OS_STK_GROWTH设为1,堆栈被设为向低端增长
*(从内存高地址向低地址增长).此时ptos应该指向任务堆栈空间的最高地址.反之,
*如果OS_STK_GROWTH设为0,堆栈将从低地址向高地址增长.
*
*prio任务的优先级。
每个任务必须有一个唯一的优先级作为标识.数字越小,优先级越高。
*
*id是任务的标识,目前这个参数没有实际的用途,但保留在OSTaskCreateExt()中供今后
*扩展,应用程序中可设置id与优先级相同.(0..65535)
*
*pbos为指向堆栈底端的指针。
如果初始化常量OS_STK_GROWTH设为1,堆栈被设为从内存高
*地址向低地址增长.此时pbos应该指向任务堆栈空间的最低地址.反之,如果
*OS_STK_GROWTH设为0,堆栈将从低地址向高地址增长。
pbos应该指向堆栈空间的最高
*地址.参数pbos用于堆栈检测函数OSTaskStkChk().
*
*stk_size指定任务堆栈的大小。
其单位由OS_STK定义:
当OS_STK的类型定义为INT8U、INT16U、
*INT32U的时候,stk_size的单位为分别为字节(8位)、字(16位)和双字(32位)。
*
*pext是一个用户定义数据结构的指针,可作为TCB的扩展。
例如,当任务切换时,用户定义
*的数据结构中可存放浮点寄存器的数值,任务运行时间,任务切入次数等等信息。
*
*opt存放与任务相关的操作信息。
opt的低8位由uC/OS保留,用户不能使用。
用户可以使用
*opt的高8位。
每一种操作由opt中的一位或几位指定,当相应的位被置位时,表示选择
*某种操作。
当前的μC/OS版本支持下列操作:
*OS_TASK_OPT_STK_CHK:
决定是否进行任务堆栈检查;
*OS_TASK_OPT_STK_CLR:
决定是否清空堆栈;
*OS_TASK_OPT_SAVE_FP:
决定是否保存浮点寄存器的数值。
此项操作仅当处理器有浮
*点硬件时有效。
保存操作由硬件相关的代码完成。
*
*
*返回:
OS_NO_ERR:
函数调用成功;
*OS_PRIO_EXIST:
具有该优先级的任务已经存在;
*OS_PRIO_INVALID:
参数指定的优先级大于OS_LOWEST_PRIO;
*OS_NO_MORE_TCB:
系统中没有OS_TCB可以分配给任务了.
*
*注意:
1、任务堆栈必须声明为OS_STK类型;
*2、在任务中必须进行uC/OS提供的下述过程之一:
延时等待、任务挂起、等待事件发生(等待
*信号量,消息邮箱、消息队列),以使其他任务得到CPU;
*3、用户程序中不能使用优先级0,1,2,3,以及OS_LOWEST_PRIO-3,OS_LOWEST_PRIO-2,
*OS_LOWEST_PRIO-1,OS_LOWEST_PRIO。
这些优先级μC/OS系统保留,其余56个优先级提供给
*应用程序.
*************************************************************************************************
*/
/*