UCOSIII使用消息队列err出现OS_ERR_INT_Q_FULL错误

串口1连接蓝牙模块在串口中断中接收数据
通过消息队列将数据发送给任务
任务请求消息阻塞等待
调试过程中,APP每隔200ms向串口发送一次数据
分别在串口和任务中的消息发送函数里标记flag计数,发现消息队列全部接收到数据并转发成功,
但根据指令解析处理函数未处理,出现蓝牙数据丢包现象。
串口中断中发送消息函数如下:

/****************************************************
函数名:USART1_IRQHandler
形参:  
返回值:无
函数功能:串口中断处理函数
****************************************************/
void USART1_IRQHandler(void)                	//串口1中断服务程序
{
    static u8 Rxcount = 0;
	u8 recv_u1 =0;
    OSIntEnter();
#if 1
	 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
        recv_u1 = USART_ReceiveData(USART1); //(USART1->DR);	//读取接收到的数据
        ServerData.server_data_rx[Rxcount++] = recv_u1;
    }
    else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)//接收到一帧数据
    {     
        recv_u1 = USART_ReceiveData(USART1);
        Rxcount = 0;
		 //蓝牙模块  修改名称
        if(strstr((char*)ServerData.server_data_rx,"AT+OK\r\n") != NULL)
        {
            if((strlen((char*)ServerData.server_data_rx)) < 8)
                return;
            substring(BLT_Rx_Buf,(char*)ServerData.server_data_rx,20,7);
						
        }
        else
        {
             OSQPost   ((OS_Q        *)&Server_DATA_Q,   //消息变量指针
             (void        *) &ServerData.server_data_rx,//要发送的数据的指针,将内存块首地址通过队列“发送出去”
             (OS_MSG_SIZE  )8,   						//数据字节大小
             (OS_OPT       )OS_OPT_POST_LIFO, 			//先进先出和发布给全部任务的形式
             (OS_ERR      *)&err);
            
        }       
    }
#endif
    OSIntExit();
}

任务中请求接收消息如下:

/****************************************************
函数名:Server_task
形参:    
返回值:
函数功能:设备与服务器通信 任务处理
****************************************************/
void Server_task(void *p_arg)
{
    OS_MSG_SIZE size;
    u8 * p;
    u8 i;

    while(1)
    {
            //请求消息KEY_Msg
            p = OSQPend((OS_Q*			)&Server_DATA_Q,
                        (OS_TICK		)0,
                        (OS_OPT			)OS_OPT_PEND_BLOCKING,
                        (OS_MSG_SIZE*	)&size,
                        (CPU_TS*		)0,
                        (OS_ERR*		)&err);
            //处理串口接收到的数据
            if(err == OS_ERR_NONE)
            { 
                    ServerData.Sw_Command   = *(p+1);    //保存变量地址
                    ServerData.Sw_Value1  = ((*(p+2) << 8) & 0xFF00 ) | (*(p+3) & 0x00FF);    //保存变量数据
                    ServerData.Sw_Value2  = ((*(p+4) << 8) & 0xFF00 ) | (*(p+5) & 0x00FF);    //保存变量数据
                    for(i = 0; i < 8; i++)
                        *(p+i) = 0;
                    Server_Data_Receive(); //数据接收
                    ServerCommand_Updata();//设置数据接收处理
                }
                else//帧头和校验值不正确  清除校验值和接收缓存
                {
                    ServerData.CRC_Value = 0x0000;
                    for(i = 0; i < 8; i++)
                        *(p+i) = 0;
                }
            
        }
        OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_HMSM_STRICT,&err); //延时10ms
}

因为判断err无错误才处理中断,怀疑是err出现问题所以未进入蓝牙数据处理函数
将err添加到watch窗口,查看变量
发现app蓝牙数据传送多了之后 err 会由OS_ERR_NONE 变成 OS_ERR_INT_Q_FULL
搜索一下这个变量在哪出现
os_int.c
出现在os_int.c中,看一下这个函数是啥

void  OS_IntQPost (OS_OBJ_TYPE   type,        //内核对象类型
                   void         *p_obj,       //被发布的内核对象
                   void         *p_void,      //消息队列或任务消息
                   OS_MSG_SIZE   msg_size,    //消息的数目
                   OS_FLAGS      flags,       //事件标志组
                   OS_OPT        opt,         //发布内核对象时的选项
                   CPU_TS        ts,          //发布内核对象时的时间戳
                   OS_ERR       *p_err)       //返回错误类型
{
    CPU_SR_ALLOC();  //使用到临界段(在关/开中断时)时必需该宏,该宏声明和定义一个局部变
                     //量,用于保存关中断前的 CPU 状态寄存器 SR(临界段关中断只需保存SR)
                     //,开中断时将该值还原。 

#ifdef OS_SAFETY_CRITICAL               //如果使能(默认禁用)了安全检测
    if (p_err == (OS_ERR *)0) {         //如果错误类型实参为空
        OS_SAFETY_CRITICAL_EXCEPTION(); //执行安全检测异常函数
        return;                         //返回,不继续执行
    }
#endif

    CPU_CRITICAL_ENTER();                                   //关中断
    if (OSIntQNbrEntries < OSCfg_IntQSize) {                //如果中断队列未占满   
        OSIntQNbrEntries++;

        if (OSIntQNbrEntriesMax < OSIntQNbrEntries) {       //更新中断队列的最大使用数目的历史记录
            OSIntQNbrEntriesMax = OSIntQNbrEntries;
        }
        /* 将要重新提交的内核对象的信息放入到中断队列入口的信息记录块 */
        OSIntQInPtr->Type       = type;                     //保存内核对象类型
        OSIntQInPtr->ObjPtr     = p_obj;                    //保存被发布的内核对象
        OSIntQInPtr->MsgPtr     = p_void;                   //保存消息内容指针
        OSIntQInPtr->MsgSize    = msg_size;                 //保存消息大小
        OSIntQInPtr->Flags      = flags;                    //保存事件标志组
        OSIntQInPtr->Opt        = opt;                      //保存选项
        OSIntQInPtr->TS         = ts;                       //保存对象被发布的时间错

        OSIntQInPtr             =  OSIntQInPtr->NextPtr;    //指向下一个带处理成员
        /* 让中断队列管理任务 OSIntQTask 就绪 */
        OSRdyList[0].NbrEntries = (OS_OBJ_QTY)1;            //更新就绪列表上的优先级0的任务数为1个 
        OSRdyList[0].HeadPtr    = &OSIntQTaskTCB;           //该就绪列表的头指针指向 OSIntQTask 任务
        OSRdyList[0].TailPtr    = &OSIntQTaskTCB;           //该就绪列表的尾指针指向 OSIntQTask 任务
        OS_PrioInsert(0u);                                  //在优先级列表中增加优先级0
        if (OSPrioCur != 0) {                               //如果当前运行的不是 OSIntQTask 任务
            OSPrioSaved         = OSPrioCur;                //保存当前任务的优先级
        }

       *p_err                   = OS_ERR_NONE;              //返回错误类型为“无错误”
    } else {                                                //如果中断队列已占满
        OSIntQOvfCtr++;                                     //中断队列溢出数目加1
       *p_err                   = OS_ERR_INT_Q_FULL;        //返回错误类型为“中断队列溢出”
    }
    CPU_CRITICAL_EXIT();                                    //开中断
}

在使用OSQPost函数发送消息队列的时候,会调用OS_IntQPost,这时候中断队列满了所以err出现OS_ERR_INT_Q_FULL错误。看看我都用了啥中断,好几个定时器、串口还有任务里也用了好多临界段
在os_cfg_app.h中可以设置中断队列和中断服务任务的大小
UCOSIII使用消息队列err出现OS_ERR_INT_Q_FULL错误_第1张图片
原UCOSIII系统 中断队列大小OS_CFG_INT_Q_SIZE 设置的是10u 改为 50u
原UCOSIII系统中断服务任务的栈大小OS_CFG_INT_Q_TASK_STK_SIZE 设置的是128u 改为 200u
修改后重新测试app每隔200ms给蓝牙发数据,没出现中断队列溢出的错误了,蓝牙数据也全部解析指令处理完成。

你可能感兴趣的:(STM32,嵌入式)