LiteOS提供消息队列,用于提供类似于数组的功能,用于传输数据。
任务或中断服务程序将消息放入消息队列,此时可以有一个或多个读取消息的任务去读取消息队列的数据。
如果队列为空,读取该任务被阻塞,可自定义阻塞时间,如果该任务等待时间超过了阻塞时间,自动转为就绪态。
消息队列满足先进先出(FIFO)的原则,也支持后进先出(LIFO)的原则。同时读队列和写队列还支持超时机制
创建队列时,根据传入的队列长度和消息节点大小,开辟内存空间,并初始化消息队列的相关信息,返回队列ID
消息队列控制块中,会维护一个消息头节点usQueueHead和消息尾节点usQueueTail位置变量,头节点表示队列中被占用消息节点的起始位置,尾节点表示占用消息节点的结束位置。队列刚创建时,两个节点均指向队列起始位置
写队列前,先判断队列是否可写(根据usReadWriteable判断),队列未满时可写。写队列时,根据尾节点找到消息节点末尾的空闲节点作为消息写入区。如果尾节点已经指向队列尾,则采用回卷方式(把队列看成一个圆圈)进行操作
读队列前,判断是否有消息读取(根据usReadWriteable),队列为空时不能操作,为空时读取将引起任务挂起。读队列时根据头节点找到最先写入对的消息节点进行读取,如果头节点指向队列尾,采用回卷操作
删除队列时,根据传入的队列ID,将队列置为未使用状态,释放内存空间,将队列头设置为初始状态
消息队列读写消息示意图如下所示

消息队列中有多个消息节点,消息节点的大小在创建队列时由用户指定,对数据的传递有复制和引用两种方式,复制的数据不影响原数据,引用的数据影响原数据。
阻塞机制用于保护各任务对消息队列进行正常读写操作
A对队列进行读取时,假如队列为空,A有三个选择:1.不阻塞,不等待消息到来 2.阻塞A,定义等待时间,时间内消息来到恢复就绪态读取消息,超时则恢复就绪态继续运行 3.A阻塞,一直等待到消息到来,直到读取完成
A向队列写入消息,假如队列已满,A被阻塞,直到允许入队时才能成功写入。系统根据用户定义的阻塞超时时间将任务阻塞,超时了还不能写入,返回错误代码,解除阻塞状态。只有在任务中写入消息才允许带有阻塞,中断中写入消息不允许带有阻塞。
多个任务阻塞在一个消息队列中时,阻塞的任务按照优先级排序,优先级高的优先获得队列访问权
在工程的los_queue.h文件中,定义了错误代码的说明
使用消息队列的流程:创建队列,得到队列ID—>写消息—>读消息—>删除队列
创建成功的队列,队列长度和消息节点的大小无法更改。初始化队列时,系统会为控制块分配对应的内存空间,控制块保存消息队列的基本信息:队列指针、队列状态、消息个数、节点大小、队列ID、消息头结点位置、消息尾结点位置等
LITE_OS_SEC_TEXT_INIT UINT32 LOS_QueueCreate(CHAR *pcQueueName,//消息队列名UINT16 usLen,//队列长度,1~0xFFFFUINT32 *puwQueueID,//消息队列IDUINT32 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)初始化可读消息的个数为0pstQueueCB->usReadWriteableCnt[OS_QUEUE_READ] = 0;
//(11)初始化可写的消息个数为uslenpstQueueCB->usReadWriteableCnt[OS_QUEUE_WRITE] = usLen;
//(12)头指针和为指针都为0pstQueueCB->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;
}
根据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;
消息队列的消息写入函数有两种,一种是不带复制方式的LOS_QueueWrite,一种是带复制方式的LOS_QueueWriteCopy。不带复制的函数实际上是对带复制的函数进行了封装。
任务或中断服务程序都可以给消息队列写消息,写入的消息复制到队列尾,否则根据定义的阻塞时间进行阻塞。超时了队列还是满的就返回错误。
(1)写入前先创建队列
(2)中断服务程序,必须用非阻塞方式写入,即等待时间为0
(3)初始化LiteOS前无法调用
(4)写入的信息大小不能大于消息节点大小
(5)写入队列节点中的是消息的地址(不带复制的函数)
(5)写入队列节点中的是存储在BufferAdder中的消息(带复制的函数)
LITE_OS_SEC_TEXT UINT32 LOS_QueueWrite(UINT32 uwQueueID,//队列IDVOID *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);
}LITE_OS_SEC_TEXT UINT32 LOS_QueueWriteCopy( UINT32 uwQueueID,//队列IDVOID * 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_TAILuwOperateType = OS_QUEUE_OPERATE_TYPE(OS_QUEUE_WRITE, OS_QUEUE_TAIL);return osQueueOperate(uwQueueID, uwOperateType, pBufferAddr, &uwBufferSize, uwTimeOut);
}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));}
}
同样的分为带复制方式和不带复制方式的两种函数
(1)读取前要先创建队列,根据队列ID进行读取
(2)队列读取采用的是先进先出模式,先读取存储在队列头部的消息
(3)用户必须定义一个存储地址的变量,假设为r-queue,并把存储消息的地址传递给读取函数,否则发生地址非法错误
(4)中断服务程序中必须用非阻塞,等待时间为0
(5)初始化LiteOS之前无法调用读函数
(6)r-queue变量中存储的是队列节点的地址
(7)LOS_QueueReadCopy和LOS_QueueWriteCopy是一组接口,LOS_QueueRead和LOS_QueueWrite是一组接口,两组接口配套使用。
(8)用户必须在读取消息时指定读取消息的大小,其值不能小于消息节点的大小。
LITE_OS_SEC_TEXT UINT32 LOS_QueueRead(UINT32 uwQueueID, //队列IDVOID *pBufferAddr, //存储获取消息的起始地址UINT32 uwBufferSize, //读取消息缓冲区的大小UINT32 uwTimeOut)//等待时间
{return LOS_QueueReadCopy(uwQueueID, pBufferAddr, &uwBufferSize, uwTimeOut);
}LITE_OS_SEC_TEXT UINT32 LOS_QueueReadCopy(UINT32 uwQueueID,//队列IDVOID * 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);
}/* 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*******************/