- 创建了项目的基本目录结构和文件 - 添加了 CMakeLists.txt 和 Makefile 构建配置 - 创建了 main.c 文件,实现了简单的 LED 闪烁和按键检测功能 - 集成了 SEGGER RTT 库 - 添加了 .gitignore 文件,排除了不必要的生成文件
237 lines
6.7 KiB
C
237 lines
6.7 KiB
C
/*
|
|
* A generic kernel FIFO implementation
|
|
*
|
|
* Copyright (C) 2009/2010 Stefani Seibold <stefani@seibold.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
#ifndef __GE_KFIFO_H__
|
|
#define __GE_KFIFO_H__
|
|
/**
|
|
* 仿照linux内核中的kfifo实现
|
|
*/
|
|
|
|
#ifndef GE_MEMORY_BARRIR
|
|
#define GE_MEMORY_BARRIR() __sync_synchronize()
|
|
#endif
|
|
|
|
#ifndef GE_ARRAY_SIZE
|
|
#define GE_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
|
#endif
|
|
|
|
struct __ge_kfifo {
|
|
unsigned int in;
|
|
unsigned int out;
|
|
unsigned int mask;
|
|
unsigned int esize;
|
|
void *data;
|
|
};
|
|
|
|
#define __STRUCT_GE_KFIFO(type, size) \
|
|
{ \
|
|
struct __ge_kfifo kfifo; \
|
|
type buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
|
|
}
|
|
|
|
/**
|
|
* DECLARE_KFIFO - macro to declare a fifo object
|
|
* @fifo: name of the declared fifo
|
|
* @type: type of the fifo elements
|
|
* @size: the number of elements in the fifo, this must be a power of 2
|
|
*/
|
|
#define DECLARE_GE_KFIFO(fifo, type, size, tname) struct tname __STRUCT_GE_KFIFO(type, size) fifo
|
|
|
|
#define INIT_GE_KFIFO(fifo) do { \
|
|
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
|
__kfifo->in = 0; \
|
|
__kfifo->out = 0; \
|
|
__kfifo->mask = GE_ARRAY_SIZE((fifo)->buf) - 1; \
|
|
__kfifo->esize = sizeof(*((fifo)->buf)); \
|
|
__kfifo->data = (fifo)->buf; \
|
|
} while (0)
|
|
|
|
/**
|
|
* DEFINE_KFIFO - macro to define and initialize a fifo
|
|
* @fifo: name of the declared fifo datatype
|
|
* @type: type of the fifo elements
|
|
* @size: the number of elements in the fifo, this must be a power of 2
|
|
*
|
|
* Note: the macro can be used for global and local fifo data type variables.
|
|
*/
|
|
#define DEFINE_GE_KFIFO(fifo, type, size, tname) \
|
|
DECLARE_GE_KFIFO(fifo, type, size, tname) = \
|
|
(struct tname) { { \
|
|
.in = 0, \
|
|
.out = 0, \
|
|
.mask = GE_ARRAY_SIZE((fifo).buf) - 1, \
|
|
.esize = sizeof(*(fifo).buf), \
|
|
.data = (fifo).buf, \
|
|
}, { 0 } }
|
|
|
|
/**
|
|
* kfifo_size - returns the size of the fifo in elements
|
|
* @fifo: address of the fifo to be used
|
|
*/
|
|
#define ge_kfifo_size(fifo) \
|
|
((fifo)->kfifo.mask + 1)
|
|
|
|
/**
|
|
* kfifo_len - returns the number of used elements in the fifo
|
|
* @fifo: address of the fifo to be used
|
|
*/
|
|
#define ge_kfifo_len(fifo) \
|
|
((fifo)->kfifo.in - (fifo)->kfifo.out)
|
|
|
|
/**
|
|
* kfifo_is_empty - returns true if the fifo is empty
|
|
* @fifo: address of the fifo to be used
|
|
*/
|
|
#define ge_kfifo_is_empty(fifo) \
|
|
((fifo)->kfifo.in == (fifo)->kfifo.out)
|
|
|
|
/**
|
|
* kfifo_is_full - returns true if the fifo is full
|
|
* @fifo: address of the fifo to be used
|
|
*/
|
|
#define ge_kfifo_is_full(fifo) (ge_kfifo_len(fifo) > (fifo)->kfifo.mask)
|
|
|
|
/**
|
|
* kfifo_put - put data into the fifo
|
|
* @fifo: address of the fifo to be used
|
|
* @val: the data to be added
|
|
*
|
|
* This macro copies the given value into the fifo.
|
|
* It returns 0 if the fifo was full. Otherwise it returns the number
|
|
* processed elements.
|
|
*
|
|
* Note that with only one concurrent reader and one concurrent
|
|
* writer, you don't need extra locking to use these macro.
|
|
*/
|
|
#define ge_kfifo_put(fifo, val) do { \
|
|
unsigned int __ret; \
|
|
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
|
__ret = !ge_kfifo_is_full(fifo); \
|
|
if (__ret) { \
|
|
((fifo)->buf)[__kfifo->in & __kfifo->mask] = val; \
|
|
/*smp_wmb();*/ \
|
|
GE_MEMORY_BARRIR(); \
|
|
__kfifo->in++; \
|
|
} \
|
|
/*__ret;*/ \
|
|
} while(0)
|
|
|
|
/**
|
|
* kfifo_get - get data from the fifo
|
|
* @fifo: address of the fifo to be used
|
|
* @val: address where to store the data
|
|
*
|
|
* This macro reads the data from the fifo.
|
|
* It returns 0 if the fifo was empty. Otherwise it returns the number
|
|
* processed elements.
|
|
*
|
|
* Note that with only one concurrent reader and one concurrent
|
|
* writer, you don't need extra locking to use these macro.
|
|
*/
|
|
#define ge_kfifo_get(fifo, val) do { \
|
|
unsigned int __ret; \
|
|
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
|
__ret = !ge_kfifo_is_empty(fifo); \
|
|
if (__ret) { \
|
|
*val = ((fifo)->buf)[__kfifo->out & __kfifo->mask]; \
|
|
/*smp_wmb();*/ \
|
|
GE_MEMORY_BARRIR(); \
|
|
__kfifo->out++; \
|
|
} \
|
|
/*__ret;*/ \
|
|
} while(0)
|
|
|
|
/**
|
|
* kfifo_peek - get data from the fifo without removing
|
|
* @fifo: address of the fifo to be used
|
|
* @val: address where to store the data
|
|
*
|
|
* This reads the data from the fifo without removing it from the fifo.
|
|
* It returns 0 if the fifo was empty. Otherwise it returns the number
|
|
* processed elements.
|
|
*
|
|
* Note that with only one concurrent reader and one concurrent
|
|
* writer, you don't need extra locking to use these macro.
|
|
*/
|
|
#define ge_kfifo_peek(fifo, val) do { \
|
|
unsigned int __ret; \
|
|
struct __ge_kfifo *__kfifo = &((fifo)->kfifo); \
|
|
__ret = !ge_kfifo_is_empty(fifo); \
|
|
if (__ret) { \
|
|
*val = ((fifo)->buf)[__kfifo->out & __kfifo->mask]; \
|
|
/*smp_wmb();*/ \
|
|
GE_MEMORY_BARRIR(); \
|
|
} \
|
|
/*__ret;*/ \
|
|
} while(0)
|
|
|
|
/**
|
|
* kfifo_in - put data into the fifo
|
|
* @fifo: address of the fifo to be used
|
|
* @buf: the data to be added
|
|
* @n: number of elements to be added
|
|
*
|
|
* This macro copies the given buffer into the fifo and returns the
|
|
* number of copied elements.
|
|
*
|
|
* Note that with only one concurrent reader and one concurrent
|
|
* writer, you don't need extra locking to use these macro.
|
|
*/
|
|
/*
|
|
#define kfifo_in(fifo, buf, n) \
|
|
({ \
|
|
typeof((fifo) + 1) __tmp = (fifo); \
|
|
typeof(__tmp->ptr_const) __buf = (buf); \
|
|
unsigned long __n = (n); \
|
|
const size_t __recsize = sizeof(*__tmp->rectype); \
|
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
|
(__recsize) ?\
|
|
__kfifo_in_r(__kfifo, __buf, __n, __recsize) : \
|
|
__kfifo_in(__kfifo, __buf, __n); \
|
|
})
|
|
*/
|
|
/**
|
|
* kfifo_out - get data from the fifo
|
|
* @fifo: address of the fifo to be used
|
|
* @buf: pointer to the storage buffer
|
|
* @n: max. number of elements to get
|
|
*
|
|
* This macro gets some data from the fifo and returns the numbers of elements
|
|
* copied.
|
|
*
|
|
* Note that with only one concurrent reader and one concurrent
|
|
* writer, you don't need extra locking to use these macro.
|
|
*/
|
|
/*
|
|
#define kfifo_out(fifo, buf, n) \
|
|
({ \
|
|
typeof((fifo) + 1) __tmp = (fifo); \
|
|
typeof(__tmp->ptr) __buf = (buf); \
|
|
unsigned long __n = (n); \
|
|
const size_t __recsize = sizeof(*__tmp->rectype); \
|
|
struct __kfifo *__kfifo = &__tmp->kfifo; \
|
|
(__recsize) ?\
|
|
__kfifo_out_r(__kfifo, __buf, __n, __recsize) : \
|
|
__kfifo_out(__kfifo, __buf, __n); \
|
|
})
|
|
*/
|
|
|
|
#endif // __GE_KFIFO_H__
|