添加环形buff

This commit is contained in:
OPTOC
2025-10-16 09:44:18 +08:00
parent d96f0a1ee2
commit b0307adc46
3 changed files with 230 additions and 0 deletions

View File

@@ -32,6 +32,7 @@ list(APPEND srcs "drivers/sertrf/sertrf.c")
list(APPEND srcs "drivers/sertrf/device.c") list(APPEND srcs "drivers/sertrf/device.c")
list(APPEND srcs "drivers/sertrf/key.c") list(APPEND srcs "drivers/sertrf/key.c")
list(APPEND srcs "drivers/sertrf/ota_u.c") list(APPEND srcs "drivers/sertrf/ota_u.c")
list(APPEND srcs "drivers/sertrf/ring_buffer.c")
list(APPEND srcs "drivers/sertrf/protocol/MSP.c") list(APPEND srcs "drivers/sertrf/protocol/MSP.c")
list(APPEND srcs "drivers/sertrf/protocol/p_protocol.c") list(APPEND srcs "drivers/sertrf/protocol/p_protocol.c")
list(APPEND srcs "drivers/sertrf/protocol/mavlink_control.c") list(APPEND srcs "drivers/sertrf/protocol/mavlink_control.c")

View File

@@ -0,0 +1,137 @@
/* ring_buffer.c */
#include "ring_buffer.h"
#include <stdlib.h>
#include <string.h>
bool rb_init(RingBuffer *rb, size_t capacity, size_t elem_size) {
rb->buffer = malloc(capacity * elem_size);
if (!rb->buffer) return false;
rb->max = capacity;
rb->sz = elem_size;
rb->head = 0;
rb->tail = 0;
rb->full = false;
return true;
}
void rb_free(RingBuffer *rb) {
free(rb->buffer);
rb->buffer = NULL;
}
void rb_reset(RingBuffer *rb) {
rb->head = rb->tail = 0;
rb->full = false;
}
bool rb_empty(const RingBuffer *rb) {
return (!rb->full && (rb->head == rb->tail));
}
bool rb_full(const RingBuffer *rb) {
return rb->full;
}
bool rb_put(RingBuffer *rb, const void *data) {
if (rb->full) return false;
memcpy((char*)rb->buffer + (rb->head * rb->sz), data, rb->sz);
rb->head = (rb->head + 1) % rb->max;
rb->full = (rb->head == rb->tail);
return true;
}
bool rb_get(RingBuffer *rb, void *data) {
if (rb_empty(rb)) return false;
memcpy(data, (char*)rb->buffer + (rb->tail * rb->sz), rb->sz);
rb->full = false;
rb->tail = (rb->tail + 1) % rb->max;
return true;
}
size_t rb_size(const RingBuffer *rb) {
size_t size = rb->max;
if (!rb->full) {
if (rb->head >= rb->tail) {
size = rb->head - rb->tail;
} else {
size = rb->max + rb->head - rb->tail;
}
}
return size;
}
size_t rb_get_bulk(RingBuffer *rb, void *data, size_t len) {
if (rb_empty(rb)) {
return 0;
}
size_t curr_size = rb_size(rb);
size_t to_read = len < curr_size ? len : curr_size;
// 第一次拷贝:从 tail 到缓冲区末尾
size_t cnt1 = rb->max - rb->tail;
if (cnt1 > to_read) cnt1 = to_read;
memcpy(data,
(char*)rb->buffer + rb->tail * rb->sz,
cnt1 * rb->sz);
// 第二次拷贝:如果需要,从缓冲区开头继续读取
size_t cnt2 = to_read - cnt1;
if (cnt2 > 0) {
memcpy((char*)data + cnt1 * rb->sz,
rb->buffer,
cnt2 * rb->sz);
}
rb->tail = (rb->tail + to_read) % rb->max;
rb->full = false;
return to_read;
}
size_t rb_put_bulk(RingBuffer *rb, const void *data, size_t len) {
// 如果缓冲区已满,直接返回 0
if (rb->full) {
return 0;
}
// 计算当前可用空间(元素数)
size_t curr_size = rb_size(rb);
size_t avail = rb->max - curr_size;
// 实际要写入的元素数
size_t to_write = len < avail ? len : avail;
if (to_write == 0) {
return 0;
}
// 第一次拷贝:从 head 开始直到缓冲区末尾
size_t cnt1 = rb->max - rb->head;
if (cnt1 > to_write) {
cnt1 = to_write;
}
memcpy((char*)rb->buffer + rb->head * rb->sz,
data,
cnt1 * rb->sz);
// 第二次拷贝:如果还要写入,则回绕到缓冲区开头
size_t cnt2 = to_write - cnt1;
if (cnt2 > 0) {
memcpy(rb->buffer,
(const char*)data + cnt1 * rb->sz,
cnt2 * rb->sz);
}
// 更新 head 索引
rb->head = (rb->head + to_write) % rb->max;
// 如果写满,则置 full
if (to_write == avail) {
rb->full = true;
}
return to_write;
}

View File

@@ -0,0 +1,92 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
/** 环形缓冲区结构体 */
typedef struct {
void *buffer; /**< 缓冲区起始地址 */
size_t head; /**< 写索引 */
size_t tail; /**< 读索引 */
size_t max; /**< 最大元素数量 */
size_t sz; /**< 每个元素字节大小 */
bool full; /**< 是否已满标志 */
} RingBuffer;
/**
* 初始化环形缓冲区
* @param rb 指向 RingBuffer 结构
* @param capacity 最大元素个数
* @param elem_size 每个元素字节大小
* @return true 成功false 内存分配失败
*/
bool rb_init(RingBuffer *rb, size_t capacity, size_t elem_size);
/**
* 释放环形缓冲区占用的内存
* @param rb 指向 RingBuffer 结构
*/
void rb_free(RingBuffer *rb);
/**
* 重置缓冲区为空
* @param rb 指向 RingBuffer 结构
*/
void rb_reset(RingBuffer *rb);
/**
* 判断缓冲区是否为空
* @param rb 指向 RingBuffer 结构
* @return true 如果空,否则 false
*/
bool rb_empty(const RingBuffer *rb);
/**
* 判断缓冲区是否已满
* @param rb 指向 RingBuffer 结构
* @return true 如果满,否则 false
*/
bool rb_full(const RingBuffer *rb);
/**
* 向缓冲区写入一个元素
* @param rb 指向 RingBuffer 结构
* @param data 指向要写入的数据
* @return true 写入成功false 缓冲区已满
*/
bool rb_put(RingBuffer *rb, const void *data);
/**
* 从缓冲区读取一个元素
* @param rb 指向 RingBuffer 结构
* @param data 指向用于存放读取数据的缓冲
* @return true 读取成功false 缓冲区为空
*/
bool rb_get(RingBuffer *rb, void *data);
/**
* 获取当前缓冲区中已存储的元素数量
* @param rb 指向 RingBuffer 结构
* @return 已存储的元素数量
*/
size_t rb_size(const RingBuffer *rb);
/**
* 批量向缓冲区写入多个元素
* @param rb 指向 RingBuffer 结构
* @param data 指向要写入的数据数组
* @param len 期望写入的元素个数
* @return 已成功写入的元素个数(可能小于 len如果空间不足
*/
size_t rb_put_bulk(RingBuffer *rb, const void *data, size_t len);
/**
* 批量向缓冲区读取多个元素
* @param rb 指向 RingBuffer 结构
* @param data 指向要写入的数据数组
* @param len 期望写入的元素个数
* @return 已成功写入的元素个数(可能小于 len如果空间不足
*/
size_t rb_get_bulk(RingBuffer *rb, void *data, size_t len) ;