嵌入式--内存池

嵌入式–内存池

直接上代码,自己体会。嵌入式设备,一般keil提供的堆很小,一般都不使用。使用内存池,自己可以调节内存大小。

头文件 malloc.h

#ifndef __MALLOC_H
#define __MALLOC_H


#include <stdint.h>


#ifndef NULL
#define NULL (0)
#endif


//内存参数设定.
#define MEM_BLOCK_SIZE			32  	  						//内存块大小为32字节
#define MEM_MAX_SIZE			1*1024  						//最大管理内存 
#define MEM_ALLOC_TABLE_SIZE	MEM_MAX_SIZE/MEM_BLOCK_SIZE 	//内存表大小


//内存管理控制器
struct _m_mallco_dev
{
	void (*init)(void);				    //初始化
    uint8_t (*perused)(void);		  	//内存使用率
    uint8_t *membase;					//内存池
    uint16_t *memmap; 					//内存管理状态表
   uint8_t  memrdy; 					//内存管理是否就绪
};

extern struct _m_mallco_dev mallco_dev;	//在mallco.c里面定义

void mymemset(void *s, uint8_t c, uint32_t count);	    //设置内存
void mymemcpy(void *des, void *src, uint32_t n);        //复制内存
void mem_init(void);					                //内存管理初始化函数(外/内部调用)
uint32_t mem_malloc(uint32_t size);		 		        //内存分配(内部调用)
uint8_t mem_free(uint32_t offset);		 		        //内存释放(内部调用)
uint8_t mem_perused(void);					            //得内存使用率(外/内部调用)


//用户调用函数
void myfree(void *ptr);  				//内存释放(外部调用)
void *mymalloc(uint32_t size);				//内存分配(外部调用)
void *myrealloc(void *ptr, uint32_t size);	//重新分配内存(外部调用)


#endif

源文件 malloc.c

#include "malloc.h"

//内存池(4字节对齐)
__align(4) uint8_t membase[MEM_MAX_SIZE];			//SRAM内存池
//内存管理表
uint16_t memmapbase[MEM_ALLOC_TABLE_SIZE];			//SRAM内存池MAP
//内存管理参数
const uint32_t memtblsize=MEM_ALLOC_TABLE_SIZE;		//内存表大小
const uint32_t memblksize=MEM_BLOCK_SIZE;			//内存分块大小
const uint32_t memsize=MEM_MAX_SIZE;			    //内存总大小


//内存管理控制器
struct _m_mallco_dev mallco_dev=
{
    mem_init,			//内存初始化
    mem_perused,		//内存使用率
    membase,			//内存池
    memmapbase,			//内存管理状态表
    0,  				//内存管理未就绪
};

//复制内存
//*des:目的地址
//*src:源地址
//n:需要复制的内存长度(字节为单位)
void mymemcpy(void *des,void *src, uint32_t n)
{
    uint8_t *xdes=des;
    uint8_t *xsrc=src;
    while(n--)*xdes++=*xsrc++;
}

//设置内存
//*s:内存首地址
//c :要设置的值
//count:需要设置的内存大小(字节为单位)
void mymemset(void *s, uint8_t c, uint32_t count)
{
    uint8_t *xs = s;
    while(count--)*xs++=c;
}

//内存管理初始化
void mem_init(void)
{
    //内存状态表数据清零
    mymemset(mallco_dev.memmap, 0,memtblsize*2);
    //内存池所有数据清零
    mymemset(mallco_dev.membase, 0,memsize);	
    //内存管理初始化OK
    mallco_dev.memrdy=1;						
}

//获取内存使用率
//返回值:使用率(0~100)
uint8_t mem_perused(void)
{
    uint32_t used=0;
    uint32_t i;
    for(i=0; i<memtblsize; i++)
    {
        if(mallco_dev.memmap[i])used++;
    }
    return (used*100)/(memtblsize);
}

//内存分配(内部调用)
//memx:所属内存块
//size:要分配的内存大小(字节)
//返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
uint32_t mem_malloc(uint32_t size)
{
    signed long offset=0;
    uint16_t nmemb;	//需要的内存块数
    uint16_t cmemb=0;//连续空内存块数
    uint32_t i;
    if(!mallco_dev.memrdy)
    {
        //未初始化,先执行初始化
        mallco_dev.init();	
    }
    
    //不需要分配
    if(size==0)
        return 0XFFFFFFFF;	
    //获取需要分配的连续内存块数
    nmemb=size/memblksize;  					
    if(size%memblksize)
    {
        nmemb++;
    }
    //搜索整个内存控制区
    for(offset=memtblsize-1; offset>=0; offset--)	
    {
        if(!mallco_dev.memmap[offset])
        {
            //连续空内存块数增加
            cmemb++;	
        }
        else 
        {
            //连续内存块清零
            cmemb=0;							
        }
        //找到了连续nmemb个空内存块
        if(cmemb==nmemb)						
        {
            //标注内存块非空
            for(i=0; i<nmemb; i++)  				
            {
                mallco_dev.memmap[offset+i]=nmemb;
            }
            //返回偏移地址
            return (offset*memblksize);			
        }
    }
    //未找到符合分配条件的内存块
    return 0XFFFFFFFF;
}

//释放内存(内部调用)
//offset:内存地址偏移
//返回值:0,释放成功;1,释放失败;
uint8_t mem_free(uint32_t offset)
{
    int i;
    if(!mallco_dev.memrdy)//未初始化,先执行初始化
    {
        mallco_dev.init();
        return 1;//未初始化
    }
    //偏移在内存池内.
    if(offset<memsize)
    {
        //偏移所在内存块号码
        int index=offset/memblksize;	
        //内存块数量
        int nmemb=mallco_dev.memmap[index];	
        //内存块清零
        for(i=0; i<nmemb; i++)  				
        {
            mallco_dev.memmap[index+i]=0;
        }
        return 0;
    }
    else
    {
        //偏移超区了.
        return 2;
    }
}

//释放内存(外部调用)
//ptr:内存首地址
void myfree(void *ptr)
{
    uint32_t offset;
    if(ptr==NULL)
    {
        return;//地址为0.
    }
    offset=(uint32_t)ptr-(uint32_t)mallco_dev.membase;
    mem_free(offset);
}

//分配内存(外部调用)
//size:内存大小(字节)
//返回值:分配到的内存首地址.
void *mymalloc(uint32_t size)
{
    uint32_t offset;
    offset=mem_malloc(size);
    if(offset==0XFFFFFFFF)return NULL;
    else return (void*)((uint32_t)mallco_dev.membase+offset);
}

//重新分配内存(外部调用)
//*ptr:旧内存首地址
//size:要分配的内存大小(字节)
//返回值:新分配到的内存首地址.
void *myrealloc(void *ptr,uint32_t size)
{
    uint32_t offset;
    offset = mem_malloc(size);
    if(offset==0XFFFFFFFF)
    {
        return NULL;
    }
    else
    {
        //拷贝旧内存内容到新内存
        mymemcpy((void*)((uint32_t)mallco_dev.membase+offset),ptr,size);
        //释放旧内存
        myfree(ptr);  
        //返回新内存首地址
        return (void*)((uint32_t)mallco_dev.membase+offset);  			
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值