新增动态申请内存方法,可进行内存回收。完善注释
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build/
|
36
CMakeLists.txt
Executable file
36
CMakeLists.txt
Executable file
@@ -0,0 +1,36 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(My_ptotocol VERSION 0.1 LANGUAGES CXX C)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_COMPILER gcc)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
# set(CMAKE_CXX_STANDARD 23)
|
||||
# set(CMAKE_CXX_COMPILER g++)
|
||||
# set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
|
||||
|
||||
include_directories(
|
||||
.
|
||||
src/lib
|
||||
)
|
||||
set(PROJECT_SOURCES
|
||||
src/main.c
|
||||
src/lib/kfifo/kfifo.c
|
||||
)
|
||||
add_executable(${PROJECT_NAME}
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
366
src/lib/kfifo/kfifo.c
Executable file
366
src/lib/kfifo/kfifo.c
Executable file
@@ -0,0 +1,366 @@
|
||||
/**
|
||||
* @file kfifo.c
|
||||
* @author guishenking (guishenking@outlook.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2025-08-15
|
||||
*
|
||||
* @copyright Copyright (c) 2025
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kfifo.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief 获取 FIFO 数据起始位置
|
||||
*
|
||||
*/
|
||||
#define KFIFO_POOL_PTR(_fifo) ((uint8_t *)_fifo->pool)
|
||||
|
||||
/**
|
||||
* @brief 获取写入位置偏移量
|
||||
*
|
||||
* @param[in] fifo
|
||||
* @return uint32_t
|
||||
*/
|
||||
#define kfifo_offset_in(_fifo_ptr) ((_fifo_ptr)->in & (_fifo_ptr)->mask)
|
||||
|
||||
/**
|
||||
* @brief 获取读取位置偏移量
|
||||
*
|
||||
* @param[in] fifo
|
||||
* @return uint32_t
|
||||
*/
|
||||
#define kfifo_offset_out(_fifo_ptr) ((_fifo_ptr)->out & (_fifo_ptr)->mask)
|
||||
|
||||
/**
|
||||
* @brief 计算从当前读取位置偏移 _seek 后的新位置在缓冲区中的实际偏移。
|
||||
*
|
||||
*/
|
||||
#define kfifo_offset_seek_out(_fifo_ptr, _seek) \
|
||||
(((_fifo_ptr)->out + (_seek)) & (_fifo_ptr)->mask)
|
||||
|
||||
/**
|
||||
* @brief 获取写入位置到缓冲区末尾的空间大小
|
||||
*
|
||||
* @param[in] fifo
|
||||
* @return uint32_t
|
||||
*/
|
||||
#define kfifo_remain_in(_fifo_ptr) \
|
||||
(kfifo_size(_fifo_ptr) - kfifo_offset_in(_fifo_ptr))
|
||||
|
||||
/**
|
||||
* @brief 获取读取位置到缓冲区末尾的空间大小
|
||||
*
|
||||
* @param[in] fifo
|
||||
* @return uint32_t
|
||||
*/
|
||||
#define kfifo_remain_out(_fifo_ptr) \
|
||||
(kfifo_size(_fifo_ptr) - kfifo_offset_out(_fifo_ptr))
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
#define kfifo_remain_seek_out(_fifo_ptr, _seek) \
|
||||
(kfifo_size(_fifo_ptr) - kfifo_offset_seek_out(_fifo_ptr, _seek))
|
||||
|
||||
/**
|
||||
* @brief 通过申请内存的方式初始化 FIFO,使得内存可回收
|
||||
*
|
||||
* @param size
|
||||
* @return kfifo_t*
|
||||
*/
|
||||
kfifo_t* kfifo_init_dynamic(uint32_t size) {
|
||||
// 检查size是否为2的幂
|
||||
if ((size & (size - 1)) != 0) return NULL;
|
||||
|
||||
// 分配缓冲区和控制结构
|
||||
uint8_t *pool = (uint8_t*)malloc(size);
|
||||
if (!pool) return NULL;
|
||||
|
||||
kfifo_t *fifo = (kfifo_t*)malloc(sizeof(kfifo_t));
|
||||
if (!fifo) { free(pool); return NULL; }
|
||||
|
||||
// 初始化结构体
|
||||
fifo->in = 0;
|
||||
fifo->out = 0;
|
||||
fifo->mask = size - 1;
|
||||
fifo->pool = pool;
|
||||
fifo->method = KFIFO_CREATED_METHOD_DYNAMIC; // 设置为动态创建方法
|
||||
return fifo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 销毁通过申请内存方式创建的 FIFO
|
||||
*
|
||||
* @param fifo
|
||||
* @return true success destroyed memory
|
||||
* @return false failed Memery was created by static method
|
||||
*/
|
||||
bool kfifo_destroy(kfifo_t *fifo) {
|
||||
if (fifo->method == KFIFO_CREATED_METHOD_STATIC) {
|
||||
return false; // 静态创建的 FIFO 不允许销毁
|
||||
}
|
||||
if (fifo) {
|
||||
if(fifo->pool == NULL) {
|
||||
free(fifo); // 如果 pool 已经是 NULL,直接释放 fifo
|
||||
return false; // 如果 pool 已经是 NULL,直接返回
|
||||
}
|
||||
free(fifo->pool);
|
||||
fifo->pool = NULL; // 清空指针,避免悬挂指针
|
||||
free(fifo);
|
||||
fifo = NULL; // 清空指针,避免悬挂指针
|
||||
return true; // 成功销毁
|
||||
}
|
||||
return false; // 如果 fifo 是 NULL,直接返回 false
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化FIFO
|
||||
* @note 使用@kfifo_def 定义的fifo无需调用此函数
|
||||
* @param[in] fifo
|
||||
* @param[in] pool fifo 数据缓冲区
|
||||
* @param[in] size fifo 大小,必须是2的幂次
|
||||
* @return int
|
||||
* @retval -1 参数错误、pool对齐错误
|
||||
* @retval 0 初始化完成
|
||||
*/
|
||||
bool kfifo_init_static(kfifo_t *fifo, uint8_t *pool, uint32_t size) {
|
||||
/* 判断参数是否正确 */
|
||||
if ((NULL == fifo) || (NULL == pool) || (size & size - 1)) {
|
||||
return false;
|
||||
}
|
||||
fifo->in = 0;
|
||||
fifo->out = 0;
|
||||
fifo->pool = pool;
|
||||
fifo->mask = size - 1;
|
||||
fifo->method = KFIFO_CREATED_METHOD_STATIC; // 设置为静态创建方法
|
||||
|
||||
return true; // 初始化成功
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 向 in 位置写入一个字节
|
||||
*
|
||||
* @param fifo
|
||||
* @param data
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool kfifo_put_byte(kfifo_t *fifo, uint8_t data) {
|
||||
if (NULL == fifo) {
|
||||
return false; // 参数错误
|
||||
}
|
||||
if (kfifo_is_full(fifo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
KFIFO_POOL_PTR(fifo)[kfifo_offset_in(fifo)] = data;
|
||||
fifo->in++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从 out 位置获取一个字节
|
||||
*
|
||||
* @param fifo
|
||||
* @param data
|
||||
* @return int
|
||||
*/
|
||||
bool kfifo_get_byte(kfifo_t *fifo, uint8_t *data) {
|
||||
if ((NULL == fifo) || (NULL == data)) {
|
||||
return false; // 参数错误
|
||||
}
|
||||
if (kfifo_is_empty(fifo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*data = KFIFO_POOL_PTR(fifo)[kfifo_offset_out(fifo)];
|
||||
fifo->out++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 写入数据块
|
||||
* @note 当fifo空间不足时会对 data 进行截断处理
|
||||
* @param[in] fifo
|
||||
* @param[in] data
|
||||
* @param[in] len
|
||||
* @return int 返回写入的数据大小
|
||||
*/
|
||||
int kfifo_in(kfifo_t *fifo, const uint8_t *data, uint32_t len) {
|
||||
uint32_t avail = kfifo_avail(fifo);
|
||||
|
||||
if (len > avail) {
|
||||
len = avail;
|
||||
}
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (kfifo_remain_in(fifo) < len) {
|
||||
memcpy(fifo->pool + kfifo_offset_in(fifo),
|
||||
data,
|
||||
kfifo_remain_in(fifo));
|
||||
memcpy(fifo->pool,
|
||||
data + kfifo_remain_in(fifo),
|
||||
len - kfifo_remain_in(fifo));
|
||||
} else {
|
||||
memcpy(fifo->pool + kfifo_offset_in(fifo),
|
||||
data,
|
||||
len);
|
||||
}
|
||||
|
||||
fifo->in += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 读取数据块
|
||||
*
|
||||
* @param fifo
|
||||
* @param buffer
|
||||
* @param size
|
||||
* @return int
|
||||
*/
|
||||
int kfifo_out(kfifo_t *fifo, uint8_t *buffer, uint32_t size) {
|
||||
uint32_t used = kfifo_used(fifo);
|
||||
if (size > used) {
|
||||
size = used;
|
||||
}
|
||||
if (0 == size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (kfifo_remain_out(fifo) < size) {
|
||||
memcpy(buffer, fifo->pool + kfifo_offset_out(fifo), kfifo_remain_out(fifo));
|
||||
memcpy(buffer + kfifo_remain_out(fifo),
|
||||
fifo->pool,
|
||||
size - kfifo_remain_out(fifo));
|
||||
} else {
|
||||
memcpy(buffer,
|
||||
fifo->pool + kfifo_offset_out(fifo),
|
||||
size);
|
||||
}
|
||||
|
||||
fifo->out += size;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取 fifo 数据指针偏移位置
|
||||
*
|
||||
* @param[in] fifo
|
||||
* @param[in] ptr
|
||||
* @return int 可连续读取的数据数量
|
||||
* @retval 0 fifo is empty
|
||||
*/
|
||||
int kfifo_peek(kfifo_t *fifo, const uint8_t **ptr) {
|
||||
int linear;
|
||||
|
||||
*ptr = NULL;
|
||||
|
||||
if (kfifo_is_empty(fifo)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*ptr = &KFIFO_POOL_PTR(fifo)[kfifo_offset_out(fifo)];
|
||||
if (kfifo_offset_in(fifo) <= kfifo_offset_out(fifo)) {
|
||||
linear = kfifo_remain_out(fifo);// 数据在缓冲区末尾
|
||||
} else {
|
||||
linear = kfifo_used(fifo);// 数据未跨缓冲区末尾
|
||||
}
|
||||
|
||||
return linear;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取偏移 seek 后的数据指针(模拟读取后位置)。
|
||||
*
|
||||
* @param fifo
|
||||
* @param ptr
|
||||
* @param seek
|
||||
* @return int
|
||||
*/
|
||||
int kfifo_peek_seek(kfifo_t *fifo, const uint8_t **ptr, uint32_t seek) {
|
||||
*ptr = NULL;
|
||||
|
||||
if (kfifo_used(fifo) < seek) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *ptr = &KFIFO_POOL_PTR(fifo)[kfifo_offset_seek_out(fifo, seek)];
|
||||
*ptr = (uint8_t*)fifo->pool + kfifo_offset_seek_out(fifo, seek);
|
||||
if (kfifo_remain_out(fifo) > seek) {
|
||||
seek = kfifo_remain_seek_out(fifo, seek);
|
||||
} else {
|
||||
seek = kfifo_used(fifo) - seek;
|
||||
}
|
||||
|
||||
return seek;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 复制数据到 buffer 但不移动 out 指针。
|
||||
*
|
||||
* @param[in] fifo
|
||||
* @param[in] buffer 存储数据的缓冲区
|
||||
* @param[in] size 需要复制的数据量
|
||||
* @return int
|
||||
* @return -1 参数错误
|
||||
*/
|
||||
int kfifo_peek_block(kfifo_t *fifo, uint8_t *buffer, uint32_t size) {
|
||||
int temp;
|
||||
|
||||
if ((NULL == fifo) || (NULL == buffer) || (0 == size)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* FIFO 中的数据量 */
|
||||
temp = kfifo_used(fifo);
|
||||
if (!temp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size > temp) {
|
||||
size = temp;
|
||||
}
|
||||
|
||||
temp = kfifo_remain_out(fifo);
|
||||
|
||||
if (size > temp) {
|
||||
memcpy(buffer, fifo->pool + kfifo_offset_out(fifo), temp);
|
||||
memcpy(buffer + temp,
|
||||
fifo->pool,
|
||||
size - temp);
|
||||
} else {
|
||||
memcpy(buffer,
|
||||
fifo->pool + kfifo_offset_out(fifo),
|
||||
size);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 丢弃seek个字节
|
||||
*
|
||||
* @param fifo
|
||||
* @param seek 偏移量
|
||||
* @return int
|
||||
*/
|
||||
int kfifo_seek(kfifo_t *fifo, uint32_t seek) {
|
||||
if (kfifo_used(fifo) < seek) {
|
||||
seek = kfifo_used(fifo);
|
||||
}
|
||||
|
||||
fifo->out += seek;
|
||||
return seek;
|
||||
}
|
143
src/lib/kfifo/kfifo.h
Executable file
143
src/lib/kfifo/kfifo.h
Executable file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* @file kfifo.h
|
||||
* @author guishenking (guishenking@outlook.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2025-08-15
|
||||
*
|
||||
* @copyright Copyright (c) 2025
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _KFIFO_H_
|
||||
#define _KFIFO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
enum kfifo_created_method {
|
||||
KFIFO_CREATED_METHOD_STATIC = 0, /*!< 静态创建 */
|
||||
KFIFO_CREATED_METHOD_DYNAMIC, /*!< 动态创建 */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief kfifo 结构定义
|
||||
*
|
||||
*/
|
||||
typedef struct kfifo {
|
||||
uint32_t in; /*!< 输入数据下标, 对于单片机使用 volatile 修饰 */
|
||||
uint32_t out; /*!< 输出数据下标, 对于单片机使用 volatile 修饰 */
|
||||
uint32_t mask;/*!< 缓冲区大小掩码, size - 1 */
|
||||
uint8_t *pool;/*!< 数据缓冲区指针 */
|
||||
enum kfifo_created_method method;/*!< FIFO 创建方法 */
|
||||
}kfifo_t;
|
||||
|
||||
/**
|
||||
* @brief kfifo 初始化器
|
||||
*
|
||||
* @param[in] _pool FIFO数据缓冲区
|
||||
* @param[in] _size 缓冲区大小
|
||||
*/
|
||||
#define kfifo_initializer(_pool, _size) \
|
||||
{ 0, 0, _size - 1, _pool, KFIFO_CREATED_METHOD_STATIC, }
|
||||
|
||||
/**
|
||||
* @brief 定义 KFIFO
|
||||
*
|
||||
* @param[in] _name FIFO名称
|
||||
* @param[in] _size 缓冲区大小,必须是2的幂次
|
||||
*/
|
||||
#define kfifo_def(_name, _size) \
|
||||
static uint8_t _##_name##_pool[_size]; \
|
||||
static kfifo_t _name = kfifo_initializer(_##_name##_pool, _size)//初始化fifo
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
//静态创建fifo
|
||||
bool kfifo_init_static(kfifo_t *fifo, uint8_t *pool, uint32_t size);
|
||||
//动态创建fifo
|
||||
kfifo_t* kfifo_init_dynamic(uint32_t size);
|
||||
//销毁动态创建的fifo
|
||||
bool kfifo_destroy(kfifo_t *fifo) ;
|
||||
|
||||
//向fifo写入一个字节
|
||||
bool kfifo_put_byte(kfifo_t *fifo, uint8_t data);
|
||||
|
||||
//从fifo读取一个字节
|
||||
bool kfifo_get_byte(kfifo_t *fifo, uint8_t *data);
|
||||
|
||||
//写入数据块
|
||||
int kfifo_in(kfifo_t *fifo, const uint8_t *data, uint32_t len);
|
||||
|
||||
//读取数据块
|
||||
int kfifo_out(kfifo_t *fifo, uint8_t *data, uint32_t size);
|
||||
|
||||
//获取fifo数据指针
|
||||
int kfifo_peek(kfifo_t *fifo, const uint8_t **ptr);
|
||||
|
||||
//从获取偏移位置的数据指针
|
||||
int kfifo_peek_seek(kfifo_t *fifo, const uint8_t **ptr, uint32_t seek);
|
||||
|
||||
//从fifo读取数据块,不改变 fifo 状态
|
||||
int kfifo_peek_block(kfifo_t *fifo, uint8_t *buffer, uint32_t size);
|
||||
|
||||
//丢弃fifo部分数据
|
||||
int kfifo_seek(kfifo_t *fifo, uint32_t seek);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 清空 FIFO
|
||||
*
|
||||
*/
|
||||
#define kfifo_clear(_fifo_ptr) \
|
||||
do { \
|
||||
(_fifo_ptr)->in = 0; \
|
||||
(_fifo_ptr)->out = 0; \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief 获取fifo大小
|
||||
*
|
||||
* @param[in] fifo
|
||||
* @return uint32_t
|
||||
*/
|
||||
#define kfifo_size(_fifo_ptr) ((_fifo_ptr)->mask + 1)
|
||||
|
||||
/**
|
||||
* @brief 获取当前存储的数据量
|
||||
*
|
||||
* @param[in] fifo
|
||||
* @return uint32_t
|
||||
*/
|
||||
#define kfifo_used(_fifo_ptr) \
|
||||
(((kfifo_size(_fifo_ptr)) + (_fifo_ptr)->out) == (_fifo_ptr)->in \
|
||||
? kfifo_size(_fifo_ptr) \
|
||||
: (((_fifo_ptr)->in - (_fifo_ptr)->out) & (_fifo_ptr)->mask))
|
||||
|
||||
/**
|
||||
* @brief 获取空闲空间大小
|
||||
*
|
||||
* @param[in] fifo
|
||||
* @return uint32_t
|
||||
*/
|
||||
#define kfifo_avail(_fifo_ptr) (kfifo_size(_fifo_ptr) - kfifo_used(_fifo_ptr))
|
||||
|
||||
/**
|
||||
* @brief 判断 FIFO 是否已满
|
||||
*
|
||||
*/
|
||||
#define kfifo_is_full(_fifo_ptr) (kfifo_avail(_fifo_ptr) == 0)
|
||||
|
||||
/**
|
||||
* @brief 判断 FIFO 是否为空
|
||||
*
|
||||
*/
|
||||
#define kfifo_is_empty(_fifo_ptr) (kfifo_used(_fifo_ptr) == 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* !_KFIFO_H_ */
|
40
src/main.c
Executable file
40
src/main.c
Executable file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file main.c
|
||||
* @author guishenking (guishenking@outlook.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2025-07-24
|
||||
*
|
||||
* @copyright Copyright (c) 2025
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "lib/kfifo/kfifo.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
kfifo_def(fifo,1024);
|
||||
|
||||
int main(){
|
||||
// 示例数据
|
||||
uint8_t src_data[] = {0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
size_t src_length = sizeof(src_data);
|
||||
uint8_t dest_data[1024];
|
||||
size_t dest_length = sizeof(dest_data);
|
||||
uint32_t offset;
|
||||
|
||||
memset(dest_data, 0, dest_length); // 清空目标数据缓冲区
|
||||
|
||||
kfifo_in(&fifo, dest_data, dest_length); // 将数据写入FIFO
|
||||
|
||||
int ret = kfifo_peek_block(&fifo, dest_data, dest_length); // 从FIFO读取数据
|
||||
|
||||
memset(src_data, 0, src_length); // 清空源数据缓冲区
|
||||
|
||||
// 解码数据
|
||||
kfifo_seek(&fifo, offset); // 根据偏移量调整FIFO读取位置
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user