fifo在嵌入式里面用的相当多,一般用到的通讯如iic, spi, uart,都会有一个fifo。fifo实现起来也比较简单,一般就是用一个数组,设置两个指针,读指针和写指针。相比之前的filo实现不同,这里我把错误标志直接设置在了fifo对象里面,这样也方便在应用中使用多个fifo而不会相互干扰。
main.c
#include <stdio.h>
#include "cfifo.h"
int main(void)
{
struct fifo_t *myfifo = fifo_create(100);
if(myfifo == NULL)
return 0;
int i;
for(i = 0; i < 102; i++){
myfifo->push(myfifo, i);
if(myfifo->is_err(myfifo)){
break;
}
}
myfifo->print(myfifo);
for(i = 0; i < 102; i++){
printf("<%d>: %d\n", i, myfifo->pop(myfifo));
if(myfifo->is_err(myfifo)){
break;
}
}
return 0;
}
cfifo.h
#ifndef CFIFO_H_
#define CFIFO_H_
#define MAX_FIFO_DEPTH 1024u
// fifo object
struct fifo_t {
unsigned int depth; // fifo depth
unsigned int free_size; // fifo free size
int fifo_err; // fifo operation err flag
int *fifo_head; // fifo array head
int *fifo_tail; // fifo array tail
int *phead; // fifo head
int *ptail; // fifo tail
void(*push)(struct fifo_t *p, int num); // push a num to fifo
int(*pop)(struct fifo_t *p); // pop a num from fifo
void(*print)(struct fifo_t *p); // print all num in fifo
unsigned int(*get_free_size)(struct fifo_t *p); // get free size of fifo
int(*is_err)(struct fifo_t *p); // judge fifo err happened or not
};
void fifo_push(struct fifo_t *p, int num);
int fifo_pop(struct fifo_t *p);
unsigned int fifo_get_free_size(struct fifo_t *p);
void fifo_print(struct fifo_t *p);
int fifo_is_err(struct fifo_t *p);
struct fifo_t *fifo_create(unsigned int fifo_depth);
#endif /* CFIFO_H_ */
cfifo.c
#include <stdio.h>
#include <stdlib.h>
#include "cfifo.h"
// push a num to fifo tail
void fifo_push(struct fifo_t *p, int num)
{
if(p->free_size == 0){ // fifo is full
p->fifo_err = -1;
printf("the fifo is full\n");
return ;
}
if(p->ptail == NULL ){ // first num push to fifo
p->ptail = p->fifo_head;
p->phead = p->fifo_head;
}
else if(p->ptail == p->fifo_tail){ // have moved to tail of array
p->ptail = p->fifo_head;
}
else{
p->ptail++;
}
*(p->ptail) = num;
p->free_size--;
p->fifo_err = 0;
}
// pop the fifo head num
int fifo_pop(struct fifo_t *p)
{
if(p->free_size == p->depth){ // fifo is empty
p->fifo_err = -1;
printf("the fifo is empty\n");
return 0;
}
int ret;
ret = *(p->phead);
if(p->phead == p->fifo_tail){ // head moved to tail of array
p->phead = p->fifo_head;
}
else{
p->phead++;
}
p->free_size++;
p->fifo_err = 0;
return ret;
}
unsigned int fifo_get_free_size(struct fifo_t *p)
{
return p->free_size;
}
void fifo_print(struct fifo_t *p)
{
if(p->free_size == p->depth){ // fifo is empty
printf("NULL\n");
p->fifo_err = -1;
return ;
}
int i;
int *ptmp = p->phead;
for(i = 0; i < (p->depth - p->free_size); i++ ){
printf("<%d>: %d\n",i, *ptmp);
if(ptmp == p->fifo_tail){
ptmp = p->fifo_head;
}
else{
ptmp++;
}
}
p->fifo_err = 0;
}
int fifo_isfifoerr(struct fifo_t *p)
{
if(p->fifo_err < 0){
return 1;
}
else{
return 0;
}
}
struct fifo_t *fifo_create(unsigned int fifo_depth)
{
if(fifo_depth <= 0 || fifo_depth > MAX_FIFO_DEPTH){
printf("fifo depth err\n");
return NULL;
}
struct fifo_t *p = (struct fifo_t *)malloc(sizeof(struct fifo_t));
// init fifo element
p->depth = fifo_depth;
p->free_size = fifo_depth;
p->fifo_err = 0;
p->fifo_head = (int *)malloc(sizeof(int) * fifo_depth); // array head
p->fifo_tail = p->fifo_head + fifo_depth - 1; // array tail
p->phead = NULL;
p->ptail = NULL;
p->get_free_size = fifo_get_free_size;
p->pop = fifo_pop;
p->print = fifo_print;
p->push = fifo_push;
p->is_err = fifo_isfifoerr;
return p;
}