一个严谨的FIFO(RING BUFF)2

4 篇文章 0 订阅
3 篇文章 0 订阅

增加操作系统RT_THREAD支持

在操作系统进行FIFO操作时,删除了FIFO类型,相关的繁忙标志位及备份缓冲区和回调函数功能。

在使用RT-THREAD时,中断接收数据均 存在缓冲区,数据得以保存。使用互斥量代替了原有的busy标志位,线程通过等待信号量的方式来实现对FIFO元素的互斥操作

增加宏定义SYS_RTT来实现驱动在有误操作系统情况下的切换

#ifndef _FUNC_FIFO_H_
#define _FUNC_FIFO_H_

#define SYS_RTT

/*************************************************************************************************************************
 *                                                   头文件
**************************************************************************************************************************/
#ifdef SYS_RTT
#include <rtthread.h>
#else
#endif
#include "config.h"
/*************************************************************************************************************************
 *                                                   宏定义
**************************************************************************************************************************/
#define VER_FIFO  200
/*************************************************************************************************************************
 *                                                    枚举
**************************************************************************************************************************/
typedef enum
{
    FIFO_EOK=0,
    FIFO_EINIT,
    FIFO_ENUM,
    FIFO_EFAILED,
}FifoErr;
#ifdef SYS_RTT
#else
typedef enum
{
    FIFO_TYPE_INT_PUSH,
    FIFO_TYPE_INT_PULL,
}FifoType;
#endif
/*************************************************************************************************************************
 *                                                     结构体
**************************************************************************************************************************/
typedef struct FifoTypeDef
{
#ifdef SYS_RTT
#else
    //构成链表。
    struct FifoTypeDef*     Next;
#endif

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


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


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

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

/*************************************************************************************************************************
 *                                                      函数声明
**************************************************************************************************************************/
extern void func_fifo_Init();

#ifdef SYS_RTT
extern FifoTypeDef* func_fifo_Create(INT16U depth);
#else
extern FifoTypeDef* func_fifo_Create(INT16U depth, FifoType type);
#endif

extern FifoErr func_fifo_Push(FifoTypeDef* fifo, INT16U num, INT8U* data);

#ifdef SYS_RTT
#else
extern FifoErr func_fifo_PushInt(FifoTypeDef* fifo, INT16U num, INT8U* data);
#endif


extern FifoErr func_fifo_Pull(FifoTypeDef* fifo, INT16U num, INT8U* data);
extern FifoErr func_fifo_PullPart(FifoTypeDef* fifo, INT16U num, INT8U* data, INT16U* len);

#ifdef SYS_RTT
#else
extern FifoErr func_fifo_PullPartInt(FifoTypeDef* fifo, INT16U num, INT8U* data, INT16U* len);
#endif


extern FifoErr func_fifo_Copy(FifoTypeDef* fifo , INT16U ind, INT16U len, INT8U* data);
extern FifoErr func_fifo_Delete(FifoTypeDef* fifo , INT16U num);
extern FifoErr func_fifo_Cmp(FifoTypeDef* fifo, INT16U ind, INT16U len, INT8U* data);
extern FifoErr func_fifo_FindDelete(FifoTypeDef* fifo, INT16U len, INT8U* data);
extern FifoErr func_fifo_Find(FifoTypeDef* fifo, INT16U ind, INT8U* data, INT16U len,  INT16U* pos);
extern INT16U  func_fifo_GetUsed(FifoTypeDef* fifo);

#ifdef SYS_RTT
#else
extern void func_fifo_TimerCallBack();
#endif

#endif

/*   说明:
 *      FIFO用来实现如下功能
 *      1)中断数据的接收,主函数的数据访问解析(串口接收    其他带中断的外设进行数据采集接收)
 *      2)主函数向FIFO中写入数据,中断中进行数据处理(串口发送)
 *
 *      整个驱动文件采用busy标志位来解决中断和主函数间对于全局变量的访问问题。
 *      busy仅在主函数中可进行写操作,中断中仅进行busy读取的操作。
 *
 *      FIFO写入数据分为两种模式
 *      1)普通写入(主函数写入)
 *           设置繁忙标志位,直接进行写入。
 *      2)中断写入
 *           中断写入时,busy不繁忙,直接写入到FIFO中,写入前需要判断备份区域是否存在数据,若存在则将数据先行写入
 *           中断写入时,busy繁忙,将数据写入到备份区域。(中断数据若不进行处理,则数据丢失)。
 *               当数据被写入到备份区域时可通过如下两种模式将备份区域数据写到fifo中。
 *                  1),下次中断时,不繁忙,在写入data数据前会处理备份区域数据。
 *                  2),设定定时器,定时遍历FIFO链表,当检查到FIFO不在中断中且不繁忙时,会将数据写入到fifo中。
 *
 *      定时器实现的功能
 *      1)对于中断接收类型的FIFO,进行备份区域数据的写入,需要注意一下两个条件
 *           不在中断中
 *           不繁忙
 *      2)对中断发送类型的FIFO,进行FIFO使用量查询,当查询到有数据时,通过回调函数进行数据处理。
 *
 *      使用说明:
 *      1)首先进行FIFO的初始化,使用func_fifo_create实现。
 *      2)针对创建FIFO类型的不同,通过如下几个函数进行FIFO数据的写入操作。
 *          func_fifo_Push(FifoTypeDef* fifo, INT16U num, INT8U* data);
 *                  主函数写入
 *          func_fifo_PushInt(FifoTypeDef* fifo, INT16U num, INT8U* data);
 *                  中断写入
 *      3)针对不同类型的FIFO,使用如下函数进行FIFO数据操作。
 *          func_fifo_Pull(FifoTypeDef* fifo, INT16U num, INT8U* data);
 *                  主函数调用,若fifo内容不足返回错误。
 *          func_fifo_PullPart(FifoTypeDef* fifo, INT16U num, INT8U* data, INT16U* len);
 *                  主函数调用,若fifo内容不足,通过参数len返回实际pull的数值。
 *          func_fifo_PullPartInt(FifoTypeDef* fifo, INT16U num, INT8U* data, INT16U* len);
 *                  中断调用,若fifo内容不足,通过参数len返回实际pull的数值。
 *      4)以下函数实现主函数中对FIFO内部内容的查找,判断和删除的工作。
 *          func_fifo_Copy(FifoTypeDef* fifo , INT16U ind, INT16U len, INT8U* data);
 *                  复制FIFO中的数据,不对FIFO元素进行操作。
 *          func_fifo_Delete(FifoTypeDef* fifo , INT16U num);
 *                  删除FIFO的元素
 *          func_fifo_Cmp(FifoTypeDef* fifo, INT16U ind, INT16U len, INT8U* data);
 *                  比较FIFOA中的元素
 *          func_fifo_FindDelete(FifoTypeDef* fifo, INT16U len, INT8U* data);
 *                  查找FIFO中元素,对不符合内容进行删除
 *          func_fifo_Find(FifoTypeDef* fifo, INT16U ind, INT8U* data, INT16U len,  INT16U* pos);
 *                  查找FIFO中元素,通过pos返回找到的位置
 *
 *
*************************************************************************************************************************
 *      @his
 *          ver:V1.0.0.0
 *          author:WXL
 *          date:2021.09.03
*      @his
 *          ver:V2.0.0.0
 *          author:WXL
 *          date:2021.09.10
 *          note:
 *                               使用信号量代替busy标志,适配RTT
 * */
/*************************************************************************************************************************
 *                                                  头文件
**************************************************************************************************************************/
#include "func_fifo.h"
/*************************************************************************************************************************
 *                                                   宏定义
**************************************************************************************************************************/
#define FIFO_INIT_CHECK(fifo)   (fifo->InitFlag == 1? 1:0)
#ifdef SYS_RTT
#define FIFO_MALLOC     rt_malloc
#define FIFO_FREE       rt_free
#define FIFO_MEMCPY     rt_memcpy
#define FIFO_MEMSET     rt_memset
#define FIFO_MEMCMP     rt_memcmp
#else
#define FIFO_MALLOC     malloc
#define FIFO_FREE       free
#define FIFO_MEMCPY     memcpy
#define FIFO_MEMSET     memset
#define FIFO_MEMCMP     memcmp
#endif



/*************************************************************************************************************************
 *                                                   全局变量
**************************************************************************************************************************/
#ifdef SYS_RTT
#else
FifoTypeDef* FifoChain = NULL;
#endif

/*************************************************************************************************************************
 *                                                    局部函数
**************************************************************************************************************************/
#ifdef SYS_RTT
static inline void FIFO_SET_BUSY(FifoTypeDef* fifo)
{
    rt_mutex_take(fifo->Mutex, RT_WAITING_FOREVER);
}
static inline void FIFO_RESET_BUSY(FifoTypeDef* fifo)
{
    rt_mutex_release(fifo->Mutex);
}
#else
static inline void FIFO_SET_BUSY(FifoTypeDef* fifo)
{
    fifo->BusyFlag = 1;
}
static inline void FIFO_RESET_BUSY(FifoTypeDef* fifo)
{
    fifo->BusyFlag = 0;
}
static inline INT8U FIFO_GET_BUSY(FifoTypeDef* fifo)
{
    return fifo->BusyFlag;
}

static inline void FIFO_SET_INT(FifoTypeDef* fifo)
{
    fifo->IntFlag = 1;
}
static inline void FIFO_RESET_INT(FifoTypeDef* fifo)
{
    fifo->IntFlag = 0;
}
static inline INT8U FIFO_GET_INT(FifoTypeDef* fifo)
{
    return fifo->IntFlag;
}
#endif

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

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

static inline INT16U func_fifo_CalPoint2end(FifoTypeDef* fifo, INT8U* point)
{
    return  fifo->EndPos - point + 1;
}
/**
***************************************************
* @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(FIFO_MEMCMP(data,point,len) == 0)
        {
            return FIFO_EOK;
        }
        else
        {
            return FIFO_EFAILED;
        }
    }
    else
    {
        if(FIFO_MEMCMP(data,point,len2end) == 0 && FIFO_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)
    {
        FIFO_MEMSET(fifo->Pull , 0 , num);
    }
    else
    {
        FIFO_MEMSET(fifo->Pull , 0 , len2end);
        FIFO_MEMSET(fifo->Buf , 0 , num - len2end);
    }
    fifo->CntUsed -= num;
    func_fifo_PullOffset(fifo,num);
    return FIFO_EOK;
}

#ifdef SYS_RTT
/**
***************************************************
* @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)
{
    INT16U   offset = 0;
    INT16U   len2end = func_fifo_CalPoint2end(fifo,fifo->Push);
    INT16U   num2push = 0;

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

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

    //到FIFO结尾可以容纳写入的数据,说明不存在覆盖情况。将back和带写入数据写入即可。
    if(len2end >= num2push)
    {
        //写入data
        srcpos = data;
        despos = fifo->Push;
        len = num2push;
        FIFO_MEMCPY(despos, srcpos, len);
    }
    //存在回头写的情况
    else
    {
        //写入到队尾。
        srcpos = data + offset;
        despos = fifo->Push;
        len = len2end;
        FIFO_MEMCPY(despos, srcpos, len);
        //重头写入
        srcpos = srcpos + len;
        despos = fifo->Buf;
        len = num2push - len2end;
        FIFO_MEMCPY(despos, srcpos, len);
    }
    func_fifo_PushOffset(fifo,num2push);

    fifo->CntUsed += num2push;
    if(fifo->CntUsed >= fifo->Depth)
    {
        fifo->CntUsed = fifo->Depth;
        fifo->Pull = fifo->Push;
    }
}
#else
/**
***************************************************
* @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;
            FIFO_MEMCPY(despos, srcpos, len);
        }
        else
        {
            //更新原有数据
            srcpos = fifo->BackBuf + offset;
            despos = fifo->BackBuf;
            len = fifo->BackCount - offset;
            FIFO_MEMCPY(despos, srcpos, len);
            //写入新数据。
            srcpos = data;
            despos = despos + len;
            len = num;
            FIFO_MEMCPY(despos, srcpos, len);
        }
        fifo->BackCount = fifo->Depth;
    }
    //现有数据和待写入数据的总数不大于FIFO的容量,将现有数据附加到back
    else
    {
        srcpos = data;
        despos = fifo->BackBuf + fifo->BackCount;
        len = num;
        fifo->BackCount += num;
        FIFO_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;
        FIFO_MEMCPY(despos, srcpos, len);
        //写入data
        srcpos = data;
        despos = despos + len;
        len = num;
        FIFO_MEMCPY(despos, srcpos, len);
    }
    //存在回头写的情况
    else
    {
        //偏移量大于back的个数,back区域不执行写入操作。
        if(offset >= fifo->BackCount)
        {
            //写入到队尾。
            srcpos = data + offset - fifo->BackCount;
            despos = fifo->Push;
            len = len2end;
            FIFO_MEMCPY(despos, srcpos, len);
            //重头写入
            srcpos = srcpos + len;
            despos = fifo->Buf;
            len = num2push - len2end;
            FIFO_MEMCPY(despos, srcpos, len);
        }
        //写入备份区域和数据区域数据。
        else
        {
            INT16U back2push = fifo->BackCount - offset;
            if(len2end >= back2push)
            {
                //写入back
                srcpos = fifo->BackBuf + offset;
                despos = fifo->Push;
                len = back2push;
                FIFO_MEMCPY(despos, srcpos, len);
                //写入DATA到队尾
                srcpos = data;
                despos = despos + len;
                len = len2end - len;
                FIFO_MEMCPY(despos, srcpos, len);
                //重头写
                srcpos = data + len;
                despos = fifo->Buf;
                len = num2push - back2push ;
                FIFO_MEMCPY(despos, srcpos, len);
            }
            else
            {
                //写入back
                srcpos = fifo->BackBuf + offset;
                despos = fifo->Push;
                len = len2end;
                FIFO_MEMCPY(despos, srcpos, len);
                //重头写BACK
                srcpos = srcpos + len;
                despos = fifo->Buf;
                len = back2push - len;
                FIFO_MEMCPY(despos, srcpos, len);
                //写DATA
                srcpos = data;
                despos = despos + len;
                len = num2push - back2push;
                FIFO_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;
    }
}
#endif

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)
    {
        FIFO_MEMCPY(data , fifo->Pull , num2pull);
        FIFO_MEMSET(fifo->Pull , 0 , num2pull);
    }
    //需要重头读取。
    else
    {
        FIFO_MEMCPY(data , fifo->Pull, len2end);
        FIFO_MEMSET(fifo->Pull , 0 , len2end);
        FIFO_MEMCPY(data+len2end , fifo->Buf , num2pull-len2end);
        FIFO_MEMSET(fifo->Buf , 0 , num2pull-len2end);
    }
    //读位置和使用量更新。
    func_fifo_PullOffset(fifo,num2pull);
    fifo->CntUsed -= num2pull;
    return FIFO_EOK;
}
/*************************************************************************************************************************
 *                                              全局函数
**************************************************************************************************************************/
/**
***************************************************
* @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;
}
#ifdef SYS_RTT
/**
***************************************************
* @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)
{
    FifoTypeDef* p = RT_NULL;

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

    p->Buf = FIFO_MALLOC(depth);
    if(p->Buf == NULL)
    {
        FIFO_FREE(p);
        return NULL;
    }
    FIFO_MEMSET(p->Buf,0,depth);

    p->Mutex = rt_mutex_create("MUTEX", 0);
    if(p->Mutex == RT_NULL)
    {
        FIFO_FREE(p->Buf);
        FIFO_FREE(p);
        return 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;
}
#else
/**
***************************************************
* @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);
}
/**
***************************************************
* @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 = FIFO_MALLOC(sizeof(FifoTypeDef));
        if(p == NULL)
        {
            return NULL;
        }
        FifoChain = p;
    }

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

    p->Buf = FIFO_MALLOC(depth);
    if(p->Buf == NULL)
    {
        if(FifoChain ==  p)
        {
            FifoChain = 0;
        }
        FIFO_FREE(p);
        return NULL;
    }
    FIFO_MEMSET(p->Buf,0,depth);

    p->BackBuf = FIFO_MALLOC(depth);
    if(p->BackBuf == NULL)
    {
        if(FifoChain ==  p)
        {
            FifoChain = 0;
        }
        FIFO_FREE(p->Buf);
        FIFO_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;
}
#endif

/**
***************************************************
* @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;
}
#ifdef SYS_RTT
#else
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;
}
#endif

/**
***************************************************
* @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;
}
#ifdef SYS_RTT
#else
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;
}
#endif
/**
***************************************************
* @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)
    {
        FIFO_MEMCPY(data,point,len);
    }
    else
    {
        FIFO_MEMCPY(data , point , len2end);
        FIFO_MEMCPY(data+len2end , fifo->Buf , len-len2end);
    }
    FIFO_RESET_BUSY(fifo);
    return FIFO_EOK;
}

/**
***************************************************
* @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;
}
/**
***************************************************
* @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;
}

/**
***************************************************
* @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;
}
/**
***************************************************
* @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;
}

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

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

#ifdef SYS_RTT
#else
/**
***************************************************
* @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;
    }
}
#endif








  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值