stm 32実用サイクルbuffer
5286 ワード
筆者は実際の開発でシリアルポートのループ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;
}