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