从零开始学ESP32:(四)ESP32/freeRTOS 实现一个内存池操作

零开始学ESP32:个人笔记记录:

芯片型号: ESP32
网络环境支持:LWIP
IDF.PY-SDK: ESP-IDF v4.3
芯片功能: freeRTOS系统

声明: 当前内存池参考 Linux / rttthreadOS 两个套系统,自己写成的。

内存池的创建:
头文件:

#include <stdint.h>
内存池主体结构


#define MP_ALIGN_SIZE 4 
#define MP_ALIGN(size, align)               (((size) + (align) - 1) & ~((align) - 1))

typedef struct ST_MEMORY_POOL__ { 
    
    void*     startA_address;    // 起始地址
    size_t    size ;             // 总大小
    size_t    block_size;        // 块大小
    uint8_t*  block_lisk;        // 块链表
    size_t    block_total_count; // 块数量   
    size_t    block_free_count;  // 空闲块数量

}st_memoryPool , *st_mp_t;


/****************************************************************************
 * 函数名称:T_mp_create
 * 输入值:  
 * 输出值:
 * 返回值
 * 其他: 
 * 说明: 内存池的创建
 * */
void* T_mp_create(size_t block_count , size_t  block_size)
{
    uint8_t* block_chr      = NULL;
    register size_t  offset = 0; //寄存器变量

    st_memoryPool* mp = (st_memoryPool * )pvPortMalloc ( sizeof( st_memoryPool ) ); 
    if( mp == NULL )
    {
        return NULL;
    }
    block_size     = MP_ALIGN( block_size ,  MP_ALIGN_SIZE ); //内存4字节对齐
    mp->block_size = block_size;
    mp->size       =  (block_size + sizeof(uint8_t * ) ) * block_count ;

    mp->startA_address = pvPortMalloc(  mp->size  );
    if( !mp->startA_address )
    {
        goto Err_startAdd;
    }

    mp->block_total_count = block_count;
    mp->block_free_count  = block_count;

    block_chr = mp->startA_address ; 
    for(offset = 0 ; offset < mp->block_total_count ; offset ++ )
    {
        *( uint8_t **)( block_chr  + offset *  (block_size + sizeof(uint8_t *)))
        = block_chr + ( offset + 1) * ( block_size + sizeof( uint8_t *) ); 
    }

    *( uint8_t **)( block_chr  + (offset -1) *  (block_size + sizeof(uint8_t *))) = NULL;

    mp->block_lisk = block_chr;

    return mp;

Err_startAdd: vPortFree( mp );
    return NULL;
}

在内存池里面申请内存

/****************************************************************************
 * 函数名称:T_mp_malloc
 * 输入值:  
 * 输出值:
 * 返回值
 * 其他:每次操作内存池分配空间的操作, 需要打断时间 ~= 3400( us ) ( 微秒 )    
 * 说明: 内存池的申请
 * 每次申请必须进行返回,不论当前内存池是否还存在对象
 * 
 * 
 * */
void* T_mp_malloc( st_memoryPool* mp )
{
    uint8_t* block_chr = NULL;
    vTaskSuspendAll();                  //将任务管理器挂起来
    if( mp->block_free_count == 0 ) 
    { 
        xTaskResumeAll();
        return NULL;
    }
    mp->block_free_count --;
    block_chr = mp->block_lisk; 
    assert( block_chr != NULL );
    mp->block_lisk = *(uint8_t **)block_chr;
    *( uint8_t **)block_chr = (uint8_t *)mp;
    xTaskResumeAll();                   //开启任务管理器 
    return ( uint8_t * )( block_chr + sizeof( uint8_t *) );
}

// 释放归还内存块回给内存池里面

/****************************************************************************
 * 函数名称:T_mp_free
 * 输入值:  
 * 输出值:
 * 返回值
 * 其他:  
 * 说明: 内存池的释放
 * */
void T_mp_free( void * block )
{
    uint8_t** block_str = NULL;
    st_memoryPool* mp   = NULL;
    vTaskSuspendAll();  
    block_str      = (uint8_t **)( (uint8_t*) block - (sizeof( uint8_t * )));
    mp             = (st_memoryPool *)*block_str;
    *block_str     = mp->block_lisk;
    mp->block_lisk = ( uint8_t* )block_str; 
    mp->block_free_count ++;
    xTaskResumeAll();                   //开启任务管理器 
}

//释放整个内存块

/****************************************************************************
 * 函数名称:T_mp_free
 * 输入值:  
 * 输出值:
 * 返回值
 * 其他:  
 * 说明: 内存池的释放
 * */
void T_mp_free( void * block )
{
    uint8_t** block_str = NULL;
    st_memoryPool* mp   = NULL;
    vTaskSuspendAll();  
    block_str      = (uint8_t **)( (uint8_t*) block - (sizeof( uint8_t * )));
    mp             = (st_memoryPool *)*block_str;
    *block_str     = mp->block_lisk;
    mp->block_lisk = ( uint8_t* )block_str; 
    mp->block_free_count ++;
    xTaskResumeAll();                   //开启任务管理器 
}

在当前这个版本内存池里面存在尚未解决的问题,在使用时候必须要考虑到:

一、当前任务向内存池申请内存是(T_mp_malloc),没有实现一个超时等待,或者阻塞等待直至有空闲内存块
当前内存池空闲内存为零时, 应该将当前任务挂起并且放到一个任务里面,等待内存到来。

二、在T_mp_malloc 函数里面使用到vTaskSuspendAll()和 xTaskResumeAll(),FREERTOS内存API ,尚未明确会不会
存在一些危险操作和与之相关的问题

三、当多任务都在同时等待当前内存池时候而被第三方任务将整个内存池删除,应该要实现一个操作, 唤醒当前所有等待的任务,并且告
知当前内存池一已经被释放。

要是碰巧看到这边博文的工程师,并且有想法或者是对freeRTOS比较熟系的,希望您路过的时候不设赐教。
当前用上你的想法或者对应的方案,博文也会明确表示当您的身份和对应的贡献。
感谢。

关注微信公众号 一起学习 ( 技术Code城 )

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值