/// ------------------------------------------------------------------------------------------------------------------------------------ /// /// MIT License /// /// 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. /// /// Copyright (c) 2022 ycz. All rights reserved. /// /// Created by ycz on 2022/1/12. /// /// @brief /// y_ringbuf 具体功能实现 /// /// ------------------------------------------------------------------------------------------------------------------------------------ /// ------------------------------------------------------------------------------------------------------------------------------------ /// 头文件 /// ------------------------------------------------------------------------------------------------------------------------------------ #include "y_ringbuf.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "esp_log.h" #include "driver/uart.h" #include "string.h" #include "driver/gpio.h" #include "freertos/timers.h" extern SemaphoreHandle_t debug_Mutex; /// ------------------------------------------------------------------------------------------------------------------------------------ /// 结构体 /// ------------------------------------------------------------------------------------------------------------------------------------ /// ringbuf 实例结构类型 struct ringbuf { uint8_t *buf; ///< ringbuf 指针 uint16_t length; ///< ringbuf 大小 最大64k uint16_t head; ///< ringbuf 头所在位置 uint16_t tail; ///< ringbuf 尾所在位置 uint16_t used_size; ///< ringbuf 已使用大小 uint16_t free_size; ///< ringbuf 空闲大小 #if Y_RINGBUF_USE_MUTEX_LOCK == 1 int32_t mutex_lock; ///< 互斥锁句柄 #endif }; /// ------------------------------------------------------------------------------------------------------------------------------------ /// 私有函数 /// ------------------------------------------------------------------------------------------------------------------------------------ #if Y_RINGBUF_USE_MUTEX_LOCK == 1 /// @brief ringbuf 上锁 /// @param [in] ringbuf ringbuf 句柄指针 /// @retval true 成功 /// @retval false 失败 static bool _y_ringbuf_lock(RINGBUF_st *ringbuf) { // todo : 添加代码 xSemaphoreTake( debug_Mutex, portMAX_DELAY ); return true; } /// @brief ringbuf 解锁 /// @param [in] ringbuf ringbuf 句柄指针 /// @retval true 成功 /// @retval false 失败 static bool _y_ringbuf_unlock(RINGBUF_st *ringbuf) { // todo : 添加代码 xSemaphoreGive( debug_Mutex ); return true; } /// @brief 销毁互斥锁 /// @param [in] ringbuf ringbuf 句柄指针 /// @retval true 成功 /// @retval false 失败 static bool _y_ringbuf_destroy_mutex_lock(RINGBUF_st *ringbuf) { // todo : 添加代码 vSemaphoreDelete(debug_Mutex); return true; } /// @brief 创建互斥锁 /// @param [in] ringbuf ringbuf 句柄指针 /// @retval true 成功 /// @retval false 失败 static bool _y_ringbuf_create_mutex_lock(RINGBUF_st *ringbuf) { // todo : 添加代码 debug_Mutex = xSemaphoreCreateMutex(); if(debug_Mutex == NULL) { return false; } return true; } #endif // Y_RINGBUF_USE_MUTEX_LOCK /// @brief ringbuf read 子函数 /// @param [in] ringbuf ringbuf 句柄指针 /// @param [out] data 读到数据存放的地址 /// @param [in] size 想要读取的字节数 /// @param [in] clear_data 读取后是否清除 buf 中的数据 true:清除 false:不清除 /// @return 实际读到的字节数(\<=size) static uint16_t _y_ringbuf_read_sub(RINGBUF_st *ringbuf, uint8_t *data, uint16_t size, bool clear_data) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL"); return 0; } if (data == NULL && size != 0) { printf("data pointer is NULL ,but size != 0 is %d", size); return 0; } #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 上锁 _y_ringbuf_lock(ringbuf); #endif uint16_t read_size = 0; // 判断是否有数据可读 if (ringbuf->used_size != 0 && size != 0) { // 判断需要可读的大小 if (ringbuf->used_size >= size) { read_size = size; } else { read_size = ringbuf->used_size; } // 判断头尾位置 确定读取方式 if (ringbuf->tail <= ringbuf->head) { // 尾在头前面 或 在同一位置(全满) uint16_t end_size = ringbuf->length - ringbuf->head; // 尾部可读的空间 if (end_size > read_size) { // 尾部数据足够读 可以顺序读取 memcpy(data, ringbuf->buf + ringbuf->head, read_size); if (clear_data == true) { ringbuf->head += read_size; } } else if (end_size == read_size) { // 尾部数据刚好够读 可以顺序读取 但头位置移到 buf 开头 memcpy(data, ringbuf->buf + ringbuf->head, read_size); if (clear_data == true) { ringbuf->head = 0; } } else { // 尾部数据不够读 需要分段读取 memcpy(data, ringbuf->buf + ringbuf->head, end_size); memcpy(data + end_size, ringbuf->buf, read_size - end_size); if (clear_data == true) { ringbuf->head = read_size - end_size; } } } else { // 尾在头后面 memcpy(data, ringbuf->buf + ringbuf->head, read_size); if (clear_data == true) { ringbuf->head += read_size; } } } // 更新句柄相关状态 if (clear_data == true) { ringbuf->used_size -= read_size; ringbuf->free_size += read_size; } #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 解锁 _y_ringbuf_unlock(ringbuf); #endif //printf("ringbuf read %d byte succeed", read_size); return read_size; } /// ------------------------------------------------------------------------------------------------------------------------------------ /// 公有函数 /// ------------------------------------------------------------------------------------------------------------------------------------ /// @brief 打印 y_ringbuf 版本号 void y_ringbuf_print_version() { printf("y_ringbuf version : V%d.%d.%d", Y_RINGBUF_VERSION_MAJOR, Y_RINGBUF_VERSION_MINOR, Y_RINGBUF_VERSION_PATCH); } /// @brief 获取 ringbuf 中已使用的字节数 /// @param [in] ringbuf ringbuf 句柄指针 /// @return 已使用的字节数 uint16_t y_ringbuf_get_used_size(RINGBUF_st *ringbuf) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL"); return 0; } return ringbuf->used_size; } /// @brief 获取 ringbuf 中剩余可用的字节数 /// @param [in] ringbuf ringbuf 句柄指针 /// @return 剩余可用的字节数 uint16_t y_ringbuf_get_free_size(RINGBUF_st *ringbuf) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL"); return 0; } return ringbuf->free_size; } /// @brief 从 ringbuf 中读取数据后并清除 /// @param [in] ringbuf ringbuf 句柄指针 /// @param [out] data 读到数据存放的地址 /// @param [in] size 想要读取的字节数 /// @return 实际读到的字节数(\<=size) uint16_t y_ringbuf_read_clear(RINGBUF_st *ringbuf, uint8_t *data, uint16_t size) { return _y_ringbuf_read_sub(ringbuf, data, size, true); } /// @brief 从 ringbuf 中读取数据但不清除数据 /// @param [in] ringbuf ringbuf 句柄指针 /// @param [out] data 读到数据存放的地址 /// @param [in] size 想要读取的字节数 /// @return 实际读到的字节数(\<=size) uint16_t y_ringbuf_read_only(RINGBUF_st *ringbuf, uint8_t *data, uint16_t size) { return _y_ringbuf_read_sub(ringbuf, data, size, false); } /// @brief 写入数据到 ringbuf 长度大于空间时立即分配内存 /// @param [in] ringbuf ringbuf 句柄指针 /// @param [in] data 待写入数据指针 /// @param [in] size 待写入数据大小 /// @retval true 成功 /// @retval false 失败 bool y_ringbuf_write_remalloc_memory(RINGBUF_st *ringbuf, uint8_t *data, uint16_t size) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL"); return false; } if (data == NULL && size != 0) { printf("data pointer is NULL ,but size != 0 is %d", size); return false; } #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 上锁 _y_ringbuf_lock(ringbuf); #endif // 判断空闲空间是否满足写入要求 if (ringbuf->free_size < size) { printf("ringbuf free size %d ,but need write size %d", ringbuf->free_size, size); //重新设置内存 //ringbuf->buf = (uint8_t *) heap_caps_malloc(length); // 开辟 ringbuf 所需要的空间 ringbuf->length += ringbuf->length ; ringbuf->free_size += ringbuf->length; ringbuf->buf = (RINGBUF_st *) heap_caps_realloc( ringbuf->buf, ringbuf->length,MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM); if( ringbuf->buf!=NULL) { printf("remalloc ringbuf ok contiune write\r\n"); }else { #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 解锁 _y_ringbuf_unlock(ringbuf); #endif printf("remalloc ringbuf fail not contiune write\r\n"); return false; } //ringbuf = (RINGBUF_st *) heap_caps_malloc(sizeof(RINGBUF_st)); // 开辟 结构体句柄 所需要的空间 //return false; } // 判断头尾位置 确定写入方式 if (ringbuf->tail < ringbuf->head) { // 尾在头前面 可以直接顺序写入 memcpy(ringbuf->buf + ringbuf->tail, data, size); ringbuf->tail += size; } else { // 尾在头后面 或 在同一位置(全空) uint16_t end_size = ringbuf->length - ringbuf->tail; // 尾部剩余可用的空间 if (end_size > size) { // 尾部可用空间足够 可以直接顺序写入 memcpy(ringbuf->buf + ringbuf->tail, data, size); ringbuf->tail += size; } else if (end_size == size) { // 尾部可用空间刚好够 可以直接顺序写入 但尾位置移到 buf 开头 memcpy(ringbuf->buf + ringbuf->tail, data, size); ringbuf->tail = 0; } else { // 尾部可用空间不足 需要分段写入 memcpy(ringbuf->buf + ringbuf->tail, data, end_size); memcpy(ringbuf->buf, data + end_size, size - end_size); ringbuf->tail = size - end_size; } } // 更新句柄相关状态 ringbuf->used_size += size; ringbuf->free_size -= size; #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 解锁 _y_ringbuf_unlock(ringbuf); #endif //printf("ringbuf write %d byte succeed", size); return true; } /// @brief 写入数据到 ringbuf /// @param [in] ringbuf ringbuf 句柄指针 /// @param [in] data 待写入数据指针 /// @param [in] size 待写入数据大小 /// @retval true 成功 /// @retval false 失败 bool y_ringbuf_write(RINGBUF_st *ringbuf, uint8_t *data, uint16_t size) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL"); return false; } if (data == NULL && size != 0) { printf("data pointer is NULL ,but size != 0 is %d", size); return false; } #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 上锁 _y_ringbuf_lock(ringbuf); #endif // 判断空闲空间是否满足写入要求 if (ringbuf->free_size < size) { printf("ringbuf free size %d ,but need write size %d", ringbuf->free_size, size); #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 解锁 _y_ringbuf_unlock(ringbuf); #endif return false; } // 判断头尾位置 确定写入方式 if (ringbuf->tail < ringbuf->head) { // 尾在头前面 可以直接顺序写入 memcpy(ringbuf->buf + ringbuf->tail, data, size); ringbuf->tail += size; } else { // 尾在头后面 或 在同一位置(全空) uint16_t end_size = ringbuf->length - ringbuf->tail; // 尾部剩余可用的空间 if (end_size > size) { // 尾部可用空间足够 可以直接顺序写入 memcpy(ringbuf->buf + ringbuf->tail, data, size); ringbuf->tail += size; } else if (end_size == size) { // 尾部可用空间刚好够 可以直接顺序写入 但尾位置移到 buf 开头 memcpy(ringbuf->buf + ringbuf->tail, data, size); ringbuf->tail = 0; } else { // 尾部可用空间不足 需要分段写入 memcpy(ringbuf->buf + ringbuf->tail, data, end_size); memcpy(ringbuf->buf, data + end_size, size - end_size); ringbuf->tail = size - end_size; } } // 更新句柄相关状态 ringbuf->used_size += size; ringbuf->free_size -= size; #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 解锁 _y_ringbuf_unlock(ringbuf); #endif //printf("ringbuf write %d byte succeed", size); return true; } /// @brief 删除 ringbuf 中指定长度的数据 /// @param [in] ringbuf ringbuf 句柄指针 /// @param [in] size 要删除的数据长度 /// @retval true 成功 /// @retval false 失败 bool y_ringbuf_delete_data(RINGBUF_st *ringbuf, uint16_t size) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL"); return false; } // 判断是否有足够的数据可删 if (ringbuf->used_size < size) { printf("not enough data, need delete %d data,but only used size %d", size, ringbuf->used_size); return false; } #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 上锁 _y_ringbuf_lock(ringbuf); #endif // 判断头尾位置 确定删除方式 if (ringbuf->tail <= ringbuf->head) { // 尾在头前面 或 在同一位置(全满) uint16_t end_size = ringbuf->length - ringbuf->head; // 尾部删除的空间 if (end_size > size) { // 尾部数据足够 可以直接删除 ringbuf->head += size; } else if (end_size == size) { // 尾部数据刚好 可以直接删除 但头位置移到 buf 开头 ringbuf->head = 0; } else { // 尾部数据不够 需要分段删除 ringbuf->head = size - end_size; } } else { // 尾在头后面 可以直接删除 ringbuf->head += size; } // 更新句柄相关状态 ringbuf->used_size -= size; ringbuf->free_size += size; #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 解锁 _y_ringbuf_unlock(ringbuf); #endif printf("ringbuf delete %d byte succeed", size); return true; } /// @brief 判断 ringbuf 是否为满 /// @param [in] ringbuf ringbuf 句柄指针 /// @retval true 成功 /// @retval false 失败 bool y_ringbuf_is_full(RINGBUF_st *ringbuf) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL"); return false; } if (ringbuf->free_size == 0) { return true; } else { return false; } } /// @brief 判断 ringbuf 是否为空 /// @param [in] ringbuf ringbuf 句柄指针 /// @retval true 成功 /// @retval false 失败 bool y_ringbuf_is_empty(RINGBUF_st *ringbuf) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL"); return false; } if (ringbuf->used_size == 0) { return true; } else { return false; } } /// @brief 重置 ringbuf /// @param [in] ringbuf ringbuf 句柄指针 /// @retval true 成功 /// @retval false 失败 bool y_ringbuf_reset(RINGBUF_st *ringbuf) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL, ringbuf reset fail"); return false; } #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 上锁 _y_ringbuf_lock(ringbuf); #endif // 句柄状态初始化 ringbuf->head = 0; // ringbuf 头所在位置 ringbuf->tail = 0; // ringbuf 尾所在位置 ringbuf->used_size = 0; // ringbuf 已使用大小 ringbuf->free_size = ringbuf->length; // ringbuf 空闲大小 #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 解锁 _y_ringbuf_unlock(ringbuf); #endif printf("ringbuf %p reset succeed", ringbuf); return true; } /// @brief 销毁一个 ringbuf /// @param [in] ringbuf ringbuf 句柄指针 /// @retval true 成功 /// @retval false 失败 bool y_ringbuf_destroy(RINGBUF_st *ringbuf) { // 断言 if (ringbuf == NULL) { printf("ringbuf is NULL, no need to delete"); return false; } #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 销毁互斥锁 if (_y_ringbuf_destroy_mutex_lock(ringbuf) == false) { printf("ringbuf destroy mutex lock error, destroy ringbuf fail"); return false; } #endif // 释放内存空间 heap_caps_free(ringbuf->buf); heap_caps_free(ringbuf); printf("ringbuf %p destroy succeed", ringbuf); ringbuf = NULL; return true; } /// @brief 创建一个 ringbuf /// @param [in] length ringbuf 长度 (max 65535) /// @return ringbuf 句柄指针 RINGBUF_st *y_ringbuf_create(uint16_t length) { // 断言 if (length == 0) { printf("ringbuf length must > 0, ringbuf create fail"); return NULL; } // 创建 ringbuf 句柄 RINGBUF_st *tmp_ringbuf = (RINGBUF_st *) heap_caps_malloc(sizeof(RINGBUF_st),MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM); // 开辟 结构体句柄 所需要的空间 if (tmp_ringbuf == NULL) { printf("heap_caps_malloc RINGBUF_st error"); return NULL; } else { memset(tmp_ringbuf, 0, sizeof(RINGBUF_st)); // 清零 } tmp_ringbuf->buf = (uint8_t *) heap_caps_malloc(length,MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM); // 开辟 ringbuf 所需要的空间 if (tmp_ringbuf->buf == NULL) { printf("heap_caps_malloc ringbuf->buf error"); heap_caps_free(tmp_ringbuf); return NULL; } else { memset(tmp_ringbuf->buf, 0, length); // 清零 } // 初始化 ringbuf 句柄 tmp_ringbuf->length = length; tmp_ringbuf->free_size = length; #if Y_RINGBUF_USE_MUTEX_LOCK == 1 // 创建互斥锁 if (_y_ringbuf_create_mutex_lock(tmp_ringbuf) == false) { heap_caps_free(tmp_ringbuf->buf); heap_caps_free(tmp_ringbuf); tmp_ringbuf = NULL; printf("ringbuf create mutex lock error, create ringbuf fail"); return NULL; } #endif printf("ringbuf %p create succeed\n", tmp_ringbuf); return tmp_ringbuf; }