FreeRTOS 队列操作——异步转同步

9 篇文章 0 订阅
8 篇文章 0 订阅

FreeRTOS 队列操作

功能说明

队列可以实现系统的异步转同步的消息机制,用于保证系统和谐运行。以下代码实现为方式。
这里尤其要注意在队列调用的实际使用方式。

代码示例
  • 源文件
/*
 * 2019-10-22
 * by fzy at leshun
 * 
 * harmony_msg.c
 */

#include <stdio.h>
#include <string.h>

#include "cmsis_os.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"


#include "harmony_msg.h"

#define HMMSG_Q_NUM      4
static QueueHandle_t HMMSG_queue[HMS_QUEUE_TYPE_NUM] = {NULL};
DTU_MSG HMMSG_Msg[HMMSG_Q_NUM];

int HMSG_init(void)
{
    int ret = 0;
    int i = 0;
    for (i = 0; i < HMS_QUEUE_TYPE_NUM; i++)
    {
        HMMSG_queue[i] = xQueueCreate(HMMSG_Q_NUM, sizeof( DTU_MSG * ));
        if (HMMSG_queue[i] == NULL)
        {
            //LSFS_DEBUG(DBG_LEVEL_ERROR, "HMMSG_queue create queue fail\r\n");
            //while(1);
            ret = -1;
            break;
        }
        
    }
    
    for (i = 0; i < HMMSG_Q_NUM; i++)
    {
        HMMSG_Msg[i].used = 0;
    }
    return ret;
}

int HMSG_Send_MSG(int msg_id, DTU_MSG *msg)
{
    int ret = -1;
    
    DTU_MSG *pMsg;
    int i;
    if (HMMSG_queue[msg_id] != NULL)
    {
        // find a useless space in HMMSG_Msg
        taskENTER_CRITICAL();
        for (i = 0; i < HMMSG_Q_NUM; i++)
        {
            if (HMMSG_Msg[i].used == 0)
            {
                HMMSG_Msg[i].used = 1;
                break;
            }
        }
        taskEXIT_CRITICAL();
        
        if (i != HMMSG_Q_NUM)   // find it
        {
            pMsg = &HMMSG_Msg[i];
            if (msg != NULL)
            {
                memcpy(pMsg, msg, sizeof(DTU_MSG));
            }               
            pMsg->msg_type = msg_id;            
            
            if( xQueueSend( HMMSG_queue[msg_id], ( void * )&pMsg, ( TickType_t ) 10 ) != pdPASS )
            {
                //LSFS_DEBUG(DBG_LEVEL_INFO, "LSFS_log_print send fail\r\n");
                return -1;
            }
            
            ret = 0;
        }
    }
    
    return ret;
}


int HMSG_Recv_MSG(int msgType, DTU_MSG *msg, int timeout)
{
    int ret = -1;
    DTU_MSG *p_msg = NULL;
    
    if (xQueueReceive(HMMSG_queue[msgType], (void *)&p_msg, ( TickType_t ) timeout) == pdTRUE) 
    {
        if (p_msg != NULL)
        {
            if (p_msg->cVal.cmd_type == DTU_MSGCMD_REBOOT)
            {
                if (msg != NULL)
                {
                    memcpy((void *)msg, (void *)p_msg, sizeof(DTU_MSG));
                    ret = DTU_MSGCMD_REBOOT;
                }
            }
            
            taskENTER_CRITICAL();
            p_msg->used = 0;
            taskEXIT_CRITICAL();
        }
    }
    
    return ret;
}


  • 头文件
/*
 * 2019-10-22
 * by fzy at leshun
 * 
 * harmony_msg.h
 */

#ifndef __HARMONY_MSG_H__
#define __HARMONY_MSG_H__


#define HMS_QUEUE_TYPE_NUM   1  /* 消息队列通道类型个数 */

#define HMS_QUEUE_TYPE_SYS   0   /* 系统 TYPE_ID */

#ifdef __cplusplus
extern "C"
{
#endif

/* 消息类型 */
#define DTU_MSGCMD_HBT			0		/* 心跳报文 */
#define DTU_MSGCMD_CMD			1		/* 普通命令 */
#define DTU_MSGCMD_REBOOT		2		/* 要求系统重新启动 */

  
#define UPLOAD_MAX_LEN	256
typedef struct _DTU_MSG_Val
{
	int		cmd_type; /* 命令类型 */
	union
	{
		int state; /* 心跳报文回复状态 */
		int cmd; /* 管理程序下发给子模块的命令 */
        
        int reboot_delay;    /* 重启延时 ms, 0 表示立刻重启*/
		struct
		{
			int	dev_code;	/* 设备号 */
			char bin[UPLOAD_MAX_LEN];
			unsigned int len;
			unsigned int type; /* 用于记录MQTT的数据包类型 */
			int app_id;
		} UploadData;
	}data;
}DTU_MSG_Val;		/* 消息队列实际值 */

typedef struct _DTU_MSG
{
    char used;     /* 是否忙碌 */
	int msg_type; /* 消息类型 */
	DTU_MSG_Val cVal; /* 实际数据 */
}DTU_MSG;


int HMSG_init(void);
int HMSG_Send_MSG(int msg_id, DTU_MSG *msg);
int HMSG_Recv_MSG(int msgType, DTU_MSG *msg, int timeout);


#ifdef __cplusplus
}
#endif

#endif

使用方法示例: main.c

void main_task()
{
	int ret;
	HMSG_init();
	DTU_MSG m;
	while(1)
	{
			ret = HMSG_Recv_MSG(HMS_QUEUE_TYPE_SYS, &m, 100);
			//
			//  处理接收的队列消息
			//
			msleep(1);	// 注意这个延时
	}
}

void task_Send_A()
{
	DTU_MSG m;
	while(1)
	{
		if (HMSG_Send_MSG(HMS_QUEUE_TYPE_SYS, &m) != 0)
    	{
        	printf("send fail\r\n");
    	}
    	msleep(5);	// 注意延时,保证发送的频率,接收函数有能力处理
	}
}

void task_Send_B()
{
	DTU_MSG m;
	while(1)
	{
		if (HMSG_Send_MSG(HMS_QUEUE_TYPE_SYS, &m) != 0)
    	{
        	printf("send fail\r\n");
    	}
    	msleep(5);	// 注意延时,保证发送的频率,接收函数有能力处理
	}
}
注意事项
  • 尤其要注意上面的延时,设计合理的接受频率和发送频率,以及优先级是保证队列正常运行的关键。
  • FreeRTOS V9.0.0 下,发送任务太快,接收任务太慢时,会出现队列接收重复的现象,严重会影响业务逻辑。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值