零开始学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城 )