[其他ST产品] 一个严谨的FIFO(RING BUFF)

[复制链接]
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:27 | 显示全部楼层 |阅读模式
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标志位进行置位复位操作

 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:28 | 显示全部楼层
2、FIFO结构体及说明

  1. typedef struct FifoTypeDef
  2. {
  3.     //构成链表。
  4.     struct FifoTypeDef*     Next;

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

  13.     //FIFO类型
  14.     FifoType                Type;

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

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

  22.     //定时器中断回调函数
  23.     void                    (*func_timmer)();
  24. }FifoTypeDef;
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:28 | 显示全部楼层
基本元素

Depth:FIFO的深度,能存储原始的个数(元素的大小为1字节)
CntUsed:FIFO使用了的个数
Push:FIFO的写入指针
Pull:FIFO的读取指针
Buf:FIFO的缓冲区
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:28 | 显示全部楼层
扩展元素

Next:用于构成FIFO链表,定时器中断中进行FIFO的遍历
EndPos:缓冲区的结尾地址,用于计算
Type:FIFO的类型,中断写入,还是主函数写入
InitFlag:初始化标志位
BusyFlag:FIFO繁忙标志位
InitFlag:FIFO在中断中进行操作标志位
BackCount:备份缓冲区使用了的数量
BackBuf:备份缓冲区
func_timer():FIFO的定时器回调函数
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:29 | 显示全部楼层
3、相关函数说明
3.1相关宏定义

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

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

  7. #define FIFO_INIT_CHECK(fifo)   (fifo->InitFlag == 1? 1:0)
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:29 | 显示全部楼层
置位,复位,查询FIFO的繁忙,中断,初始化状态。
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:29 | 显示全部楼层
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;
        }
}
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:29 | 显示全部楼层
更新push指针的位置。需要注意到FIFO的缓冲区结尾时回头的情况
  1. static inline void func_fifo_PullOffset(FifoTypeDef* fifo,INT16U offset)
  2. {
  3.         fifo->Pull += offset;
  4.         if(fifo->Pull > fifo->EndPos)
  5.         {
  6.                 fifo->Pull = fifo->Pull - fifo->Depth;
  7.         }
  8. }
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:29 | 显示全部楼层
更新pull指针的位置,同上。
static inline INT16U func_fifo_CalPoint2end(FifoTypeDef* fifo, INT8U* point)
{
        return  fifo->EndPos - point + 1;
}
计算某个指针到fifo缓冲末尾的元素个数。
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:30 | 显示全部楼层
3.2.2底层操作函数
        FIFO的底层操作函数,底层操作函数不对FIFO的标志位进行判断,时主函数和中断操作FIFO的具体实现步骤。
  1. /**
  2. ***************************************************
  3. * [url=home.php?mod=space&uid=247401]@brief[/url]   func_fifo_CmpLower
  4. * [url=home.php?mod=space&uid=536309]@NOTE[/url]    比较FIFO重数据的底层函数,不进行标志位操作。
  5. * @param   fifo
  6. *                           指向待操作的FIFO,
  7. *          ind
  8. *                           从FIFO的pull后面的第ind个开始
  9. *          len
  10. *                           比较的长度为len
  11. *          data
  12. *                           比较的数据
  13. *          timeout
  14. * @retval  FifoErr
  15. * [url=home.php?mod=space&uid=130263]@DATA[/url]    2021.09.03
  16. * [url=home.php?mod=space&uid=638116]@auth[/url]    WXL
  17. * @his     1.0.0.0     2021.09.03     WXL
  18. *               create
  19. ***************************************************
  20. **/
  21. static FifoErr func_fifo_CmpLower(FifoTypeDef* fifo, const INT16U ind, const INT16U len, const INT8U* data)
  22. {
  23.     //判断FIFO中是否有足够的数量进行比较。
  24.         if(ind + len > fifo->CntUsed)
  25.     {
  26.         return FIFO_ENUM;
  27.     }

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

  32.     INT16U len2end = func_fifo_CalPoint2end(fifo,point);
  33.     if(len2end >= len)
  34.     {
  35.         if(memcmp(data,point,len) == 0)
  36.         {
  37.             return FIFO_EOK;
  38.         }
  39.         else
  40.         {
  41.             return FIFO_EFAILED;
  42.         }
  43.     }
  44.     else
  45.     {
  46.         if(memcmp(data,point,len2end) == 0 && memcmp(data+len2end,fifo->Buf,len-len2end) == 0 )
  47.         {
  48.             return FIFO_EOK;
  49.         }
  50.         else
  51.         {
  52.             return FIFO_EFAILED;
  53.         }
  54.     }
  55. }

  56. /**
  57. ***************************************************
  58. * @brief   func_fifo_DeleteLower
  59. * @note    删除FIFO数据的底层函数,不进行标志位操作。
  60. * @param   fifo
  61. *                           指向待操作的FIFO,
  62. *          num
  63. *                           删除的元素个数
  64. * @retval  FifoErr
  65. * @data    2021.09.03
  66. * @auth    WXL
  67. * @his     1.0.0.0     2021.09.03     WXL
  68. *               create
  69. ***************************************************
  70. **/
  71. FifoErr func_fifo_DeleteLower(FifoTypeDef* fifo, INT16U num)
  72. {
  73.     //删除的数据大于FIFO已使用数据。
  74.     if(num > fifo->CntUsed)
  75.     {
  76.         return FIFO_ENUM;
  77.     }

  78.     //开始删除数据
  79.     INT16U len2end = func_fifo_CalPoint2end(fifo,fifo->Pull);
  80.     if(len2end >= num)
  81.     {
  82.         memset(fifo->Pull , 0 , num);
  83.     }
  84.     else
  85.     {
  86.         memset(fifo->Pull , 0 , len2end);
  87.         memset(fifo->Buf , 0 , num - len2end);
  88.     }
  89.     fifo->CntUsed -= num;
  90.     func_fifo_PullOffset(fifo,num);
  91.     return FIFO_EOK;
  92. }
  93. /**
  94. ***************************************************
  95. * @brief   func_fifo_Push2Back
  96. * @note    中断中进行FIFO写入操作时,FIFO繁忙调用该函数写入到back
  97. * @param   fifo
  98. *                           指向待操作的FIFO,
  99. *          num
  100. *                           删除的元素个数
  101. *          data
  102. *                           指向写入数据
  103. * @retval  FifoErr
  104. * @data    2021.09.03
  105. * @auth    WXL
  106. * @his     1.0.0.0     2021.09.03     WXL
  107. *               create
  108. ***************************************************
  109. **/
  110. static void func_fifo_Push2Back(FifoTypeDef* fifo, INT16U num, INT8U* data)
  111. {
  112.     INT16   offset = 0;

  113.     INT8U*  srcpos = 0;
  114.     INT8U*  despos = 0;
  115.     INT16U  len = 0;

  116.     //现有数据和待写入数据的总数大于BACK的容量,进行元素替换操作。
  117.     if(num + fifo->BackCount > fifo->Depth)
  118.     {
  119.             offset = num + fifo->BackCount - fifo->Depth;
  120.             //现有元素全部被替换。
  121.             if(offset >= fifo->BackCount)
  122.             {
  123.                     offset = num - fifo->Depth;
  124.                     //写入新数据
  125.                     srcpos = data+offset;
  126.                     despos = fifo->BackBuf;
  127.                     len = fifo->Depth;
  128.                     memcpy(despos, srcpos, len);
  129.             }
  130.             else
  131.             {
  132.                     //更新原有数据
  133.                     srcpos = fifo->BackBuf + offset;
  134.                     despos = fifo->BackBuf;
  135.                     len = fifo->BackCount - offset;
  136.                     memcpy(despos, srcpos, len);
  137.                     //写入新数据。
  138.                     srcpos = data;
  139.                     despos = despos + len;
  140.                     len = num;
  141.                     memcpy(despos, srcpos, len);
  142.             }
  143.             fifo->BackCount = fifo->Depth;
  144.     }
  145.     //现有数据和待写入数据的总数不大于FIFO的容量,将现有数据附加到back
  146.     else
  147.     {
  148.                 srcpos = data;
  149.                 despos = fifo->BackBuf + fifo->BackCount;
  150.                 len = num;
  151.                 fifo->BackCount += num;
  152.                 memcpy(despos, srcpos, len);
  153.         }
  154. }

  155. /**
  156. ***************************************************
  157. * @brief   func_fifo_Push2Fifo
  158. * @note    将数据写入到FIFO缓冲区中,仅在FIFO不繁忙时调用,
  159. *          1、首先将Back数据写入到FIFO中。
  160. *          2、将待写入数据写入到FIFO中。
  161. * @param   fifo
  162. *                           指向待操作的FIFO,
  163. *          num
  164. *                           删除的元素个数
  165. *          data
  166. *                           指向写入数据
  167. * @retval  FifoErr
  168. * @data    2021.09.03
  169. * @auth    WXL
  170. * @his     1.0.0.0     2021.09.03     WXL
  171. *               create
  172. ***************************************************
  173. **/
  174. static void func_fifo_Push2Fifo(FifoTypeDef* fifo, INT16U num, INT8U* data)
  175. {
  176.         INT16   offset = 0;
  177.         INT16   len2end = func_fifo_CalPoint2end(fifo,fifo->Push);
  178.         INT16   num2push = 0;

  179.         INT8U*  srcpos = 0;
  180.         INT8U*  despos = 0;
  181.         INT16U  len = 0;

  182.         //back数据和data数据之和大于depth,存在back和data丢弃数据的情况。
  183.         if(fifo->BackCount + num > fifo->Depth)
  184.         {
  185.                 num2push = fifo->Depth;
  186.                 offset = fifo->BackCount + num -fifo->Depth;
  187.         }
  188.         else
  189.         {
  190.                 num2push = fifo->BackCount + num;
  191.         }

  192.         //到FIFO结尾可以容纳写入的数据,说明不存在覆盖情况。将back和带写入数据写入即可。
  193.         if(len2end >= num2push)
  194.         {
  195.                 //写入BACK
  196.                 srcpos = fifo->BackBuf;
  197.                 despos = fifo->Push;
  198.                 len = fifo->BackCount;
  199.                 memcpy(despos, srcpos, len);
  200.                 //写入data
  201.                 srcpos = data;
  202.                 despos = despos + len;
  203.                 len = num;
  204.                 memcpy(despos, srcpos, len);
  205.         }
  206.         //存在回头写的情况
  207.         else
  208.         {
  209.                 //偏移量大于back的个数,back区域不执行写入操作。
  210.                 if(offset >= fifo->BackCount)
  211.                 {
  212.                         //写入到队尾。
  213.                         srcpos = data + offset - fifo->BackCount;
  214.                         despos = fifo->Push;
  215.                         len = len2end;
  216.                         memcpy(despos, srcpos, len);
  217.                         //重头写入
  218.                         srcpos = srcpos + len;
  219.                         despos = fifo->Buf;
  220.                         len = num2push - len2end;
  221.                         memcpy(despos, srcpos, len);
  222.                 }
  223.                 //写入备份区域和数据区域数据。
  224.                 else
  225.                 {
  226.                         INT16U back2push = fifo->BackCount - offset;
  227.                         if(len2end >= back2push)
  228.                         {
  229.                                 //写入back
  230.                                 srcpos = fifo->BackBuf + offset;
  231.                                 despos = fifo->Push;
  232.                                 len = back2push;
  233.                                 memcpy(despos, srcpos, len);
  234.                                 //写入DATA到队尾
  235.                                 srcpos = data;
  236.                                 despos = despos + len;
  237.                                 len = len2end - len;
  238.                                 memcpy(despos, srcpos, len);
  239.                                 //重头写
  240.                                 srcpos = data + len;
  241.                                 despos = fifo->Buf;
  242.                                 len = num2push - back2push ;
  243.                                 memcpy(despos, srcpos, len);
  244.                         }
  245.                         else
  246.                         {
  247.                                 //写入back
  248.                                 srcpos = fifo->BackBuf + offset;
  249.                                 despos = fifo->Push;
  250.                                 len = len2end;
  251.                                 memcpy(despos, srcpos, len);
  252.                                 //重头写BACK
  253.                                 srcpos = srcpos + len;
  254.                                 despos = fifo->Buf;
  255.                                 len = back2push - len;
  256.                                 memcpy(despos, srcpos, len);
  257.                                 //写DATA
  258.                                 srcpos = data;
  259.                                 despos = despos + len;
  260.                                 len = num2push - back2push;
  261.                                 memcpy(despos, srcpos, len);
  262.                         }
  263.                 }
  264.         }
  265.         fifo->BackCount = 0;
  266.         if(num2push + fifo->CntUsed > fifo->Depth)
  267.         {
  268.                 num2push -= 1;
  269.                 num2push += 1;
  270.         }
  271.         func_fifo_PushOffset(fifo,num2push);

  272.         fifo->CntUsed += num2push;
  273.         if(fifo->CntUsed >= fifo->Depth)
  274.         {
  275.                 fifo->CntUsed = fifo->Depth;
  276.                 fifo->Pull = fifo->Push;
  277.         }
  278. }

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

  283.     if(fifo->CntUsed == 0)
  284.     {
  285.             return FIFO_ENUM;
  286.     }

  287.     //全部模式
  288.     if(mode == 0)
  289.     {
  290.             if(fifo->CntUsed >= num)
  291.             {
  292.                     num2pull = num;
  293.             }
  294.             else
  295.             {
  296.                     return FIFO_ENUM;
  297.             }
  298.     }
  299.     //PART模式
  300.     else
  301.     {
  302.             if(fifo->CntUsed >= num)
  303.             {
  304.                     num2pull = num;
  305.             }
  306.             else
  307.             {
  308.                     num2pull = fifo->CntUsed;
  309.             }
  310.             *len = num2pull;
  311.     }

  312.         if(len2end >= num2pull)
  313.         {
  314.                 memcpy(data , fifo->Pull , num2pull);
  315.                 memset(fifo->Pull , 0 , num2pull);
  316.         }
  317.         //需要重头读取。
  318.         else
  319.         {
  320.                 memcpy(data , fifo->Pull, len2end);
  321.                 memset(fifo->Pull , 0 , len2end);
  322.                 memcpy(data+len2end , fifo->Buf , num2pull-len2end);
  323.                 memset(fifo->Buf , 0 , num2pull-len2end);
  324.         }
  325.         //读位置和使用量更新。
  326.         func_fifo_PullOffset(fifo,num2pull);
  327.         fifo->CntUsed -= num2pull;
  328.         return FIFO_EOK;
  329. }
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:30 | 显示全部楼层
3.2.3FIFO函数实现
        获取FIFO驱动的版本和FIFO定时器的初始化。
  1. /**
  2. ***************************************************
  3. * @brief   func_fifo_GetVer
  4. * @note    获取FIFO文件的版本号。
  5. * @param   NONE
  6. * @retval  NONE
  7. * @data    2021.09.03
  8. * @auth    WXL
  9. * @his     1.0.0.0     2021.09.03     WXL
  10. *               create
  11. ***************************************************
  12. **/
  13. INT16U func_fifo_GetVer()
  14. {
  15.         return VER_FIFO;
  16. }

  17. /**
  18. ***************************************************
  19. * @brief   func_fifo_Init
  20. * @note    启动FIFO使用的定时器。
  21. * @param   NONE
  22. * @retval  NONE
  23. * @data    2021.09.03
  24. * @auth    WXL
  25. * @his     1.0.0.0     2021.09.03     WXL
  26. *               create
  27. ***************************************************
  28. **/
  29. void func_fifo_Init()
  30. {
  31.         extern TIM_HandleTypeDef htim4;

  32.         HAL_TIM_Base_Start_IT(&htim4);
  33. }
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:30 | 显示全部楼层
  创建FIFO,初始化FIFO的相关遍历,初始化FIFO的链表
  1. /**
  2. ***************************************************
  3. * @brief   func_fifo_Create
  4. * @note    创建FIFO
  5. * @param   depth
  6. *               FIFO的深度。
  7. *          type
  8. *               FIFO类型,是中断写入还是中断读取。
  9. * @retval  0:
  10. *                           失败
  11. *                    其他:
  12. *                           成功,FIFO指针
  13. * @data    2021.09.03
  14. * @auth    WXL
  15. * @his     1.0.0.0     2021.09.03     WXL
  16. *               create
  17. ***************************************************
  18. **/
  19. FifoTypeDef* func_fifo_Create(INT16U depth, FifoType type)
  20. {
  21.     FifoTypeDef* p = FifoChain;

  22.     if(p == NULL)
  23.     {
  24.         p = malloc(sizeof(FifoTypeDef));
  25.         if(p == NULL)
  26.         {
  27.             return NULL;
  28.         }
  29.         FifoChain = p;
  30.     }

  31.     else
  32.     {
  33.             while(p->Next != NULL)
  34.             {
  35.                     p = p->Next;
  36.             }
  37.             p->Next = malloc(sizeof(FifoTypeDef));
  38.             p = p->Next;
  39.             if(p == NULL)
  40.                 {
  41.                         return NULL;
  42.                 }
  43.     }

  44.     p->Buf = malloc(depth);
  45.     if(p->Buf == NULL)
  46.     {
  47.             if(FifoChain ==  p)
  48.             {
  49.                     FifoChain = 0;
  50.             }
  51.         free(p);
  52.         return NULL;
  53.     }
  54.     memset(p->Buf,0,depth);

  55.         p->BackBuf = malloc(depth);
  56.         if(p->BackBuf == NULL)
  57.         {
  58.             if(FifoChain ==  p)
  59.             {
  60.                     FifoChain = 0;
  61.             }
  62.             free(p->Buf);
  63.             free(p);
  64.                 return NULL;
  65.         }
  66.         p->BusyFlag = 0;
  67.         p->IntFlag = 0;
  68.         p->BackCount = 0;

  69.     p->Type         = type;
  70.     p->Next         = NULL;
  71.     p->InitFlag     = 1;
  72.     p->Depth        = depth;
  73.     p->CntUsed      = 0;
  74.     p->Push         = p->Buf;
  75.     p->Pull         = p->Buf;
  76.     p->EndPos       = p->Buf + p->Depth - 1;

  77.     return p;
  78. }
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:30 | 显示全部楼层
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;
}
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:31 | 显示全部楼层
FIFO数据的读取。分为三个函数

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

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

func_fifo_PullPartInt:中断中使用,进行部分读取。
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:31 | 显示全部楼层
/**
***************************************************
* @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;
}
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:31 | 显示全部楼层
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;
}
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:31 | 显示全部楼层
删除FIFO中的元素
  1. /**
  2. ***************************************************
  3. * @brief   func_fifo_Delete
  4. * @note    从FIFO中删除数据
  5. * @param   fifo
  6. *                           指向待操作的FIFO,
  7. *          num
  8. *                           删除数据的个数
  9. *          timeout
  10. *                           等待busy 超时时间,单位ms
  11. * @retval  FifoErr
  12. * @data    2021.09.03
  13. * @auth    WXL
  14. * @his     1.0.0.0     2021.09.03     WXL
  15. *               create
  16. ***************************************************
  17. **/
  18. FifoErr func_fifo_Delete(FifoTypeDef* fifo , INT16U num)
  19. {
  20.     FifoErr err = FIFO_EOK;

  21.     if(FIFO_INIT_CHECK(fifo) == 0)
  22.     {
  23.             return FIFO_EINIT;
  24.     }

  25.         FIFO_SET_BUSY(fifo);
  26.     err =  func_fifo_DeleteLower(fifo, num);
  27.     FIFO_RESET_BUSY(fifo);

  28.     return err;
  29. }
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:32 | 显示全部楼层
比较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;
}
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:32 | 显示全部楼层
查找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;
}
 楼主| 梵蒂冈是神uy 发表于 2023-11-28 16:32 | 显示全部楼层
从FIFO的指定位置开始查找,不进行元素的删除和相关指针的操作
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

734

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部