柚子快报激活码778899分享:鸿蒙系统 LiteOS消息队列

http://www.51969.com/

一、消息队列的基本概念

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消息队列

http://www.51969.com/

查看原文