通用FIFO轻量级环形缓冲管理器开源库lwrb---测试,理解
·
lwrb是一款通用FIFO环形缓冲区实现的开源库,并遵循 MIT 开源许可协议。
优点:
- 使用C99语法编写,并且没有平台相关代码;
- 没有动态内存分配;
- 使用更优的内存复制而不是循环从内存读取数据/向内存写入数据;
lwRB.c 文件
/**
* \file lwrb.c
* \brief Lightweight ring buffer
*/
/*
* Copyright (c) 2020 Tilen MAJERLE
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* This file is part of LwRB - Lightweight ring buffer library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.1
*
* GitHub :https://github.com/MaJerle/lwrb
* 使用文档 : https://docs.majerle.eu/projects/lwrb/en/latest/index.html
* DMA传输例子 : https://docs.majerle.eu/projects/lwrb/en/latest/user-manual/hw-dma-usage.html
* DMA例子示例工程: https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx
*
*/
#include "lwrb.h"
/* Memory set and copy functions */
#define BUF_MEMSET memset
#define BUF_MEMCPY memcpy
#define BUF_MAGIC1 (0xDEADBEEF)
#define BUF_MAGIC2 (~0xDEADBEEF)
#if LWRB_USE_MAGIC
#define BUF_IS_VALID(b) ((b) != NULL && (b)->magic1 == BUF_MAGIC1 && (b)->magic2 == BUF_MAGIC2 && (b)->buff != NULL && (b)->size > 0)
#else
#define BUF_IS_VALID(b) ((b) != NULL && (b)->buff != NULL && (b)->size > 0)
#endif /* LWRB_USE_MAGIC */
#define BUF_MIN(x, y) ((x) < (y) ? (x) : (y))
#define BUF_MAX(x, y) ((x) > (y) ? (x) : (y))
#define BUF_SEND_EVT(b, type, bp) do { if ((b)->evt_fn != NULL) { (b)->evt_fn((b), (type), (bp)); } } while (0)
/**
* \brief Initialize buffer handle to default values with size and buffer data array
* \param[in] buff: Buffer handle
* \param[in] buffdata: Pointer to memory to use as buffer data
* \param[in] size: Size of `buffdata` in units of bytes
* Maximum number of bytes buffer can hold is `size - 1`
* \return `1` on success, `0` otherwise
*/
uint8_t
lwrb_init(LWRB_VOLATILE lwrb_t* buff, void* buffdata, size_t size) {
if (buff == NULL || buffdata == NULL || size == 0) {
return 0;
}
BUF_MEMSET((void*)buff, 0x00, sizeof(*buff));
buff->size = size;
buff->buff = buffdata;
#if LWRB_USE_MAGIC
buff->magic1 = BUF_MAGIC1;
buff->magic2 = BUF_MAGIC2;
#endif /* LWRB_USE_MAGIC */
return 1;
}
/**
* \brief Check if buff is initialized and ready to use
* \param[in] buff: Buffer handle
* \return `1` if ready, `0` otherwise
*/
uint8_t
lwrb_is_ready(LWRB_VOLATILE lwrb_t* buff) {
return BUF_IS_VALID(buff);
}
/**
* \brief Free buffer memory 空闲缓冲内存
* \note Since implementation does not use dynamic allocation,
* it just sets buffer handle to `NULL`
* \param[in] buff: Buffer handle
*/
void
lwrb_free(LWRB_VOLATILE lwrb_t* buff) {
if (BUF_IS_VALID(buff)) {
buff->buff = NULL;
}
}
/**
* \brief Set event function callback for different buffer operations
* \ 为不同的缓冲区操作设置事件函数回调
* \param[in] buff: Buffer handle
* \param[in] evt_fn: Callback function
*/
void
lwrb_set_evt_fn(LWRB_VOLATILE lwrb_t* buff, lwrb_evt_fn evt_fn) {
if (BUF_IS_VALID(buff)) {
buff->evt_fn = evt_fn;
}
}
/**
* \brief Write data to buffer. 将数据写入缓冲区。
* Copies data from `data` array to buffer and marks buffer as full for maximum `btw` number of bytes
* 将数据从`data`数组复制到缓冲区,并将缓冲区标记为最大`btw`字节数已满
*
* \param[in] buff: Buffer handle
* \param[in] data: Pointer to data to write into buffer
* \param[in] btw: Number of bytes to write
* \return Number of bytes written to buffer.
* When returned value is less than `btw`, there was no enough memory available
* to copy full data array
*/
size_t
lwrb_write(LWRB_VOLATILE lwrb_t* buff, const void* data, size_t btw) {
size_t tocopy, free;
const uint8_t* d = data;
if (!BUF_IS_VALID(buff) || data == NULL || btw == 0) {
return 0;
}
/* Calculate maximum number of bytes available to write */
free = lwrb_get_free(buff);
btw = BUF_MIN(free, btw);
if (btw == 0) {
return 0;
}
/* Step 1: Write data to linear part of buffer */
tocopy = BUF_MIN(buff->size - buff->w, btw);
BUF_MEMCPY(&buff->buff[buff->w], d, tocopy);
buff->w += tocopy;
btw -= tocopy;
/* Step 2: Write data to beginning of buffer (overflow part) */
if (btw > 0) {
BUF_MEMCPY(buff->buff, &d[tocopy], btw);
buff->w = btw;
}
/* Step 3: Check end of buffer */
if (buff->w >= buff->size) {
buff->w = 0;
}
BUF_SEND_EVT(buff, LWRB_EVT_WRITE, tocopy + btw);
return tocopy + btw;
}
/**
* \brief Read data from buffer. 从缓冲区读取数据
* Copies data from buffer to `data` array and marks buffer as free for maximum `btr` number of bytes
* 将数据从缓冲区复制到`data`数组,并将缓冲区标记为空闲,以达到最大的`btr`字节数
*
* \param[in] buff: Buffer handle
* \param[out] data: Pointer to output memory to copy buffer data to
* \param[in] btr: Number of bytes to read
* \return Number of bytes read and copied to data array
*/
size_t
lwrb_read(LWRB_VOLATILE lwrb_t* buff, void* data, size_t btr) {
size_t tocopy, full;
uint8_t* d = data;
if (!BUF_IS_VALID(buff) || data == NULL || btr == 0) {
return 0;
}
/* Calculate maximum number of bytes available to read */
full = lwrb_get_full(buff);
btr = BUF_MIN(full, btr);
if (btr == 0) {
return 0;
}
/* Step 1: Read data from linear part of buffer */
tocopy = BUF_MIN(buff->size - buff->r, btr);
BUF_MEMCPY(d, &buff->buff[buff->r], tocopy);
buff->r += tocopy;
btr -= tocopy;
/* Step 2: Read data from beginning of buffer (overflow part) */
if (btr > 0) {
BUF_MEMCPY(&d[tocopy], buff->buff, btr);
buff->r = btr;
}
/* Step 3: Check end of buffer */
if (buff->r >= buff->size) {
buff->r = 0;
}
BUF_SEND_EVT(buff, LWRB_EVT_READ, tocopy + btr);
return tocopy + btr;
}
/**
* \brief Read from buffer without changing read pointer (peek only)
* \ 在不更改读取指针的情况下从缓冲区读取(仅限窥视)
* \param[in] buff: Buffer handle
* \param[in] skip_count: Number of bytes to skip before reading data
* \param[out] data: Pointer to output memory to copy buffer data to
* \param[in] btp: Number of bytes to peek
* \return Number of bytes peeked and written to output array
*/
size_t
lwrb_peek(LWRB_VOLATILE lwrb_t* buff, size_t skip_count, void* data, size_t btp) {
size_t full, tocopy, r;
uint8_t* d = data;
if (!BUF_IS_VALID(buff) || data == NULL || btp == 0) {
return 0;
}
r = buff->r;
/* Calculate maximum number of bytes available to read */
full = lwrb_get_full(buff);
/* Skip beginning of buffer */
if (skip_count >= full) {
return 0;
}
r += skip_count;
full -= skip_count;
if (r >= buff->size) {
r -= buff->size;
}
/* Check maximum number of bytes available to read after skip */
btp = BUF_MIN(full, btp);
if (btp == 0) {
return 0;
}
/* Step 1: Read data from linear part of buffer */
tocopy = BUF_MIN(buff->size - r, btp);
BUF_MEMCPY(d, &buff->buff[r], tocopy);
btp -= tocopy;
/* Step 2: Read data from beginning of buffer (overflow part) */
if (btp > 0) {
BUF_MEMCPY(&d[tocopy], buff->buff, btp);
}
return tocopy + btp;
}
/**
* \brief Get available size in buffer for write operation
* \ 获取缓冲区中可用于写入操作的大小
* \param[in] buff: Buffer handle
* \return Number of free bytes in memory
*/
size_t
lwrb_get_free(LWRB_VOLATILE lwrb_t* buff) {
size_t size, w, r;
if (!BUF_IS_VALID(buff)) {
return 0;
}
/* Use temporary values in case they are changed during operations
如果临时值在操作过程中发生更改,请使用临时值*/
w = buff->w;
r = buff->r;
if (w == r) {
size = buff->size;
} else if (r > w) {
size = r - w;
} else {
size = buff->size - (w - r);
}
/* Buffer free size is always 1 less than actual size
可用缓冲区大小始终比实际大小小1*/
return size - 1;
}
/**
* \brief Get number of bytes currently available in buffer
* \ 获取缓冲区中当前可用的字节数
* \param[in] buff: Buffer handle
* \return Number of bytes ready to be read
*/
size_t
lwrb_get_full(LWRB_VOLATILE lwrb_t* buff) {
size_t w, r, size;
if (!BUF_IS_VALID(buff)) {
return 0;
}
/* Use temporary values in case they are changed during operations */
w = buff->w;
r = buff->r;
if (w == r) {
size = 0;
} else if (w > r) {
size = w - r;
} else {
size = buff->size - (r - w);
}
return size;
}
/**
* \brief Resets buffer to default values. Buffer size is not modified
* \ 将缓冲区重置为默认值。不修改缓冲区大小
* \param[in] buff: Buffer handle
*/
void
lwrb_reset(LWRB_VOLATILE lwrb_t* buff) {
if (BUF_IS_VALID(buff)) {
buff->w = 0;
buff->r = 0;
BUF_SEND_EVT(buff, LWRB_EVT_RESET, 0);
}
}
/**
* \brief Get linear address for buffer for fast read
* \ 获取用于快速读取的缓冲区的线性地址
* \ 配合 lwrb_get_linear_block_read_length 使用
* \param[in] buff: Buffer handle
* \return Linear buffer start address
*/
void*
lwrb_get_linear_block_read_address(LWRB_VOLATILE lwrb_t* buff) {
if (!BUF_IS_VALID(buff)) {
return NULL;
}
return &buff->buff[buff->r];
}
/**
* \brief Get length of linear block address before it overflows for read operation
* \ 获取线性块地址在其溢出以进行读取操作之前的长度
* \param[in] buff: Buffer handle
* \return Linear buffer size in units of bytes for read operation
*/
size_t
lwrb_get_linear_block_read_length(LWRB_VOLATILE lwrb_t* buff) {
size_t w, r, len;
if (!BUF_IS_VALID(buff)) {
return 0;
}
/* Use temporary values in case they are changed during operations */
w = buff->w;
r = buff->r;
if (w > r) {
len = w - r;
} else if (r > w) {
len = buff->size - r;
} else {
len = 0;
}
return len;
}
/**
* \brief Skip (ignore; advance read pointer) buffer data
* \ 跳过(忽略;超前读取指针)缓冲区数据
* Marks data as read in the buffer and increases free memory for up to `len` bytes
* 将数据标记为已在缓冲区中读取,并将可用内存增加到最多“len`”字节
*
* \note Useful at the end of streaming transfer such as DMA
* \param[in] buff: Buffer handle
* \param[in] len: Number of bytes to skip and mark as read
* \return Number of bytes skipped
*/
size_t
lwrb_skip(LWRB_VOLATILE lwrb_t* buff, size_t len) {
size_t full;
if (!BUF_IS_VALID(buff) || len == 0) {
return 0;
}
full = lwrb_get_full(buff);
len = BUF_MIN(len, full);
buff->r += len;
if (buff->r >= buff->size) {
buff->r -= buff->size;
}
BUF_SEND_EVT(buff, LWRB_EVT_READ, len);
return len;
}
/**
* \brief Get linear address for buffer for fast write
* \ 获取用于快速读取的缓冲区的线性地址
* \
* \param[in] buff: Buffer handle
* \return Linear buffer start address
*/
void*
lwrb_get_linear_block_write_address(LWRB_VOLATILE lwrb_t* buff) {
if (!BUF_IS_VALID(buff)) {
return NULL;
}
return &buff->buff[buff->w];
}
/**
* \brief Get length of linear block address before it overflows for write operation
* \ 在写入操作溢出之前获取线性块地址的长度 (线性溢出前可写入得数据大小)
* \
* \param[in] buff: Buffer handle
* \return Linear buffer size in units of bytes for write operation
*/
size_t
lwrb_get_linear_block_write_length(LWRB_VOLATILE lwrb_t* buff) {
size_t w, r, len;
if (!BUF_IS_VALID(buff)) {
return 0;
}
/* Use temporary values in case they are changed during operations */
w = buff->w;
r = buff->r;
if (w >= r) {
len = buff->size - w;
/*
* When read pointer is 0,
* maximal length is one less as if too many bytes
* are written, buffer would be considered empty again (r == w)
*/
if (r == 0) {
/*
* Cannot overflow:
* - If r is not 0, statement does not get called
* - buff->size cannot be 0 and if r is 0, len is greater 0
*/
--len;
}
} else {
len = r - w - 1;
}
return len;
}
/**
* \brief Advance write pointer in the buffer. 缓冲区中的高级写入指针
* Similar to skip function but modifies write pointer instead of read
* 类似于跳过函数,但修改的是写指针而不是读指针
*
* \note Useful when hardware is writing to buffer and 当硬件正在写入缓冲区时非常有用,并且
* application needs to increase number of bytes written to buffer by hardware
* 应用程序需要增加硬件写入缓冲区的字节数
* \param[in] buff: Buffer handle
* \param[in] len: Number of bytes to advance
* \return Number of bytes advanced for write operation
*/
size_t
lwrb_advance(LWRB_VOLATILE lwrb_t* buff, size_t len) {
size_t free;
if (!BUF_IS_VALID(buff) || len == 0) {
return 0;
}
free = lwrb_get_free(buff);
len = BUF_MIN(len, free);
buff->w += len;
if (buff->w >= buff->size) {
buff->w -= buff->size;
}
BUF_SEND_EVT(buff, LWRB_EVT_WRITE, len);
return len;
}
LwRB.h 文件
/**
* \file lwrb.h
* \brief LwRB - Lightweight ring buffer
*/
/*
* Copyright (c) 2020 Tilen MAJERLE
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* This file is part of LwRB - Lightweight ring buffer library.
*
* Author: Tilen MAJERLE <tilen@majerle.eu>
* Version: v2.0.1
*
* GitHub :https://github.com/MaJerle/lwrb
* 使用文档 : https://docs.majerle.eu/projects/lwrb/en/latest/index.html
* DMA传输例子 : https://docs.majerle.eu/projects/lwrb/en/latest/user-manual/hw-dma-usage.html
* DMA例子示例工程: https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx
*/
#ifndef LWRB_HDR_H
#define LWRB_HDR_H
#include <string.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* \defgroup LWRB Lightweight ring buffer manager
* \brief Lightweight ring buffer manager
* \{
*/
/**
* \brief Enable buffer structure pointer parameter as volatile (是否使用关键字volatile)
* To use this feature, uncomment keyword below
*/
#define LWRB_VOLATILE /* volatile */
/**
* \brief Adds 2 magic words to make sure if memory is corrupted 添加2个魔术字以确保内存是否损坏
* application can detect wrong data pointer and maximum size
* 应用程序可以检测错误的数据指针和最大大小
*/
#define LWRB_USE_MAGIC 1
/**
* \brief Event type for buffer operations
*/
typedef enum {
LWRB_EVT_READ, /*!< Read event */
LWRB_EVT_WRITE, /*!< Write event */
LWRB_EVT_RESET, /*!< Reset event */
} lwrb_evt_type_t;
/**
* \brief Buffer structure forward declaration
*/
struct lwrb;
/**
* \brief Event callback function type 事件回调函数类型
* \param[in] buff: Buffer handle for event
* \param[in] evt: Event type
* \param[in] bp: Number of bytes written or read (when used), depends on event type
*/
typedef void (*lwrb_evt_fn)(LWRB_VOLATILE struct lwrb* buff, lwrb_evt_type_t evt, size_t bp);
/**
* \brief Buffer structure
*/
typedef struct lwrb {
#if LWRB_USE_MAGIC
uint32_t magic1; /*!< Magic 1 word */
#endif /* LWRB_USE_MAGIC */
uint8_t* buff; /*!< Pointer to buffer data.
Buffer is considered initialized when `buff != NULL` and `size > 0` */
size_t size; /*!< Size of buffer data. Size of actual buffer is `1` byte less than value holds */
size_t r; /*!< Next read pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */
size_t w; /*!< Next write pointer. Buffer is considered empty when `r == w` and full when `w == r - 1` */
lwrb_evt_fn evt_fn; /*!< Pointer to event callback function */
#if LWRB_USE_MAGIC
uint32_t magic2; /*!< Magic 2 word */
#endif /* LWRB_USE_MAGIC */
} lwrb_t;
uint8_t lwrb_init(LWRB_VOLATILE lwrb_t* buff, void* buffdata, size_t size);
uint8_t lwrb_is_ready(LWRB_VOLATILE lwrb_t* buff);
void lwrb_free(LWRB_VOLATILE lwrb_t* buff);
void lwrb_reset(LWRB_VOLATILE lwrb_t* buff);
void lwrb_set_evt_fn(LWRB_VOLATILE lwrb_t* buff, lwrb_evt_fn fn);
/* Read/Write functions 读/写功能*/
size_t lwrb_write(LWRB_VOLATILE lwrb_t* buff, const void* data, size_t btw);
size_t lwrb_read(LWRB_VOLATILE lwrb_t* buff, void* data, size_t btr);
size_t lwrb_peek(LWRB_VOLATILE lwrb_t* buff, size_t skip_count, void* data, size_t btp);
/* Buffer size information 缓冲区大小信息 */
size_t lwrb_get_free(LWRB_VOLATILE lwrb_t* buff);
size_t lwrb_get_full(LWRB_VOLATILE lwrb_t* buff);
/* Read data block management 读数据块管理*/
void* lwrb_get_linear_block_read_address(LWRB_VOLATILE lwrb_t* buff);
size_t lwrb_get_linear_block_read_length(LWRB_VOLATILE lwrb_t* buff);
size_t lwrb_skip(LWRB_VOLATILE lwrb_t* buff, size_t len);
/* Write data block management 写数据块管理*/
void* lwrb_get_linear_block_write_address(LWRB_VOLATILE lwrb_t* buff);
size_t lwrb_get_linear_block_write_length(LWRB_VOLATILE lwrb_t* buff);
size_t lwrb_advance(LWRB_VOLATILE lwrb_t* buff, size_t len);
/**
* \}
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
/**
* 例程Demo
* uint8_t lwrb_data[8 + 1]; //缓存数组
* lwrb_t buff; //句柄
* uint8_t tmp[8]; //读缓存
*
* //Log显示反馈
* void my_buff_evt_fn(lwrb_t* buff, lwrb_evt_type_t type, size_t len) {
* switch (type) {
* case LWRB_EVT_RESET:
* printf("[EVT] Buffer reset event!\r\n");
* break;
* case LWRB_EVT_READ:
* printf("[EVT] Buffer read event: %d byte(s)!\r\n", (int)len);
* break;
* case LWRB_EVT_WRITE:
* printf("[EVT] Buffer write event: %d byte(s)!\r\n", (int)len);
* break;
* default: break;
* }
* }
*
* //测试的主程序
* int main() {
* size_t len;
*
* // Init buffer
* lwrb_init(&buff, lwrb_data, sizeof(lwrb_data)); //初始化,buff头, 实际数组 lwrb_data 数组大小
* lwrb_set_evt_fn(&buff, my_buff_evt_fn); //事件反馈实体
*
* lwrb_write(&buff, "abc", 3);
* lwrb_write(&buff, "abc", 3);
* lwrb_write(&buff, "abc", 3); //写入9个数据
* len = lwrb_read(&buff, tmp, 9); //读取9个数据
*
* buff.r = 0; //复位,读写位置
* buff.w = 0;
* memset(lwrb_get_linear_block_write_address(&buff), 'A', lwrb_get_linear_block_write_length(&buff)); //r=0 w=0 线性溢出前为空闲的位置 ,可写入 8字节
* lwrb_advance(&buff, lwrb_get_linear_block_write_length(&buff)); //写指针直接跳过8个位置
*
* buff.r = 2;
* buff.w = 0;
* memset(lwrb_get_linear_block_write_address(&buff), 'B', lwrb_get_linear_block_write_length(&buff)); //r=2 w=0 线性溢出前为空闲的位置 ,可写入 1字节
* lwrb_advance(&buff, lwrb_get_linear_block_write_length(&buff)); //写指针直接跳过1个位置
*
* buff.r = 3;
* buff.w = 3;
* memset(lwrb_get_linear_block_write_address(&buff), 'C', lwrb_get_linear_block_write_length(&buff));//r=3 w=3 线性溢出前为空闲的位置 ,可写入 6字节
* lwrb_advance(&buff, lwrb_get_linear_block_write_length(&buff)); //写指针直接跳过1个位置
*
* lwrb_reset(&buff);
*
* //for (size_t r = 0; r < sizeof(lwrb_data); ++r) {
* // void* ptr;
* // for (size_t w = 0; w < sizeof(lwrb_data); ++w) {
* // buff.r = r;
* // buff.w = w;
* // ptr = lwrb_get_linear_block_write_address(&buff);
* // len = lwrb_get_linear_block_write_length(&buff);
* // printf("W: %3d, R: %3d, LEN: %3d\r\n", (int)w, (int)r, (int)len);
* // }
* //}
*
* return 0;
* }
*
* =========================================================
* debug 显示信息
* =========================================================
* [EVT] Buffer write event: 3 byte(s)!
* [EVT] Buffer write event: 3 byte(s)!
* [EVT] Buffer write event: 2 byte(s)!
* [EVT] Buffer read event: 8 byte(s)!
* [EVT] Buffer write event: 8 byte(s)!
* [EVT] Buffer write event: 1 byte(s)!
* [EVT] Buffer write event: 6 byte(s)!
* [EVT] Buffer reset event!
* =========================================================
*/
#endif /* LWRB_HDR_H */
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)