stm32实用循环buffer
2019-08-26 来源:eefocus
本人在实际开发中多次用到串口的循环buffer,最开始在网上搜索了相关文章和资料,感觉通用性不是很高。自己也写过fifo,感觉还是过于臃肿。一直想找个完美的循环buffer。在看linux内核代码时,发现内核里面也经常使用fifo。linux内核代码是最优美、精简的,高效的代码。真是“山穷水尽疑无路,柳暗花明又一村”。特意移植除出来,希望对大家有用。代码设计的相当的巧妙~~~
头文件:
/*******************************************************************************
* @File : fifo.h
* @Author : cqx
* @Version : V0.0.1
* @Date : 29-november-2016
* @Brief : This file provides all the fifo functions.
********************************************************************************
* @Attention:
* Non
*
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _FIFO_H
#define _FIFO_H
#include #ifdef __cplusplus extern 'C' { #endif /* Includes ------------------------------------------------------------------*/ /* Define --------------------------------------------------------------------*/ #ifndef min #define min(a, b) (((a) < (b)) ? (a) : (b)) #endif #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) /* Private typedef -----------------------------------------------------------*/ struct fifo { unsigned int in; unsigned int out; unsigned int mask; unsigned char *data; }; /* Function prototypes -------------------------------------------------------*/ extern unsigned int fifo_used(struct fifo *fifo); extern signed int fifo_alloc(struct fifo *fifo, unsigned int size); extern void fifo_free(struct fifo *fifo); extern int fifo_init(struct fifo *fifo, unsigned char *buffer, unsigned int size); extern unsigned int fifo_in(struct fifo *fifo, unsigned char *buf, unsigned int len); extern unsigned int fifo_out(struct fifo *fifo, unsigned char *buf, unsigned int len); #ifdef __cplusplus } #endif #endif 源文件: /****************************************************************************** * @File : ringbuffer.c * @Author : cqx * @Version : V0.0.1 * @Date : 29-november-2016 * @Brief : This file provides all the fifo functions. ****************************************************************************** * @Attention: * * ******************************************************************************/ /* Includes -----------------------------------------------------------------*/ #include 'fifo.h' #include 'stdlib.h' #include 'string.h' #include 'includes.h' /* Variables -----------------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /******************************************************************************/ /* * internal helper to calculate the unused elements in a fifo */ static __inline unsigned int fifo_unused(struct fifo *fifo) { return (fifo->mask + 1) - (fifo->in - fifo->out); } unsigned int fifo_used(struct fifo *fifo) { return (fifo->in - fifo->out); } signed int fifo_alloc(struct fifo *fifo, unsigned int size) { /* * round down to the next power of 2, since our 'let the indices * wrap' technique works only in this case. */ if (!is_power_of_2(size)) return -1; fifo->in = 1; fifo->out = 1; if (size < 2){ fifo->data = NULL; fifo->mask = 0; return -1; } fifo->data = malloc(size); if (!fifo->data){ fifo->mask = 0; return -1; } fifo->mask = size - 1; return 0; } void fifo_free(struct fifo *fifo) { free(fifo->data); fifo->in = 0; fifo->out = 0; fifo->data = NULL; fifo->mask = 0; } int fifo_init(struct fifo *fifo, unsigned char *buffer, unsigned int size) { if (!is_power_of_2(size)) return -1; fifo->in = 0; fifo->out = 0; fifo->data = buffer; if (size < 2) { fifo->mask = 0; return -1; } fifo->mask = size - 1; return 0; } static void fifo_copy_in(struct fifo *fifo, unsigned char *src, unsigned int len, unsigned int off) { unsigned int size = fifo->mask + 1; unsigned int l; off &= fifo->mask; l = min(len, size - off); memcpy(fifo->data + off, src, l); memcpy(fifo->data, src + l, len - l); } unsigned int fifo_in(struct fifo *fifo, unsigned char *buf, unsigned int len) { unsigned int l; l = fifo_unused(fifo); if (len > l) len = l; fifo_copy_in(fifo, buf, len, fifo->in); fifo->in += len; return len; } static void fifo_copy_out(struct fifo *fifo, unsigned char *dst, unsigned int len, unsigned int off) { unsigned int size = fifo->mask + 1; unsigned int l; off &= fifo->mask; l = min(len, size - off); memcpy(dst, fifo->data + off, l); memcpy(dst + l, fifo->data, len - l); } unsigned int fifo_out_peek(struct fifo *fifo, unsigned char *buf, unsigned int len) { unsigned int l; l = fifo->in - fifo->out; if (len > l) len = l; fifo_copy_out(fifo, buf, len, fifo->out); return len; } unsigned int fifo_out(struct fifo *fifo, unsigned char *buf, unsigned int len) { len = fifo_out_peek(fifo, buf, len); fifo->out += len; return len; }