diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 4fdff86..515896e 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -32,6 +32,7 @@ list(APPEND srcs "drivers/sertrf/sertrf.c") list(APPEND srcs "drivers/sertrf/device.c") list(APPEND srcs "drivers/sertrf/key.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/p_protocol.c") list(APPEND srcs "drivers/sertrf/protocol/mavlink_control.c") diff --git a/app/drivers/sertrf/ring_buffer.c b/app/drivers/sertrf/ring_buffer.c new file mode 100644 index 0000000..72457cd --- /dev/null +++ b/app/drivers/sertrf/ring_buffer.c @@ -0,0 +1,137 @@ +/* ring_buffer.c */ + +#include "ring_buffer.h" +#include +#include + +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; +} diff --git a/app/drivers/sertrf/ring_buffer.h b/app/drivers/sertrf/ring_buffer.h new file mode 100644 index 0000000..8aa8940 --- /dev/null +++ b/app/drivers/sertrf/ring_buffer.h @@ -0,0 +1,92 @@ +#pragma once + + +#include +#include + +/** 环形缓冲区结构体 */ +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) ; + +