打印
[其他ST产品]

stm32实用循环buffer

[复制链接]
277|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
笔者在实际开发中多次用到串口的循环buffer,最开始在网上搜索了相关**和资料,感觉通用性不是很高。自己也写过fifo,感觉还是过于臃肿。一直想找个完美的循环buffer。在看linux内核代码时,发现内核里面也经常使用fifo。linux内核代码是最优美、精简的,高效的代码。真是“山穷水尽疑无路,柳暗花明又一村”。特意移植除出来,希望对大家有用。代码设计的相当的巧妙~~~

头文件:
/*******************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url]           : fifo.h
* [url=home.php?mod=space&uid=187600]@author[/url]   : cqx
* [url=home.php?mod=space&uid=895143]@version[/url]  : V0.0.1
* [url=home.php?mod=space&uid=212281]@date[/url]           : 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 <stm32f10x.h>

#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


使用特权

评论回复
沙发
怎么总是重复啊|  楼主 | 2021-12-31 23:37 | 只看该作者
源文件:
/******************************************************************************
* @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;
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

186

帖子

0

粉丝