[其他ST产品] stm32实用循环buffer

[复制链接]
 楼主| 怎么总是重复啊 发表于 2021-12-31 23:34 | 显示全部楼层 |阅读模式
笔者在实际开发中多次用到串口的循环buffer,最开始在网上搜索了相关**和资料,感觉通用性不是很高。自己也写过fifo,感觉还是过于臃肿。一直想找个完美的循环buffer。在看linux内核代码时,发现内核里面也经常使用fifo。linux内核代码是最优美、精简的,高效的代码。真是“山穷水尽疑无路,柳暗花明又一村”。特意移植除出来,希望对大家有用。代码设计的相当的巧妙~~~

头文件:
  1. /*******************************************************************************
  2. * [url=home.php?mod=space&uid=288409]@file[/url]           : fifo.h
  3. * [url=home.php?mod=space&uid=187600]@author[/url]   : cqx
  4. * [url=home.php?mod=space&uid=895143]@version[/url]  : V0.0.1
  5. * [url=home.php?mod=space&uid=212281]@date[/url]           : 29-november-2016
  6. * @Brief          : This file provides all the fifo functions.
  7. ********************************************************************************
  8. * @Attention:
  9. * Non
  10. *
  11. *******************************************************************************/

  12. /* Define to prevent recursive inclusion -------------------------------------*/
  13. #ifndef _FIFO_H
  14. #define _FIFO_H

  15. #include <stm32f10x.h>

  16. #ifdef __cplusplus
  17. extern "C" {
  18. #endif
  19.          
  20. /* Includes ------------------------------------------------------------------*/
  21. /* Define --------------------------------------------------------------------*/
  22. #ifndef min
  23. #define min(a, b) (((a) < (b)) ? (a) : (b))
  24. #endif               

  25. #define is_power_of_2(x)        ((x) != 0 && (((x) & ((x) - 1)) == 0))
  26.                
  27. /* Private typedef -----------------------------------------------------------*/
  28. struct fifo {
  29.         unsigned int        in;
  30.         unsigned int        out;
  31.         unsigned int        mask;
  32.         unsigned char *data;
  33. };

  34. /* Function prototypes -------------------------------------------------------*/
  35. extern unsigned int fifo_used(struct fifo *fifo);
  36. extern signed int fifo_alloc(struct fifo *fifo, unsigned int size);
  37. extern void         fifo_free(struct fifo *fifo);
  38. extern int          fifo_init(struct fifo *fifo, unsigned char *buffer,        unsigned int size);
  39. extern unsigned int fifo_in(struct fifo *fifo, unsigned char *buf, unsigned int len);
  40. extern unsigned int fifo_out(struct fifo *fifo,        unsigned char *buf, unsigned int len);
  41.          
  42. #ifdef __cplusplus
  43. }
  44. #endif

  45. #endif


 楼主| 怎么总是重复啊 发表于 2021-12-31 23:37 | 显示全部楼层
源文件:
  1. /******************************************************************************
  2. * @File           : ringbuffer.c
  3. * @Author   : cqx
  4. * @Version  : V0.0.1
  5. * @Date           : 29-november-2016
  6. * @Brief          : This file provides all the fifo functions.
  7. ******************************************************************************
  8. * @Attention:
  9. *
  10. *
  11. ******************************************************************************/
  12. /* Includes -----------------------------------------------------------------*/
  13. #include "fifo.h"
  14. #include "stdlib.h"
  15. #include "string.h"
  16. #include "includes.h"

  17. /* Variables -----------------------------------------------------------------*/
  18. /* Private functions ---------------------------------------------------------*/
  19. /******************************************************************************/

  20. /*
  21. * internal helper to calculate the unused elements in a fifo
  22. */
  23. static __inline unsigned int fifo_unused(struct fifo *fifo)
  24. {
  25.   return (fifo->mask + 1) - (fifo->in - fifo->out);
  26. }

  27. unsigned int fifo_used(struct fifo *fifo)
  28. {
  29.   return (fifo->in - fifo->out);
  30. }

  31. signed int fifo_alloc(struct fifo *fifo, unsigned int size)
  32. {       
  33. /*
  34.          * round down to the next power of 2, since our 'let the indices
  35.          * wrap' technique works only in this case.
  36.          */
  37.         if (!is_power_of_2(size))
  38.                 return -1;

  39.         fifo->in = 1;
  40.         fifo->out = 1;
  41.        
  42.         if (size < 2){
  43.                 fifo->data = NULL;
  44.                 fifo->mask = 0;
  45.                 return -1;
  46.         }
  47.         fifo->data = malloc(size);
  48.        
  49.         if (!fifo->data){
  50.                 fifo->mask = 0;
  51.                 return -1;
  52.         }       
  53.         fifo->mask = size - 1;
  54.   
  55.   return 0;
  56. }

  57. void fifo_free(struct fifo *fifo)
  58. {
  59.         free(fifo->data);
  60.         fifo->in = 0;
  61.         fifo->out = 0;
  62.         fifo->data = NULL;
  63.         fifo->mask = 0;
  64. }

  65. int fifo_init(struct fifo *fifo, unsigned char *buffer, unsigned int size)
  66. {
  67.         if (!is_power_of_2(size))
  68.                 return -1;

  69.         fifo->in = 0;
  70.         fifo->out = 0;
  71.         fifo->data = buffer;

  72.         if (size < 2) {
  73.                 fifo->mask = 0;
  74.                 return -1;
  75.         }
  76.         fifo->mask = size - 1;

  77.         return 0;
  78. }

  79. static void fifo_copy_in(struct fifo *fifo, unsigned char *src, unsigned int len, unsigned int off)
  80. {
  81.         unsigned int size = fifo->mask + 1;
  82.         unsigned int l;

  83.         off &= fifo->mask;

  84.         l = min(len, size - off);

  85.         memcpy(fifo->data + off, src, l);
  86.         memcpy(fifo->data, src + l, len - l);
  87. }

  88. unsigned int fifo_in(struct fifo *fifo, unsigned char *buf, unsigned int len)
  89. {
  90.         unsigned int l;

  91.         l = fifo_unused(fifo);
  92.         if (len > l)
  93.                 len = l;

  94.         fifo_copy_in(fifo, buf, len, fifo->in);
  95.         fifo->in += len;
  96.        
  97.         return len;
  98. }

  99. static void fifo_copy_out(struct fifo *fifo, unsigned char *dst, unsigned int len, unsigned int off)
  100. {
  101.         unsigned int size = fifo->mask + 1;
  102.         unsigned int l;

  103.         off &= fifo->mask;
  104.         l = min(len, size - off);

  105.         memcpy(dst, fifo->data + off, l);
  106.         memcpy(dst + l, fifo->data, len - l);
  107. }

  108. unsigned int fifo_out_peek(struct fifo *fifo, unsigned char *buf, unsigned int len)
  109. {
  110.         unsigned int l;

  111.         l = fifo->in - fifo->out;
  112.         if (len > l)
  113.                 len = l;

  114.         fifo_copy_out(fifo, buf, len, fifo->out);
  115.         return len;
  116. }

  117. unsigned int fifo_out(struct fifo *fifo, unsigned char *buf, unsigned int len)
  118. {
  119.         len = fifo_out_peek(fifo, buf, len);
  120.         fifo->out += len;
  121.         return len;
  122. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

262

帖子

1

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