123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656 |
- /// ------------------------------------------------------------------------------------------------------------------------------------
- ///
- /// 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;
- }
|