一个严谨的FIFO(RING BUFF)

1、概述

        该FIFO主要用于处理STM32的相关外设数据接收和发送使用。按照在STM32无操作系统(裸机)情况下使用时FIFO写入位置的不同,将FIFO分为两类。

  • 主函数写入

        使用场景:

                串口发送,主函数将串口数据压入到发送FIFO,调用发送函数将FIFO数据读取到发送缓冲区,发送完成中断时,继续判断FIFO中是否存在新的待发送数据,继续进行发送。

        存在的问题:

                调用串口发送函数时,串口繁忙,数据积压在FIFO中。进入发送完成中断后,此时FIFO正在写入,完成中断不能实现FIFO剩余数据的发送

        解决措施:

                使用定时器,定时对发送FIFO的使用量进行监控,不空则进行数据发送。

  • 外设中断写入

        使用场景:

                串口接收,中断中将数据压入到接收FIFO

        存在的问题:

                串口接收中断时,要将数据写入到FIFO中,此时FIFO正在主函数中进行访问(busy)无法将数据进行写入。数据若不进行备份,则跳出中断后数据丢失。

        解决措施:

                提供备份缓冲区,当中断写入数据时FIFO繁忙,将数据写入到备份缓冲区

        存在问题2:

                备份缓冲区数据什么时候写入到FIFO。

        解决措施:

                再次进入中断时,先将备份缓冲区数据写入到FIFO,再将新接收到的数据写入到FIFO。

                若后续无中断进入,通过定时器回调功能实现备份缓冲区数据的写入功能。

  • 为什么要设置繁忙标志

        因为涉及到主函数与中断同时进行读写FIFO参数的情况,可能出现全局变量错误的情况,导致程序崩溃。程序方面FIFO可能被主函数和中断访问的变量使用volatile进行限制。

  • 繁忙标志位什么时候置位

        主函数对FIFO进行操作时需要对BUSY进行置位和复位操作

        中断操作时进行busy的判断,因为中断高于主函数,不存在中断被主函数打断问题,所以中断不用对busy进行置位复位操作

  • 定时器与数据外设(串口)中断优先级问题

        定时器的优先级需要高于外设中断优先级。同时在中断中进行FIFO处理时还需要对INT标志位进行置位复位操作

2、FIFO结构体及说明

typedef struct FifoTypeDef
{
    //构成链表。
    struct FifoTypeDef*     Next;

    //FIFO节本元素。
    volatile INT16U         Depth;              //FIFO的深度
    volatile INT16U         CntUsed;            //使用了的元素个数
    INT8U*         			Push;               //写入的位置
    INT8U*         			Pull;               //读取的位置。
    INT8U*                  Buf;                //数据缓冲区
    //FIFO计算元素
    INT8U*                  EndPos;         	//缓冲区的结尾处指针。

    //FIFO类型
    FifoType                Type;

    //标志位。                                        写                读
    INT8U                   InitFlag;      //    主颜色初始化      所有FIFO相关函数。
    volatile INT8U          BusyFlag;      //      主函数             中断
    volatile INT8U          IntFlag;       //       中断            定时器中断

    //中断写入时的备份缓冲区。
    volatile INT16U         BackCount;
    INT8U*                  BackBuf;

    //定时器中断回调函数
    void                    (*func_timmer)();
}FifoTypeDef;

基本元素

  • Depth:FIFO的深度,能存储原始的个数(元素的大小为1字节)
  • CntUsed:FIFO使用了的个数
  • Push:FIFO的写入指针
  • Pull:FIFO的读取指针
  • Buf:FIFO的缓冲区

扩展元素

  • Next:用于构成FIFO链表,定时器中断中进行FIFO的遍历
  • EndPos:缓冲区的结尾地址,用于计算
  • Type:FIFO的类型,中断写入,还是主函数写入
  • InitFlag:初始化标志位
  • BusyFlag:FIFO繁忙标志位
  • InitFlag:FIFO在中断中进行操作标志位
  • BackCount:备份缓冲区使用了的数量
  • BackBuf:备份缓冲区
  • func_timer():FIFO的定时器回调函数

3、相关函数说明

3.1相关宏定义

#define FIFO_SET_BUSY(fifo)     (fifo->BusyFlag = 1)
#define FIFO_RESET_BUSY(fifo)   (fifo->BusyFlag = 0)
#define FIFO_GET_BUSY(fifo)     (fifo->BusyFlag == 1? 1:0)

#define FIFO_SET_INT(fifo)      (fifo->IntFlag = 1)
#define FIFO_RESET_INT(fifo)    (fifo->IntFlag = 0)
#define FIFO_GET_INT(fifo)      (fifo->IntFlag == 1? 1:0)

#define FIFO_INIT_CHECK(fifo)   (fifo->InitFlag == 1? 1:0)

置位,复位,查询FIFO的繁忙,中断,初始化状态。

3.2内部函数

3.2.1相关指针操作函数

指针的相关操作函数,主要用于对FIFO的push和pull指针进行更新,同时在查询FIFO时查询位置到FIFO缓冲容量结尾的元素个数的计算。

static inline void func_fifo_PushOffset(FifoTypeDef* fifo,INT16U offset)
{
	fifo->Push += offset;
	if(fifo->Push > fifo->EndPos)
	{
		fifo->Push = fifo->Push - fifo->Depth;
	}
}

更新push指针的位置。需要注意到FIFO的缓冲区结尾时回头的情况

static inline void func_fifo_PullOffset(FifoTypeDef* fifo,INT16U offset)
{
	fifo->Pull += offset;
	if(fifo->Pull > fifo->EndPos)
	{
		fifo->Pull = fifo->Pull - fifo->Depth;
	}
}

更新pull指针的位置,同上。

static inline INT16U func_fifo_CalPoint2end(FifoTypeDef* fifo, INT8U* point)
{
	return  fifo->EndPos - point + 1;
}

计算某个指针到fifo缓冲末尾的元素个数。

3.2.2底层操作函数

        FIFO的底层操作函数,底层操作函数不对FIFO的标志位进行判断,时主函数和中断操作FIFO的具体实现步骤。

/**
***************************************************
* @brief   func_fifo_CmpLower
* @note    比较FIFO重数据的底层函数,不进行标志位操作。
* @param   fifo
*                           指向待操作的FIFO,
*          ind
*                           从FIFO的pull后面的第ind个开始
*          len
*                           比较的长度为len
*          data
*                           比较的数据
*          timeout
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
static FifoErr func_fifo_CmpLower(FifoTypeDef* fifo, const INT16U ind, const INT16U len, const INT8U* data)
{
    //判断FIFO中是否有足够的数量进行比较。
	if(ind + len > fifo->CntUsed)
    {
        return FIFO_ENUM;
    }

	//上面的判断可以保证开始比较的位置+len不会超过FIFO的容量。
    INT8U* point = fifo->Pull + ind;
    if(point > fifo->EndPos)
    	point = point - fifo->Depth;

    INT16U len2end = func_fifo_CalPoint2end(fifo,point);
    if(len2end >= len)
    {
        if(memcmp(data,point,len) == 0)
        {
            return FIFO_EOK;
        }
        else
        {
            return FIFO_EFAILED;
        }
    }
    else
    {
        if(memcmp(data,point,len2end) == 0 && memcmp(data+len2end,fifo->Buf,len-len2end) == 0 )
        {
            return FIFO_EOK;
        }
        else
        {
            return FIFO_EFAILED;
        }
    }
}

/**
***************************************************
* @brief   func_fifo_DeleteLower
* @note    删除FIFO数据的底层函数,不进行标志位操作。
* @param   fifo
*                           指向待操作的FIFO,
*          num
*                           删除的元素个数
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
FifoErr func_fifo_DeleteLower(FifoTypeDef* fifo, INT16U num)
{
    //删除的数据大于FIFO已使用数据。
    if(num > fifo->CntUsed)
    {
        return FIFO_ENUM;
    }

    //开始删除数据
    INT16U len2end = func_fifo_CalPoint2end(fifo,fifo->Pull);
    if(len2end >= num)
    {
        memset(fifo->Pull , 0 , num);
    }
    else
    {
        memset(fifo->Pull , 0 , len2end);
        memset(fifo->Buf , 0 , num - len2end);
    }
    fifo->CntUsed -= num;
    func_fifo_PullOffset(fifo,num);
    return FIFO_EOK;
}
/**
***************************************************
* @brief   func_fifo_Push2Back
* @note    中断中进行FIFO写入操作时,FIFO繁忙调用该函数写入到back
* @param   fifo
*                           指向待操作的FIFO,
*          num
*                           删除的元素个数
*          data
*                           指向写入数据
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
static void func_fifo_Push2Back(FifoTypeDef* fifo, INT16U num, INT8U* data)
{
    INT16   offset = 0;

    INT8U*  srcpos = 0;
    INT8U*  despos = 0;
    INT16U  len = 0;

    //现有数据和待写入数据的总数大于BACK的容量,进行元素替换操作。
    if(num + fifo->BackCount > fifo->Depth)
    {
    	offset = num + fifo->BackCount - fifo->Depth;
    	//现有元素全部被替换。
    	if(offset >= fifo->BackCount)
    	{
    		offset = num - fifo->Depth;
    		//写入新数据
    		srcpos = data+offset;
    		despos = fifo->BackBuf;
    		len = fifo->Depth;
    		memcpy(despos, srcpos, len);
    	}
    	else
    	{
    		//更新原有数据
    		srcpos = fifo->BackBuf + offset;
    		despos = fifo->BackBuf;
    		len = fifo->BackCount - offset;
    		memcpy(despos, srcpos, len);
    		//写入新数据。
    		srcpos = data;
    		despos = despos + len;
    		len = num;
    		memcpy(despos, srcpos, len);
    	}
    	fifo->BackCount = fifo->Depth;
    }
    //现有数据和待写入数据的总数不大于FIFO的容量,将现有数据附加到back
    else
    {
		srcpos = data;
		despos = fifo->BackBuf + fifo->BackCount;
		len = num;
		fifo->BackCount += num;
		memcpy(despos, srcpos, len);
	}
}

/**
***************************************************
* @brief   func_fifo_Push2Fifo
* @note    将数据写入到FIFO缓冲区中,仅在FIFO不繁忙时调用,
*          1、首先将Back数据写入到FIFO中。
*          2、将待写入数据写入到FIFO中。
* @param   fifo
*                           指向待操作的FIFO,
*          num
*                           删除的元素个数
*          data
*                           指向写入数据
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
static void func_fifo_Push2Fifo(FifoTypeDef* fifo, INT16U num, INT8U* data)
{
	INT16   offset = 0;
	INT16   len2end = func_fifo_CalPoint2end(fifo,fifo->Push);
	INT16   num2push = 0;

	INT8U*  srcpos = 0;
	INT8U*  despos = 0;
	INT16U  len = 0;

	//back数据和data数据之和大于depth,存在back和data丢弃数据的情况。
	if(fifo->BackCount + num > fifo->Depth)
	{
		num2push = fifo->Depth;
		offset = fifo->BackCount + num -fifo->Depth;
	}
	else
	{
		num2push = fifo->BackCount + num;
	}

	//到FIFO结尾可以容纳写入的数据,说明不存在覆盖情况。将back和带写入数据写入即可。
	if(len2end >= num2push)
	{
		//写入BACK
		srcpos = fifo->BackBuf;
		despos = fifo->Push;
		len = fifo->BackCount;
		memcpy(despos, srcpos, len);
		//写入data
		srcpos = data;
		despos = despos + len;
		len = num;
		memcpy(despos, srcpos, len);
	}
	//存在回头写的情况
	else
	{
		//偏移量大于back的个数,back区域不执行写入操作。
		if(offset >= fifo->BackCount)
		{
			//写入到队尾。
			srcpos = data + offset - fifo->BackCount;
			despos = fifo->Push;
			len = len2end;
			memcpy(despos, srcpos, len);
			//重头写入
			srcpos = srcpos + len;
			despos = fifo->Buf;
			len = num2push - len2end;
			memcpy(despos, srcpos, len);
		}
		//写入备份区域和数据区域数据。
		else
		{
			INT16U back2push = fifo->BackCount - offset;
			if(len2end >= back2push)
			{
				//写入back
				srcpos = fifo->BackBuf + offset;
				despos = fifo->Push;
				len = back2push;
				memcpy(despos, srcpos, len);
				//写入DATA到队尾
				srcpos = data;
				despos = despos + len;
				len = len2end - len;
				memcpy(despos, srcpos, len);
				//重头写
				srcpos = data + len;
				despos = fifo->Buf;
				len = num2push - back2push ;
				memcpy(despos, srcpos, len);
			}
			else
			{
				//写入back
				srcpos = fifo->BackBuf + offset;
				despos = fifo->Push;
				len = len2end;
				memcpy(despos, srcpos, len);
				//重头写BACK
				srcpos = srcpos + len;
				despos = fifo->Buf;
				len = back2push - len;
				memcpy(despos, srcpos, len);
				//写DATA
				srcpos = data;
				despos = despos + len;
				len = num2push - back2push;
				memcpy(despos, srcpos, len);
			}
		}
	}
	fifo->BackCount = 0;
	if(num2push + fifo->CntUsed > fifo->Depth)
	{
		num2push -= 1;
		num2push += 1;
	}
	func_fifo_PushOffset(fifo,num2push);

	fifo->CntUsed += num2push;
	if(fifo->CntUsed >= fifo->Depth)
	{
		fifo->CntUsed = fifo->Depth;
		fifo->Pull = fifo->Push;
	}
}

static FifoErr func_fifo_PullLower(FifoTypeDef* fifo, INT16U num, INT8U* data, INT16U* len, INT8U mode)
{
    INT16U  len2end = func_fifo_CalPoint2end(fifo,fifo->Pull);
    INT16U  num2pull = 0;

    if(fifo->CntUsed == 0)
    {
    	return FIFO_ENUM;
    }

    //全部模式
    if(mode == 0)
    {
    	if(fifo->CntUsed >= num)
    	{
    		num2pull = num;
    	}
    	else
    	{
    		return FIFO_ENUM;
    	}
    }
    //PART模式
    else
    {
    	if(fifo->CntUsed >= num)
    	{
    		num2pull = num;
    	}
    	else
    	{
    		num2pull = fifo->CntUsed;
    	}
    	*len = num2pull;
    }

	if(len2end >= num2pull)
	{
		memcpy(data , fifo->Pull , num2pull);
		memset(fifo->Pull , 0 , num2pull);
	}
	//需要重头读取。
	else
	{
		memcpy(data , fifo->Pull, len2end);
		memset(fifo->Pull , 0 , len2end);
		memcpy(data+len2end , fifo->Buf , num2pull-len2end);
		memset(fifo->Buf , 0 , num2pull-len2end);
	}
	//读位置和使用量更新。
	func_fifo_PullOffset(fifo,num2pull);
	fifo->CntUsed -= num2pull;
	return FIFO_EOK;
}

3.2.3FIFO函数实现

        获取FIFO驱动的版本和FIFO定时器的初始化。

/**
***************************************************
* @brief   func_fifo_GetVer
* @note    获取FIFO文件的版本号。
* @param   NONE
* @retval  NONE
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
INT16U func_fifo_GetVer()
{
	return VER_FIFO;
}

/**
***************************************************
* @brief   func_fifo_Init
* @note    启动FIFO使用的定时器。
* @param   NONE
* @retval  NONE
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
void func_fifo_Init()
{
	extern TIM_HandleTypeDef htim4;

	HAL_TIM_Base_Start_IT(&htim4);
}

        创建FIFO,初始化FIFO的相关遍历,初始化FIFO的链表

/**
***************************************************
* @brief   func_fifo_Create
* @note    创建FIFO
* @param   depth
*               FIFO的深度。
*          type
*               FIFO类型,是中断写入还是中断读取。
* @retval  0:
*                           失败
*                    其他:
*                           成功,FIFO指针
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
FifoTypeDef* func_fifo_Create(INT16U depth, FifoType type)
{
    FifoTypeDef* p = FifoChain;

    if(p == NULL)
    {
        p = malloc(sizeof(FifoTypeDef));
        if(p == NULL)
        {
            return NULL;
        }
        FifoChain = p;
    }

    else
    {
    	while(p->Next != NULL)
    	{
    		p = p->Next;
    	}
    	p->Next = malloc(sizeof(FifoTypeDef));
    	p = p->Next;
    	if(p == NULL)
		{
			return NULL;
		}
    }

    p->Buf = malloc(depth);
    if(p->Buf == NULL)
    {
    	if(FifoChain ==  p)
    	{
    		FifoChain = 0;
    	}
        free(p);
        return NULL;
    }
    memset(p->Buf,0,depth);

	p->BackBuf = malloc(depth);
	if(p->BackBuf == NULL)
	{
    	if(FifoChain ==  p)
    	{
    		FifoChain = 0;
    	}
    	free(p->Buf);
    	free(p);
		return NULL;
	}
	p->BusyFlag = 0;
	p->IntFlag = 0;
	p->BackCount = 0;

    p->Type         = type;
    p->Next         = NULL;
    p->InitFlag     = 1;
    p->Depth        = depth;
    p->CntUsed      = 0;
    p->Push         = p->Buf;
    p->Pull         = p->Buf;
    p->EndPos       = p->Buf + p->Depth - 1;

    return p;
}

FIFO元素的写入,包括中断写入和普通写入两种。中断写入首先进行busy标志位判断,busy时将数据写入到back。

/**
***************************************************
* @brief   func_fifo_Push
* @note    向FIFO中写入数据
* @param   fifo
*                           指向待操作的FIFO,
*          num
*                            写入的数据量
*          data
*                            指向写入的数据
*          timeout
*                           等待busy 超时时间,单位ms
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
FifoErr func_fifo_Push(FifoTypeDef* fifo, INT16U num, INT8U* data)
{
    if(FIFO_INIT_CHECK(fifo) == 0)
    {
    	return FIFO_EINIT;
    }

    FIFO_SET_BUSY(fifo);
    func_fifo_Push2Fifo(fifo, num,  data);
    FIFO_RESET_BUSY(fifo);

    return FIFO_EOK;
}

FifoErr func_fifo_PushInt(FifoTypeDef* fifo, INT16U num, INT8U* data)
{
    if(FIFO_INIT_CHECK(fifo) == 0)
    {
    	return FIFO_EINIT;
    }

    FIFO_SET_INT(fifo);
    if(FIFO_GET_BUSY(fifo))
    {
    	func_fifo_Push2Back(fifo, num,  data);
    }
    else
    {
    	func_fifo_Push2Fifo(fifo, num,  data);
    }
    FIFO_RESET_INT(fifo);
    return FIFO_EOK;
}

FIFO数据的读取。分为三个函数

func_fifo_Pull:读取FIFO的数据,若读取个数大于FIFO的使用量返回错误

func_fifo_PullPart:部分读取,当读取数大于FIFO的使用量时,读取FIFO已使用的个数。

func_fifo_PullPartInt:中断中使用,进行部分读取。

/**
***************************************************
* @brief   func_fifo_Pull
* @note    从FIFO中读取数据
* @param   fifo
*                           指向待操作的FIFO,
*          num
*                            读取的数据量
*          data
*                            指向读取数据缓存区
*          timeout
*                           等待busy 超时时间,单位ms
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
FifoErr func_fifo_Pull(FifoTypeDef* fifo, INT16U num, INT8U* data)
{
	FifoErr ret = FIFO_EOK;
    if(FIFO_INIT_CHECK(fifo) == 0)
    {
    	return FIFO_EINIT;
    }

	FIFO_SET_BUSY(fifo);
	ret = func_fifo_PullLower(fifo, num, data, 0, 0);
	FIFO_RESET_BUSY(fifo);

	return ret;
}

FifoErr func_fifo_PullPart(FifoTypeDef* fifo, INT16U num, INT8U* data, INT16U* len)
{
	FifoErr ret = FIFO_EOK;
    if(FIFO_INIT_CHECK(fifo) == 0)
    {
    	return FIFO_EINIT;
    }

	FIFO_SET_BUSY(fifo);
	ret = func_fifo_PullLower(fifo, num, data, len, 1);
	FIFO_RESET_BUSY(fifo);

	return ret;
}

FifoErr func_fifo_PullPartInt(FifoTypeDef* fifo, INT16U num, INT8U* data, INT16U* len)
{
	FifoErr ret = FIFO_EOK;

    if(FIFO_INIT_CHECK(fifo) == 0)
    {
    	return FIFO_EINIT;
    }

    FIFO_SET_INT(fifo);
	if(FIFO_GET_BUSY(fifo))
	{
		ret = FIFO_EFAILED;
	}
	else
	{
		ret =func_fifo_PullLower(fifo, num, data, len, 1);
	}
	FIFO_RESET_INT(fifo);
	return ret;
}

FIFO数据的拷贝,只进行数据拷贝,不操作FIFO的相关指针

/**
***************************************************
* @brief   func_fifo_Copy
* @note    从FIFO中读取数据
* @param   fifo
*                           指向待操作的FIFO,
*          ind
*                            从FIFO的pull后面的第ind个开始
*          len
*                           拷贝数据的长度
*          data
*                            拷贝数据的缓冲区
*          timeout
*                           等待busy 超时时间,单位ms
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
FifoErr func_fifo_Copy(FifoTypeDef* fifo , INT16U ind, INT16U len, INT8U* data)
{
    if(FIFO_INIT_CHECK(fifo) == 0)
    {
    	return FIFO_EINIT;
    }

	FIFO_SET_BUSY(fifo);
    //读取数据量大于FIFO容量,不进行读取操作。
    if(ind + len > fifo->CntUsed)
    {
        //释放FIFO繁忙标志位。
    	FIFO_RESET_BUSY(fifo);
        return FIFO_ENUM;
    }

    //开始数据拷贝
    INT8U* point = fifo->Pull + ind;
    if(point > fifo->EndPos)
    {
        point = point - fifo->Depth;
    }
    INT16U len2end = func_fifo_CalPoint2end(fifo,fifo->Pull);
    if(len2end >= len)
    {
        memcpy(data,point,len);
    }
    else
    {
        memcpy(data , point , len2end);
        memcpy(data+len2end , fifo->Buf , len-len2end);
    }
    FIFO_RESET_BUSY(fifo);
    return FIFO_EOK;
}

删除FIFO中的元素

/**
***************************************************
* @brief   func_fifo_Delete
* @note    从FIFO中删除数据
* @param   fifo
*                           指向待操作的FIFO,
*          num
*                           删除数据的个数
*          timeout
*                           等待busy 超时时间,单位ms
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
FifoErr func_fifo_Delete(FifoTypeDef* fifo , INT16U num)
{
    FifoErr err = FIFO_EOK;

    if(FIFO_INIT_CHECK(fifo) == 0)
    {
    	return FIFO_EINIT;
    }

	FIFO_SET_BUSY(fifo);
    err =  func_fifo_DeleteLower(fifo, num);
    FIFO_RESET_BUSY(fifo);

    return err;
}

比较FIFO重的元素,不对FIFO指针进行操作。

/**
***************************************************
* @brief   func_fifo_Cmp
* @note    比较FIFO中数据
* @param   fifo
*                           指向待操作的FIFO,
*          ind
*                            从FIFO的pull后面的第ind个开始
*          len
*                           比较的长度为len
*          data
*                            比较的数据
*          timeout
*                           等待busy 超时时间,单位ms
*          timeout
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
FifoErr func_fifo_Cmp(FifoTypeDef* fifo, INT16U ind, INT16U len, INT8U* data)
{
	FifoErr err = FIFO_EOK;

	if(FIFO_INIT_CHECK(fifo) == 0)
	{
		return FIFO_EINIT;
	}

	FIFO_SET_BUSY(fifo);
	err = func_fifo_CmpLower(fifo, ind, len, data);
	FIFO_RESET_BUSY(fifo);

	return err;
}

查找FIFO中的元素,对不符合元素进行删除,直到查找到或者FIFO容量不符合查找长度时停止

/**
***************************************************
* @brief   func_fifo_FindDelete
* @note    比较FIFO中数据
* @param   fifo
*                           指向待操作的FIFO,
*          ind
*                            从FIFO的pull后面的第ind个开始
*          len
*                           比较的长度为len
*          data
*                            比较的数据
*          timeout
*                           等待busy 超时时间,单位ms
*          timeout
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
FifoErr func_fifo_FindDelete(FifoTypeDef* fifo, INT16U len, INT8U* data)
{
    INT16U          cycle = 0;
    FifoErr         err = FIFO_EOK;

    if(FIFO_INIT_CHECK(fifo) == 0)
    {
    	return FIFO_EINIT;
    }

 	FIFO_SET_BUSY(fifo);
    err = FIFO_EFAILED;
    while((fifo->CntUsed - cycle) >= len)
    {
    	err = func_fifo_CmpLower(fifo, cycle++, len, data);
        if(err == FIFO_EOK)
        {
            break;
        }
    }
    func_fifo_DeleteLower(fifo, cycle-1);
    FIFO_RESET_BUSY(fifo);

    return err;
}

从FIFO的指定位置开始查找,不进行元素的删除和相关指针的操作

/**
***************************************************
* @brief   func_fifo_FindDelete
* @note    比较FIFO中数据
* @param   fifo
*                           指向待操作的FIFO,
*          ind
*                            从FIFO的pull后面的第ind个开始
*          len
*                           比较的长度为len
*          data
*                            比较的数据
*          timeout
*                           等待busy 超时时间,单位ms
*          timeout
* @retval  FifoErr
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
FifoErr func_fifo_Find(FifoTypeDef* fifo, INT16U ind, INT8U* data, INT16U len,  INT16U* pos)
{
    FifoErr err = FIFO_EOK;
    INT16U      cycle = 0;

    if(FIFO_INIT_CHECK(fifo) == 0)
    {
    	return FIFO_EINIT;
    }

 	FIFO_SET_BUSY(fifo);
    INT16U times = fifo->CntUsed - ind - len - 1;
    err = FIFO_EFAILED;
    while(cycle < times)
    {
        if(func_fifo_CmpLower(fifo, ind+cycle, len, data) == FIFO_EOK)
        {
            err = FIFO_EOK;
            *pos = cycle;
            break;
        }
        cycle++;
    }
    FIFO_RESET_BUSY(fifo);

    return err;
}

获取FIFO的使用量,需要操作busy标志位

INT16U func_fifo_GetUsed(FifoTypeDef* fifo)
{
	INT16U num = 0;

	FIFO_SET_BUSY(fifo);
	num = fifo->CntUsed;
	FIFO_RESET_BUSY(fifo);
	return num;
}

FIFO使用定时器的回调函数。回调函数中判断FIFO的标志位。对不同类型的FIFO执行不同的操作。

中断写入类型的FIFO,进行备份去数据的写入

/**
***************************************************
* @brief   func_fifo_TimerCallBack
* @note    FIFO链表定时器中断回调
* @param   NONE
* @retval  NONE
* @data    2021.09.03
* @auth    WXL
* @his     1.0.0.0     2021.09.03     WXL
*               create
***************************************************
**/
void func_fifo_TimerCallBack()
{
	FifoTypeDef*    point = FifoChain;

	while(point!= NULL)
	{
		//FIFO 不繁忙   不在中断中
		if(FIFO_GET_BUSY(point) == 0 && FIFO_GET_INT(point) == 0)
		{
			if(point->Type == FIFO_TYPE_INT_PUSH && point->BackCount != 0)
			{
				func_fifo_Push2Fifo(point, 0, 0);
			}
			else if(point->Type == FIFO_TYPE_INT_PULL && point->CntUsed != 0)
			{
				point->func_timmer();
			}
		}
		point = point->Next;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值