UCOS---等待多个内核对象
概述
内核对象,可以指的是信号量、消息队列、互斥锁、事件标志组等
等待多个内核对象
等待多个内核对象,只能等待信号量和消息队列。
在UCOSIII中允许任务同时等待多个信号量和多个消息队列,也就是说,UCOSIII不支持同时等待多个事件标志组或互斥锁。
This function only allows you to pend on semaphores and/or message queues.
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,内核对象的数组
tbl_size,内核对象的数目
timeout,超时时间,默认写0,一直等待
opt,默认写OS_OPT_PEND_BLOCKING,阻塞等待
p_err,返回错误码,没有错误的就返回OS_ERR_NONE
返回值:
0,就绪内核对象的数目
=0,超时或发生错误
注意:
使用上述函数,确保OS_CFG_Q_EN、OS_CFG_SEM_EN、OS_CFG_PEND_MULTI_EN宏定义开关有效,并可在os_cfg.h文件找到。
例程
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "includes.h"
#include "string.h"
//任务函数
void Task1_task(void *parg);
//任务优先级
#define Task1_TASK_PRIO 6
//任务堆栈大小
#define Task1_TASK_SIZE 128
//任务堆栈空间
CPU_STK Task1_TASK_STK[Task1_TASK_SIZE];
//任务控制块
OS_TCB Task1_TCB;
//任务函数
void Task2_task(void *parg);
//任务优先级
#define Task2_TASK_PRIO 6
//任务堆栈大小
#define Task2_TASK_SIZE 128
//任务堆栈空间
CPU_STK Task2_TASK_STK[Task1_TASK_SIZE];
//任务控制块
OS_TCB Task2_TCB;
OS_Q g_queue_usart1;
OS_SEM g_sem;
OS_PEND_DATA MyPendArray[2];
int main(void)
{
//UCOS系统的变量定义
OS_ERR err;
delay_init(); //延时初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置
uart_init(115200); //串口波特率设置
LED_Init(); //LED初始化
//初始化UCOSIII
OSInit(&err);
//创建任务1
OSTaskCreate((OS_TCB * )&Task1_TCB, //任务控制块
(CPU_CHAR * )"Task1_task", //任务名字
(OS_TASK_PTR )Task1_task, //任务函数
(void * )0, //传递给任务函数的参数
(OS_PRIO )Task1_TASK_PRIO, //任务优先级
(CPU_STK * )&Task1_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)Task1_TASK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)Task1_TASK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
(OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
(void * )0, //用户补充的存储区
(OS_OPT )OS_OPT_TASK_NONE, //任务选项
(OS_ERR * )&err); //存放该函数错误时的返回值
//创建任务2
OSTaskCreate((OS_TCB * )&Task2_TCB, //任务控制块
(CPU_CHAR * )"Task2_task", //任务名字
(OS_TASK_PTR )Task2_task, //任务函数
(void * )0, //传递给任务函数的参数
(OS_PRIO )Task2_TASK_PRIO, //任务优先级
(CPU_STK * )&Task2_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)Task2_TASK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)Task2_TASK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
(OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
(void * )0, //用户补充的存储区
(OS_OPT )OS_OPT_TASK_NONE, //任务选项
(OS_ERR * )&err); //存放该函数错误时的返回值
//创建信号量,初值为0
OSSemCreate(&g_sem,"g_sem",0,&err);
//创建消息队列
OSQCreate(&g_queue_usart1,"g_queue_usart1",16,&err);
MyPendArray[0].PendObjPtr=(OS_PEND_OBJ*)&g_sem;
MyPendArray[1].PendObjPtr=(OS_PEND_OBJ*)&g_queue_usart1;
//开启UCOSIII
OSStart(&err);
printf("OS run error.......\r\n");
while(1);
}
void Task1_task(void *parg)
{
u32 cnt =0;
char buf[64]={0};
OS_ERR err;
printf("task1 is create ok\r\n");
while(1)
{
cnt++;
sprintf(buf,"task1 run %d times",cnt);
printf("task1 is running ...\r\n");
//每三秒发送信号量
OSSemPost(&g_sem,OS_OPT_POST_1,&err);
delay_ms(3000);
OSQPost(&g_queue_usart1,buf,strlen(buf),OS_OPT_POST_FIFO,&err);
delay_ms(1000);
}
}
void Task2_task(void *parg)
{
OS_OBJ_QTY obj_count=0;
OS_ERR err;
printf("task2 is create ok\r\n");
while(1)
{
obj_count=OSPendMulti(MyPendArray,2,0,OS_OPT_PEND_BLOCKING,&err);
if(obj_count>0)
{
if(MyPendArray[0].RdyObjPtr == (OS_PEND_OBJ*)&g_sem)
{
printf("sem get\r\n");
}
if(MyPendArray[1].RdyObjPtr == (OS_PEND_OBJ*)&g_queue_usart1)
{
printf("msg:[%s][%d]\r\n",MyPendArray[1].RdyMsgPtr,MyPendArray[1].RdyMsgSize);
memset(MyPendArray[1].RdyMsgPtr,0,MyPendArray[1].RdyMsgSize);
}
}
printf("task2 is running ...\r\n");
delay_ms(1000);
}
}
任务1每3秒发送一个信号量再延时1秒发送消息队列
任务2将接收到的消息队列和信号量打印到串口