柚子快报激活码778899分享:鸿蒙系统 LiteOS消息队列
一、消息队列的基本概念
LiteOS提供消息队列,用于提供类似于数组的功能,用于传输数据。
任务或中断服务程序将消息放入消息队列,此时可以有一个或多个读取消息的任务去读取消息队列的数据。
如果队列为空,读取该任务被阻塞,可自定义阻塞时间,如果该任务等待时间超过了阻塞时间,自动转为就绪态。
消息队列满足先进先出(FIFO)的原则,也支持后进先出(LIFO)的原则。同时读队列和写队列还支持超时机制
二、消息队列的运行机制
创建队列时,根据传入的队列长度和消息节点大小,开辟内存空间,并初始化消息队列的相关信息,返回队列ID
消息队列控制块中,会维护一个消息头节点usQueueHead和消息尾节点usQueueTail位置变量,头节点表示队列中被占用消息节点的起始位置,尾节点表示占用消息节点的结束位置。队列刚创建时,两个节点均指向队列起始位置
写队列前,先判断队列是否可写(根据usReadWriteable判断),队列未满时可写。写队列时,根据尾节点找到消息节点末尾的空闲节点作为消息写入区。如果尾节点已经指向队列尾,则采用回卷方式(把队列看成一个圆圈)进行操作
读队列前,判断是否有消息读取(根据usReadWriteable),队列为空时不能操作,为空时读取将引起任务挂起。读队列时根据头节点找到最先写入对的消息节点进行读取,如果头节点指向队列尾,采用回卷操作
删除队列时,根据传入的队列ID,将队列置为未使用状态,释放内存空间,将队列头设置为初始状态
消息队列读写消息示意图如下所示
三、消息队列的传输机制
消息队列中有多个消息节点,消息节点的大小在创建队列时由用户指定,对数据的传递有复制和引用两种方式,复制的数据不影响原数据,引用的数据影响原数据。
四、消息队列的阻塞机制
阻塞机制用于保护各任务对消息队列进行正常读写操作
4.1 出队阻塞(读阻塞)
A对队列进行读取时,假如队列为空,A有三个选择:1.不阻塞,不等待消息到来 2.阻塞A,定义等待时间,时间内消息来到恢复就绪态读取消息,超时则恢复就绪态继续运行 3.A阻塞,一直等待到消息到来,直到读取完成
4.2 入队阻塞(写阻塞)
A向队列写入消息,假如队列已满,A被阻塞,直到允许入队时才能成功写入。系统根据用户定义的阻塞超时时间将任务阻塞,超时了还不能写入,返回错误代码,解除阻塞状态。只有在任务中写入消息才允许带有阻塞,中断中写入消息不允许带有阻塞。
多个任务阻塞在一个消息队列中时,阻塞的任务按照优先级排序,优先级高的优先获得队列访问权
五、常见队列错误代码
在工程的los_queue.h文件中,定义了错误代码的说明
六、常用消息队列的函数
使用消息队列的流程:创建队列,得到队列ID—>写消息—>读消息—>删除队列
6.1 消息队列创建函数LOS_QueueCreate
创建成功的队列,队列长度和消息节点的大小无法更改。初始化队列时,系统会为控制块分配对应的内存空间,控制块保存消息队列的基本信息:队列指针、队列状态、消息个数、节点大小、队列ID、消息头结点位置、消息尾结点位置等
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(CHAR *pcQueueName,//消息队列名
UINT16 usLen,//队列长度,1~0xFFFF
UINT32 *puwQueueID,//消息队列ID
UINT32 uwFlags,//队列模式
UINT16 usMaxMsgSize )//消息节点大小(字节),1~(0xFFFF-4)
{
QUEUE_CB_S *pstQueueCB;
UINTPTR uvIntSave;
LOS_DL_LIST *pstUnusedQueue;
UINT8 *pucQueue;
UINT16 usMsgSize = usMaxMsgSize + sizeof(UINT32);
//(1)传进来的队列名称和队列模式转换为空类型,未使用到这两个参数
(VOID)pcQueueName;
(VOID)uwFlags;
//(2)如果ID为空,返回错误代码
if (NULL == puwQueueID)
{
return LOS_ERRNO_QUEUE_CREAT_PTR_NULL;
}
if(usMaxMsgSize > OS_NULL_SHORT -4)
{
return LOS_ERRNO_QUEUE_SIZE_TOO_BIG;
}
//(3)如果消息节点过大或为0,返回错误代码
if ((0 == usLen) || (0 == usMaxMsgSize))
{
return LOS_ERRNO_QUEUE_PARA_ISZERO;
}
//(4)为队列分配内存,根据队列长度和消息节点大小进行动态分配
pucQueue = (UINT8 *)LOS_MemAlloc(m_aucSysMem0, usLen * usMsgSize);
if (NULL == pucQueue)
{
return LOS_ERRNO_QUEUE_CREATE_NO_MEMORY;
}
//(5)判断是否可创建队列,因为系统配置中定义了最大可创建的队列数量
uvIntSave = LOS_IntLock();
if (LOS_ListEmpty(&g_stFreeQueueList))
{
LOS_IntRestore(uvIntSave);
(VOID)LOS_MemFree(m_aucSysMem0, pucQueue);
return LOS_ERRNO_QUEUE_CB_UNAVAILABLE;
}
//(6)从系统管理的空闲消息队列控制块列表中取下一个消息队列控制块,表示消息队列已被创建
pstUnusedQueue = LOS_DL_LIST_FIRST(&(g_stFreeQueueList));
LOS_ListDelete(pstUnusedQueue);
pstQueueCB = (GET_QUEUE_LIST(pstUnusedQueue));
//(7)配置队列的具体过程,配置队列长度
pstQueueCB->usQueueLen = usLen;
//(8)配置消息节点大小
pstQueueCB->usQueueSize = usMsgSize;
//(9)存放消息的起始地址pucQueue,将消息队列的状态设置为可用
pstQueueCB->pucQueue = pucQueue;
pstQueueCB->usQueueState = OS_QUEUE_INUSED;
//(10)初始化可读消息的个数为0
pstQueueCB->usReadWriteableCnt[OS_QUEUE_READ] = 0;
//(11)初始化可写的消息个数为uslen
pstQueueCB->usReadWriteableCnt[OS_QUEUE_WRITE] = usLen;
//(12)头指针和为指针都为0
pstQueueCB->usQueueHead = 0;
pstQueueCB->usQueueTail = 0;
//(13)初始化读写操作的消息控件链表
LOS_ListInit(&pstQueueCB->stReadWriteList[OS_QUEUE_READ]);
LOS_ListInit(&pstQueueCB->stReadWriteList[OS_QUEUE_WRITE]);
LOS_ListInit(&pstQueueCB->stMemList);
LOS_IntRestore(uvIntSave);
//(14)将ID返还给用户
*puwQueueID = pstQueueCB->usQueueID;
return LOS_OK;
}
6.2 消息队列删除函数
根据ID删除消息队列,队列在使用中或阻塞中无法删除,未创建的队列也无法删除
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueDelete(UINT32 uwQueueID)
{
QUEUE_CB_S *pstQueueCB;
UINT8 *pucQueue = NULL;
UINTPTR uvIntSave;
UINT32 uwRet;
//(1)判断ID有效性
if (uwQueueID >= LOSCFG_BASE_IPC_QUEUE_LIMIT)
{
return LOS_ERRNO_QUEUE_NOT_FOUND;
}
uvIntSave = LOS_IntLock();
//(2)根据ID获取队列控制块状态,如果队列未使用,返回错误
pstQueueCB = (QUEUE_CB_S *)GET_QUEUE_HANDLE(uwQueueID);
if (OS_QUEUE_UNUSED == pstQueueCB->usQueueState)
{
uwRet = LOS_ERRNO_QUEUE_NOT_CREATE;
goto QUEUE_END;
}
//(3)如果有任务在等待消息队列中的消息,则无法删除
if (!LOS_ListEmpty(&pstQueueCB->stReadWriteList[OS_QUEUE_READ]))
{
uwRet = LOS_ERRNO_QUEUE_IN_TSKUSE;
goto QUEUE_END;
}
//(4)如果有任务在等待写入消息到队列中,则无法删除
if (!LOS_ListEmpty(&pstQueueCB->stReadWriteList[OS_QUEUE_WRITE]))
{
uwRet = LOS_ERRNO_QUEUE_IN_TSKUSE;
goto QUEUE_END;
}
//(5)如果队列非空,系统为了保证任务获得资源,此时队列无法删除
if (!LOS_ListEmpty(&pstQueueCB->stMemList))
{
uwRet = LOS_ERRNO_QUEUE_IN_TSKUSE;
goto QUEUE_END;
}
if ((pstQueueCB->usReadWriteableCnt[OS_QUEUE_WRITE] + pstQueueCB->usReadWriteableCnt[OS_QUEUE_READ]) != pstQueueCB->usQueueLen)
{
//(6)如果队列的读写不同步,返回错误代码
uwRet = LOS_ERRNO_QUEUE_IN_TSKWRITE;
goto QUEUE_END;
}
pucQueue = pstQueueCB->pucQueue;
pstQueueCB->pucQueue = (UINT8 *)NULL;
//(7)将要删除的队列变为未使用状态,添加到消息队列控制块空闲列表中返还给系统
pstQueueCB->usQueueState = OS_QUEUE_UNUSED;
LOS_ListAdd(&g_stFreeQueueList, &pstQueueCB->stReadWriteList[OS_QUEUE_WRITE]);
LOS_IntRestore(uvIntSave);
//(8)释放队列内存
uwRet = LOS_MemFree(m_aucSysMem0, (VOID *)pucQueue);
return uwRet;
QUEUE_END:
LOS_IntRestore(uvIntSave);
return uwRet;
6.3 消息队列写消息函数
消息队列的消息写入函数有两种,一种是不带复制方式的LOS_QueueWrite,一种是带复制方式的LOS_QueueWriteCopy。不带复制的函数实际上是对带复制的函数进行了封装。
任务或中断服务程序都可以给消息队列写消息,写入的消息复制到队列尾,否则根据定义的阻塞时间进行阻塞。超时了队列还是满的就返回错误。
(1)写入前先创建队列
(2)中断服务程序,必须用非阻塞方式写入,即等待时间为0
(3)初始化LiteOS前无法调用
(4)写入的信息大小不能大于消息节点大小
(5)写入队列节点中的是消息的地址(不带复制的函数)
(5)写入队列节点中的是存储在BufferAdder中的消息(带复制的函数)
6.3.1 不带复制的方式:
LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 uwQueueID,//队列ID
VOID *pBufferAddr, //消息起始地址
UINT32 uwBufferSize, //写入消息的大小
UINT32 uwTimeOut)//等待时间,中断程序中使用时为0
{
if(pBufferAddr == NULL)
{
return LOS_ERRNO_QUEUE_WRITE_PTR_NULL;
}
uwBufferSize = sizeof(UINT32*);
return LOS_QueueWriteCopy(uwQueueID, &pBufferAddr, uwBufferSize, uwTimeOut);
}
6.3.2 带复制的方式:
LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteCopy( UINT32 uwQueueID,//队列ID
VOID * pBufferAddr,//写入消息的起始地址
UINT32 uwBufferSize,//写入消息的大小
UINT32 uwTimeOut )//等待时间
{
UINT32 uwRet;
UINT32 uwOperateType;
//对传进来的参数进行检查,如果参数非法,返回错误代码
uwRet = osQueueWriteParameterCheck(uwQueueID, pBufferAddr, &uwBufferSize, uwTimeOut);
if(uwRet != LOS_OK)
{
return uwRet;
}
//保存处理的类型,LiteOS采用通用的处理消息队列的方式进行消息处理,见6.4
//对于复制写入的消息,操作方式是写入OS_QUEUE_WRITE,位置是队列尾部OS_QUEUE_TAIL
uwOperateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL);
return osQueueOperate(uwQueueID, uwOperateType, pBufferAddr, &uwBufferSize, uwTimeOut);
}
6.4 通用的消息队列处理函数
LITE_OS_SEC_TEXT UINT32 osQueueOperate(UINT32 uwQueueID, UINT32 uwOperateType, VOID *pBufferAddr, UINT32 *puwBufferSize, UINT32 uwTimeOut)
{
QUEUE_CB_S *pstQueueCB;
LOS_TASK_CB *pstRunTsk;
UINTPTR uvIntSave;
LOS_TASK_CB *pstResumedTask;
UINT32 uwRet = LOS_OK;
//(1)通过函数得到即将处理的操作类型,0代表读,1代表写
UINT32 uwReadWrite = OS_QUEUE_READ_WRITE_GET(uwOperateType);
//(2)屏蔽中断
uvIntSave = LOS_IntLock();
//(3)通过队列ID获取队列控制块,并判断队列是否已使用,未使用则返回错误
pstQueueCB = (QUEUE_CB_S *)GET_QUEUE_HANDLE(uwQueueID);
if (OS_QUEUE_UNUSED == pstQueueCB->usQueueState)
{
uwRet = LOS_ERRNO_QUEUE_NOT_CREATE;
goto QUEUE_END;
}
//(4)如果是读消息操作,判断存放消息的地址空间大小能否放的下消息队列的消息,放不下则返回错误
if(OS_QUEUE_IS_READ(uwOperateType) && (*puwBufferSize < pstQueueCB->usQueueSize - sizeof(UINT32)))
{
uwRet = LOS_ERRNO_QUEUE_READ_SIZE_TOO_SMALL;
goto QUEUE_END;
}//(5)如果是写入,判断消息大小、消息节点大小,即能否存储要写入的消息
else if(OS_QUEUE_IS_WRITE(uwOperateType) && (*puwBufferSize > pstQueueCB->usQueueSize - sizeof(UINT32)))
{
uwRet = LOS_ERRNO_QUEUE_WRITE_SIZE_TOO_BIG;
goto QUEUE_END;
}
//(6)如果当前队列可读的消息个数为0,不能读。写也是一样。
if (0 == pstQueueCB->usReadWriteableCnt[uwReadWrite])
{
if (LOS_NO_WAIT == uwTimeOut)
{
//(7)不可读写的请胯下,加入未设置阻塞超时,根据是读操作还是写操作返回对应错误代码
uwRet = OS_QUEUE_IS_READ(uwOperateType) ? LOS_ERRNO_QUEUE_ISEMPTY : LOS_ERRNO_QUEUE_ISFULL;
goto QUEUE_END;
}
if (g_usLosTaskLock)
{
//(8)如果任务被闭锁,不允许操作消息队列
uwRet = LOS_ERRNO_QUEUE_PEND_IN_LOCK;
goto QUEUE_END;
}
//(9)获取当前任务的任务控制块
pstRunTsk = (LOS_TASK_CB *)g_stLosTask.pstRunTask;
//(10)根据用户指定的阻塞超时时间等待,把当前任务添加到对应操作队列的阻塞列表中
//写—>写操作阻塞列表,有空闲消息节点时恢复就绪态执行写入操作,超时恢复就绪态
//读—>读操作阻塞列表,、等到其他任务/中断写入消息,当队列有可读消息时恢复就绪态执行操作,超时恢复就绪态
osTaskWait(&pstQueueCB->stReadWriteList[uwReadWrite], OS_TASK_STATUS_PEND_QUEUE, uwTimeOut);
LOS_IntRestore(uvIntSave);
//(11)任务切换
LOS_Schedule();
uvIntSave = LOS_IntLock();
//(12)判断阻塞解除原因,如果是超时,返回错误代码
if (pstRunTsk->usTaskStatus & OS_TASK_STATUS_TIMEOUT)
{
pstRunTsk->usTaskStatus &= (~OS_TASK_STATUS_TIMEOUT);
uwRet = LOS_ERRNO_QUEUE_TIMEOUT;
goto QUEUE_END;
}
}
else
{
//(13)不是超时解除阻塞,说明消息队列可读写,可读写的消息个数减一
pstQueueCB->usReadWriteableCnt[uwReadWrite]--;
}
//(14)调用函数进行对应操作,函数如下所示
osQueueBufferOperate(pstQueueCB, uwOperateType, pBufferAddr, puwBufferSize);
//(15)如果与当前操作相反的另一个阻塞列表中有任务阻塞,操作完成后恢复任务
if (!LOS_ListEmpty(&pstQueueCB->stReadWriteList[!uwReadWrite])) /*lint !e514*/
{
pstResumedTask = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&pstQueueCB->stReadWriteList[!uwReadWrite])); /*lint !e413 !e514*/
//(16)调用函数,唤醒任务
osTaskWake(pstResumedTask, OS_TASK_STATUS_PEND_QUEUE);
LOS_IntRestore(uvIntSave);
//(17)进行一次,任务调度
LOS_Schedule();
return LOS_OK;
}
else
{
//(18)如果没有任务阻塞与当前操作相反的阻塞列表,与当前操作相反的可用消息个数+1.
//写完后可读消息个数加一,读取完后可写消息个数加一
pstQueueCB->usReadWriteableCnt[!uwReadWrite]++; /*lint !e514*/
}
QUEUE_END:
LOS_IntRestore(uvIntSave);
return uwRet;
}
osQueueBufferOperate函数源码
LITE_OS_SEC_TEXT static VOID osQueueBufferOperate(QUEUE_CB_S *pstQueueCB, UINT32 uwOperateType, VOID *pBufferAddr, UINT32 *puwBufferSize)
{
UINT8 *pucQueueNode;
UINT32 uwMsgDataSize = 0;
UINT16 usQueuePosion = 0;
/* get the queue position */
switch (OS_QUEUE_OPERATE_GET(uwOperateType))
{
case OS_QUEUE_READ_HEAD:
usQueuePosion = pstQueueCB->usQueueHead;
//支持回卷操作,可读或可写指针到达队尾时重置为0开始
(pstQueueCB->usQueueHead + 1 == pstQueueCB->usQueueLen) ? (pstQueueCB->usQueueHead = 0) : (pstQueueCB->usQueueHead++);
break;
case OS_QUEUE_WRITE_HEAD:
(0 == pstQueueCB->usQueueHead) ? (pstQueueCB->usQueueHead = pstQueueCB->usQueueLen - 1) : (--pstQueueCB->usQueueHead);
//消息队列支持LIFO,将消息队列头部写入消息
usQueuePosion = pstQueueCB->usQueueHead;
break;
case OS_QUEUE_WRITE_TAIL :
usQueuePosion = pstQueueCB->usQueueTail;
(pstQueueCB->usQueueTail + 1 == pstQueueCB->usQueueLen) ? (pstQueueCB->usQueueTail = 0) : (pstQueueCB->usQueueTail++);
break;
default: //read tail , reserved.
PRINT_ERR("invalid queue operate type!\n");
return;
}
pucQueueNode = &(pstQueueCB->pucQueue[(usQueuePosion * (pstQueueCB->usQueueSize))]);
if(OS_QUEUE_IS_READ(uwOperateType))
{
memcpy((VOID *)&uwMsgDataSize, (VOID *)(pucQueueNode + pstQueueCB->usQueueSize - sizeof(UINT32)), sizeof(UINT32));
memcpy((VOID *)pBufferAddr, (VOID *)pucQueueNode, uwMsgDataSize);
*puwBufferSize = uwMsgDataSize;
}
else
{
memcpy((VOID *)pucQueueNode, (VOID *)pBufferAddr, *puwBufferSize);
memcpy((VOID *)(pucQueueNode + pstQueueCB->usQueueSize - sizeof(UINT32)), puwBufferSize, sizeof(UINT32));
}
}
6.5 消息队列读消息函数
同样的分为带复制方式和不带复制方式的两种函数
(1)读取前要先创建队列,根据队列ID进行读取
(2)队列读取采用的是先进先出模式,先读取存储在队列头部的消息
(3)用户必须定义一个存储地址的变量,假设为r-queue,并把存储消息的地址传递给读取函数,否则发生地址非法错误
(4)中断服务程序中必须用非阻塞,等待时间为0
(5)初始化LiteOS之前无法调用读函数
(6)r-queue变量中存储的是队列节点的地址
(7)LOS_QueueReadCopy和LOS_QueueWriteCopy是一组接口,LOS_QueueRead和LOS_QueueWrite是一组接口,两组接口配套使用。
(8)用户必须在读取消息时指定读取消息的大小,其值不能小于消息节点的大小。
6.5.1 不带复制方式读取函数LOS_QueueRead
LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(UINT32 uwQueueID, //队列ID
VOID *pBufferAddr, //存储获取消息的起始地址
UINT32 uwBufferSize, //读取消息缓冲区的大小
UINT32 uwTimeOut)//等待时间
{
return LOS_QueueReadCopy(uwQueueID, pBufferAddr, &uwBufferSize, uwTimeOut);
}
6.5.2 带复制方式读取函数LOS_QueueReadCopy
LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 uwQueueID,//队列ID
VOID * pBufferAddr,//存储获取消息的起始地址
UINT32 * puwBufferSize,//读取消息缓冲区的大小
UINT32 uwTimeOut)//等待时间
{
UINT32 uwRet;
UINT32 uwOperateType;
uwRet = osQueueReadParameterCheck(uwQueueID, pBufferAddr, puwBufferSize, uwTimeOut);
if(uwRet != LOS_OK)
{
return uwRet;
}
uwOperateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_READ, OS_QUEUE_HEAD);
return osQueueOperate(uwQueueID, uwOperateType, pBufferAddr, puwBufferSize, uwTimeOut);
}
7.消息队列实验main文件
/* LiteOS 头文件 */
#include "los_sys.h"
#include "los_task.ph"
#include "los_queue.h"
/* 板级外设头文件 */
#include "bsp_usart.h"
#include "bsp_led.h"
#include "bsp_key.h"
/* 定义任务句柄 */
UINT32 Receive_Task_Handle;
UINT32 Send_Task_Handle;
/*定义消息队列ID*/
UINT32 Test_Queue_Handle;
/*定义消息队列长度*/
#define TEST_QUEUE_LEN 16
#define TEST_QUEUE_SIZE 16
/*声明全局变量*/
UINT32 send_data1 = 1;
UINT32 send_data2 = 2;
/* 函数声明 */
static UINT32 AppTaskCreate(void);
static UINT32 Creat_Receive_Task(void);
static UINT32 Creat_Send_Task(void);
static void Receive_Task(void);
static void Send_Task(void);
static void BSP_Init(void);
int main(void)
{
UINT32 uwRet = LOS_OK; //定义一个任务创建的返回值,默认为创建成功
/* 板载相关初始化 */
BSP_Init();
printf("按下KEY1或者KEY2写入队列消息\r\n");
printf("Receive_Task 任务读取到消息在串口回显\r\n");
/* LiteOS 内核初始化 */
uwRet = LOS_KernelInit();
if (uwRet != LOS_OK)
{
printf("LiteOS 核心初始化失败!失败代码0x%X\n",uwRet);
return LOS_NOK;
}
uwRet = AppTaskCreate();
if (uwRet != LOS_OK)
{
printf("AppTaskCreate创建任务失败!失败代码0x%X\n",uwRet);
return LOS_NOK;
}
/* 开启LiteOS任务调度 */
LOS_Start();
//正常情况下不会执行到这里
while(1);
}
static UINT32 AppTaskCreate(void)
{
/* 定义一个返回类型变量,初始化为LOS_OK */
UINT32 uwRet = LOS_OK;
/*创建一个测试队列*/
uwRet = LOS_QueueCreate("Test_Queue",TEST_QUEUE_LEN,&Test_Queue_Handle,0,TEST_QUEUE_SIZE);
if(uwRet!=LOS_OK)
{
printf("Test_Queue队列创建失败!失败代码0x%X\n",uwRet);
return uwRet;
}
uwRet = Creat_Receive_Task();
if (uwRet != LOS_OK)
{
printf("Receive_Task任务创建失败!失败代码0x%X\n",uwRet);
return uwRet;
}
uwRet = Creat_Send_Task();
if (uwRet != LOS_OK)
{
printf("Send_Task任务创建失败!失败代码0x%X\n",uwRet);
return uwRet;
}
return LOS_OK;
}
static UINT32 Creat_Receive_Task()
{
//定义一个创建任务的返回类型,初始化为创建成功的返回值
UINT32 uwRet = LOS_OK;
//定义一个用于创建任务的参数结构体
TSK_INIT_PARAM_S task_init_param;
task_init_param.usTaskPrio = 5; /* 任务优先级,数值越小,优先级越高 */
task_init_param.pcName = "Receive_Task";/* 任务名 */
task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)Receive_Task;/* 任务函数入口 */
task_init_param.uwStackSize = 1024; /* 堆栈大小 */
uwRet = LOS_TaskCreate(&Receive_Task_Handle, &task_init_param);/* 创建任务 */
return uwRet;
}
static UINT32 Creat_Send_Task()
{
// 定义一个创建任务的返回类型,初始化为创建成功的返回值
UINT32 uwRet = LOS_OK;
TSK_INIT_PARAM_S task_init_param;
task_init_param.usTaskPrio = 4; /* 任务优先级,数值越小,优先级越高 */
task_init_param.pcName = "Send_Task"; /* 任务名*/
task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)Send_Task;/* 任务函数入口 */
task_init_param.uwStackSize = 1024; /* 堆栈大小 */
uwRet = LOS_TaskCreate(&Send_Task_Handle, &task_init_param);/* 创建任务 */
return uwRet;
}
static void Receive_Task(void)
{
/*定义一个返回类型变量,初始化LOS_OK*/
UINT32 uwRet = LOS_OK;
UINT32 r_queue;
UINT32 buffsize =16;
/* 任务都是一个无限循环,不能返回 */
while(1)
{
uwRet = LOS_QueueRead(Test_Queue_Handle,&r_queue,buffsize,LOS_WAIT_FOREVER);
if(LOS_OK == uwRet){
printf("本次读取到的消息是%d\n",*(UINT32 *) r_queue);
}else {
printf("消息读取出错,错误代码0x%X\n",uwRet);
}
}
}
static void Send_Task(void)
{
UINT32 uwRet = LOS_OK;
/* 任务都是一个无限循环,不能返回 */
while(1)
{
if(Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==KEY_ON){
uwRet = LOS_QueueWrite(Test_Queue_Handle,&send_data1,sizeof(send_data1),0);
if(LOS_OK != uwRet){
printf("消息不能写入到消息队列!错误代码0x%X\r\n",uwRet);
}
}
else if(Key_Scan(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==KEY_ON){
uwRet = LOS_QueueWrite(Test_Queue_Handle,&send_data2,sizeof(send_data2),0);
if(LOS_OK != uwRet){
printf("消息不能写入到消息队列!错误代码0x%X\r\n",uwRet);
}
}
LOS_TaskDelay(20);
}
}
/*******************************************************************
* @ 函数名 : BSP_Init
* @ 功能说明: 板级外设初始化,所有板子上的初始化均可放在这个函数里面
* @ 参数 :
* @ 返回值 : 无
******************************************************************/
static void BSP_Init(void)
{
/*
* STM32中断优先级分组为4,即4bit都用来表示抢占优先级,范围为:0~15
* 优先级分组只需要分组一次即可,以后如果有其他的任务需要用到中断,
* 都统一用这个优先级分组,千万不要再分组,切忌。
*/
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
/* LED 初始化 */
LED_GPIO_Config();
/* 串口初始化 */
USART_Config();
/* KEY初始化 */
Key_GPIO_Config();
}
/******************************END OF FILE*******************/
柚子快报激活码778899分享:鸿蒙系统 LiteOS消息队列
发表评论