μCOSII系统基础嵌入式开发编程教程.docx
《μCOSII系统基础嵌入式开发编程教程.docx》由会员分享,可在线阅读,更多相关《μCOSII系统基础嵌入式开发编程教程.docx(16页珍藏版)》请在冰豆网上搜索。
![μCOSII系统基础嵌入式开发编程教程.docx](https://file1.bdocx.com/fileroot1/2022-11/18/a6cd389f-a425-4476-85fb-dfaed2cd8a42/a6cd389f-a425-4476-85fb-dfaed2cd8a421.gif)
μCOSII系统基础嵌入式开发编程教程
μC/OS-II系统基础嵌入式开发编程教程
μC/OS-II通过uCOS_II.H中定义的OS_EVENT数据结构来维护一个事件控制块的所有信息[程序清单L6.1],也就是本章开篇讲到的事件控制块ECB。
该结构中除了包含了事件本身的定义,如用于信号量的计数器,用于指向邮箱的指针,以及指向消息队列的指针数组等,还定义了等待该事件的所有任务的列表。
typedefstruct{
void*OSEventPtr;/*指向消息或者消息队列的指针*/
INT8UOSEventTbl[OS_EVENT_TBL_SIZE];/*等待任务列表*/
INT16UOSEventCnt;/*计数器(当事件是信号量时)*/
INT8UOSEventType;/*时间类型*/
INT8UOSEventGrp;/*等待任务所在的组*/
}OS_EVENT;
.OSEventPtr指针,只有在所定义的事件是邮箱或者消息队列时才使用。
当所定义的事件是
邮箱时,它指向一个消息,而当所定义的事件是消息队列时,它指向一个数据结构,详见6.06
节消息邮箱和6.07节消息队列。
.OSEventTbl[]和.OSEventGrp很像前面讲到的OSRdyTbl[]和OSRdyGrp,只不过前两者
包含的是等待某事件的任务,而后两者包含的是系统中处于就绪状态的任务。
(见3.04节就
绪表)
.OSEventCnt当事件是一个信号量时,.OSEventCnt是用于信号量的计数器,(见6.05节
信号量)。
e.OSEventType定义了事件的具体类型。
它可以是信号量(OS_EVENT_SEM)、邮箱
(OS_EVENT_TYPE_MBOX)或消息队列(OS_EVENT_TYPE_Q)中的一种。
用户要根据该域的具体值
来调用相应的系统函数,以保证对其进行的操作的正确性。
下面的代码将一个任务放到事件的等待任务列表中。
程序清单L6.2——将一个任务插入到事件的等待任务列表中
pevent->OSEventGrp|=OSMapTbl[prio>>3];
pevent->OSEventTbl[prio>>3]|=OSMapTbl[prio
程序清单L6.3从等待任务列表中删除一个任务
if((pevent->OSEventTbl[prio>>3]">pevent->OSEventGrp
}
程序清单L6.4在等待任务列表中查找最高优先级的任务
y=OSUnMapTbl[pevent->OSEventGrp];
x=OSUnMapTbl[pevent->OSEventTbl[y]];
prio=(yaitListInit(OS_EVENT*pevent)
{
INT8Ui;
pevent->OSEventGrp=0x00;
for(i=0;iOSEventTbl[i]=0x00;
}
}
程序清单L6.6使一个任务进入就绪状态
voidOSEventTaskRdy(OS_EVENT*pevent,void*msg,INT8Umsk)
{
OS_TCB*ptcb;
INT8Ux;
INT8Uy;
INT8Ubitx;
INT8Ubity;
INT8Uprio;
y=OSUnMapTbl[pevent->OSEventGrp];
(1)
bity=OSMapTbl[y];
(2)
x=OSUnMapTbl[pevent->OSEventTbl[y]];(3)
bitx=OSMapTbl[x];(4)
prio=(INT8U)((yOSEventTbl[y]">pevent->OSEventGrp
}
ptcb=OSTCBPrioTbl[prio];(7)
ptcb->OSTCBDly=0;(8)
ptcb->OSTCBEventPtr=(OS_EVENT*)0;(9)
#if(OS_Q_EN">ptcb->OSTCBMsg=msg;(10)
#else
msg=msg;
#endif
ptcb->OSTCBStat(11)
if(ptcb->OSTCBStat==OS_STAT_RDY){(12)
OSRdyGrp|=bity;(13)
OSRdyTbl[y]|=bitx;
}
}
程序清单L6.7使一个任务进入等待状态
voidOSEventTaskWait(OS_EVENT*pevent)
{
OSTCBCur->OSTCBEventPtr=pevent;
(1)
if((OSRdyTbl[OSTCBCur->OSTCBY]">OSRdyGrp
}
pevent->OSEventTbl[OSTCBCur->OSTCBY]|=OSTCBCur->OSTCBBitX;(3)
pevent->OSEventGrp|=OSTCBCur->OSTCBBitY;
}
程序清单L6.8因为等待超时将任务置为就绪状态
voidOSEventTO(OS_EVENT*pevent)
{
if((pevent->OSEventTbl[OSTCBCur->OSTCBY]">{
(1)
pevent->OSEventGrp
}
OSTCBCur->OSTCBStat=OS_STAT_RDY;
(2)
OSTCBCur->OSTCBEventPtr=(OS_EVENT*)0;(3)
}
信号量
μC/OS-II中的信号量由两部分组成:
一个是信号量的计数值,它是一个16位的无符号整
数(0到65,535之间);另一个是由等待该信号量的任务组成的等待任务表。
用户要在OS_CFG.H
中将OS_SEM_EN开关量常数置成1,这样μC/OS-II才能支持信号量。
信号量
μC/OS-II中的信号量由两部分组成:
一个是信号量的计数值,它是一个16位的无符号整
数(0到65,535之间);另一个是由等待该信号量的任务组成的等待任务表。
用户要在OS_CFG.H
中将OS_SEM_EN开关量常数置成1,这样μC/OS-II才能支持信号量。
程序清单L6.9建立一个信号量
OS_EVENT*OSSemCreate(INT16Ucnt)
{
OS_EVENT*pevent;
OS_ENTER_CRITICAL();
pevent=OSEventFreeList;
(1)
if(OSEventFreeList!
=(OS_EVENT*)0){
(2)
OSEventFreeList=(OS_EVENT*)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if(pevent!
=(OS_EVENT*)0){(3)
pevent->OSEventType=OS_EVENT_TYPE_SEM;(4)
pevent->OSEventCnt=cnt;(5)
OSEventWaitListInit(pevent);(6)
}
return(pevent);(7)
}
程序清单L6.10等待一个信号量
voidOSSemPend(OS_EVENT*pevent,INT16Utimeout,INT8U*err)
{
OS_ENTER_CRITICAL();
if(pevent->OSEventType!
=OS_EVENT_TYPE_SEM){
(1)
OS_EXIT_CRITICAL();
*err=OS_ERR_EVENT_TYPE;
}
if(pevent->OSEventCnt>0){
(2)
pevent->OSEventCnt--;(3)
OS_EXIT_CRITICAL();
*err=OS_NO_ERR;
6-15
}elseif(OSIntNesting>0){(4)
OS_EXIT_CRITICAL();
*err=OS_ERR_PEND_ISR;
}else{
OSTCBCur->OSTCBStat|=OS_STAT_SEM;(5)
OSTCBCur->OSTCBDly=timeout;(6)
OSEventTaskWait(pevent);(7)
OS_EXIT_CRITICAL();
OSSched();(8)
OS_ENTER_CRITICAL();
if(OSTCBCur->OSTCBStat">OSEventTO(pevent);(10)
OS_EXIT_CRITICAL();
*err=OS_TIMEOUT;
}else{
OSTCBCur->OSTCBEventPtr=(OS_EVENT*)0;(11)
OS_EXIT_CRITICAL();
*err=OS_NO_ERR;
}
}
}
程序清单L6.11发出一个信号量
INT8UOSSemPost(OS_EVENT*pevent)
{
OS_ENTER_CRITICAL();
if(pevent->OSEventType!
=OS_EVENT_TYPE_SEM){
(1)
OS_EXIT_CRITICAL();
return(OS_ERR_EVENT_TYPE);
}
if(pevent->OSEventGrp){
(2)
OSEventTaskRdy(pevent,(void*)0,OS_STAT_SEM);(3)
OS_EXIT_CRITICAL();
OSSched();(4)
return(OS_NO_ERR);
}else{
if(pevent->OSEventCntOSEventCnt++;(5)
OS_EXIT_CRITICAL();
return(OS_NO_ERR);
}else{
OS_EXIT_CRITICAL();
return(OS_SEM_OVF);
}
}
}
程序清单L6.12无等待地请求一个信号量
INT16UOSSemAccept(OS_EVENT*pevent)
{
INT16Ucnt;
OS_ENTER_CRITICAL();
if(pevent->OSEventType!
=OS_EVENT_TYPE_SEM){
(1)
OS_EXIT_CRITICAL();
return(0);
}
cnt=pevent->OSEventCnt;
(2)
if(cnt>0){(3)
pevent->OSEventCnt--;(4)
}
OS_EXIT_CRITICAL();
return(cnt);(5)
}
程序清单L6.13查询一个信号量的状态
INT8UOSSemQuery(OS_EVENT*pevent,OS_SEM_DATA*pdata)
{
INT8Ui;
INT8U*psrc;
INT8U*pdest;
OS_ENTER_CRITICAL();
if(pevent->OSEventType!
=OS_EVENT_TYPE_SEM){
(1)
OS_EXIT_CR