UCOSIII中存在很多进行任务同步、交流的方法,例如使用信号量、互斥信号量、消息队列、事件标志组,一般都是单独使用它们进行任务同步,UCOSIII同时等待多个内核对象就是实现多对一的任务同步方法。
我的理解:
现在需要进行任务同步,任务A、任务B可以发布不同的内核对象信号量SemA
、SemB
,假设任务C是需要同步的,同步的意思就是当某些事件发生时才进行接下来的动作。在任务C中调用OSPendMulti()
对SemA、SemB进行等待,当未等待到任何信号量时就会挂起当前任务,当等待到SemA
或SemB
亦或者同时等待到SemA、SemB
时,任务C就会释放运行后面的程序、动作。
当然是否选择挂起等待是可以通过opt
进行设置的。
OSPendMulti()
OS_OBJ_QTY OSPendMulti (OS_PEND_DATA *p_pend_data_tbl,
OS_OBJ_QTY tbl_size,
OS_TICK timeout,
OS_OPT opt,
OS_ERR *p_err)
参数:
p_pend_data_tbl
:OS_PEND_DATA
类型的指针,
tbl_size
:等待的内核对象的数量
timeout
:超时时间,为0则一直等待
opt
:选项字节:
阻塞等待OS_OPT_PEND_BLOCKING
、非阻塞等待 OS_OPT_PEND_NON_BLOCKING
p_err
:错误码
使用方法:
index=OSPendMulti((OS_PEND_DATA* )pend_multi_tbl,
(OS_OBJ_QTY )CORE_OBJ_NUM, //内核数量
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(OS_ERR* )&err);
在使用pend_multi_tbl
之前,需要初始化为我们设置要等待的内核对象,只支持信号量和消息队列。下面是初始化为两个信号量和一个消息队列:
OS_PEND_DATA pend_multi_tbl[CORE_OBJ_NUM];
pend_multi_tbl[0].PendObjPtr=(OS_PEND_OBJ*)&Test_Sem1;
pend_multi_tbl[1].PendObjPtr=(OS_PEND_OBJ*)&Test_Sem2;
pend_multi_tbl[2].PendObjPtr=(OS_PEND_OBJ*)&Test_Q;
OS_PEND_DATA
是一种结构体类型,成员PendObjPtr
就是指向我们要等待的对象,因此上面的例子初始化的是PendObjPtr
,让其指向我们要等待的三个内核对象。
typedef struct os_pend_data OS_PEND_DATA;
struct os_pend_data {
OS_PEND_DATA *PrevPtr;
OS_PEND_DATA *NextPtr;
OS_TCB *TCBPtr;
OS_PEND_OBJ *PendObjPtr;
OS_PEND_OBJ *RdyObjPtr;
void *RdyMsgPtr;
OS_MSG_SIZE RdyMsgSize;
CPU_TS RdyTS;
};
当在其他地方发布了这些内核对象,上面使用OSPendMulti()
的任务就会释放运行从而实现任务间的同步。例如下面的代码(部分)使用按键对内核对象进行发布,从而实现任务同步。
while(1)
{
key = KEY_Scan(0); //扫描按键
switch(key)
{
case KEY1_PRES:
OSSemPost(&Test_Sem1,OS_OPT_POST_1,&err);//发送信号量1
break;
case KEY0_PRES:
OSSemPost(&Test_Sem2,OS_OPT_POST_1,&err);//发送信号量2
case WKUP_PRES:
msg_num++;
sprintf((char*)pbuf,"ALIENTEK %d",msg_num);
//发送消息
OSQPost((OS_Q* )&Test_Q,
(void* )pbuf,
(OS_MSG_SIZE)10,
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
break;
}
总结:
OSPendMulti()
等待多个内核对象是为了进行多对一的任务同步,可以利用它使多个事件的发生触发另一个事件执行。
注意:只支持同时等待多个信号量和消息队列,不支持事件标志组和互斥信号量。