【14】、STM32F767——————>内存管理

  1. 简述
    1. 内存管理是指运行时对计算机内存资源的分配和使用的技术
    2. 其目的是如何高效、快速的分配,并且在适当的时候释放和回收内存资源
    3. 内存管理函数只有两个:内存申请malloc(),内存释放free()
  2. 分块式内存管理
    1. 框图
    2. 组成:
      1. 内存池
      2. 内存管理表
      3. 内存池被等分为n块,对应的内存管理表,大小 也为n,内存管理表的每一个项对应内存池的一块内存
      4. 内存管理表项值意义:项值为0,表示对应的内存块未被占用,非0,己占用
      5. 分配方向:顶->底,即首先从末端开始找空内存,初始化时内存表全部清零
    3. 申请原理
      1. 指针p调用malloc函数申请内存时,先判断p要分配的内存块数(m)
      2. 然后从第n项开始,向下查找,直到找到m块连续的空内存块,然后将m个内存管理表项的值都设置为m(非0)
      3. 内存不够,如果没有找到m块空闲内存,则返回null给p,表示分配失败
    4. 释放原理
      1. 指针p调用free函数,先判断p指向内存地址所对应的内存块,找到对应的内存管理表项目
      2. 得到p所占用的内存块数目m,将m个内存管理表项目值都清零,标记释放
    5. 内存池地址范围
      1. 普通内存:起始地址:0x2002 0000,大小:384KB,任何外设都可以访问
      2. DTCM内存:起始地址:0x2000 0000,大小:128KB,CPU和DMA外设访问
      3. 外部SDRAM:起始地址:0xc000 0000,大小:32768KB
    6. 例程
      1. //内存池(32字节对齐)
        __align(64) u8 mem1base[MEM1_MAX_SIZE];													//内部SRAM内存池
        __align(64) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0XC01F4000)));					//外部SDRAM内存池,前面2M给LTDC用了(1280*800*2)
        __align(64) u8 mem3base[MEM3_MAX_SIZE] __attribute__((at(0X20000000)));					//内部DTCM内存池
        //内存管理表
        u32 mem1mapbase[MEM1_ALLOC_TABLE_SIZE];													//内部SRAM内存池MAP
        u32 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0XC01F4000+MEM2_MAX_SIZE)));	//外部SRAM内存池MAP
        u32 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((at(0X20000000+MEM3_MAX_SIZE)));	//内部DTCM内存池MAP
        //内存管理参数	   
        const u32 memtblsize[SRAMBANK]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE,MEM3_ALLOC_TABLE_SIZE};	//内存表大小
        const u32 memblksize[SRAMBANK]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE,MEM3_BLOCK_SIZE};					//内存分块大小
        const u32 memsize[SRAMBANK]={MEM1_MAX_SIZE,MEM2_MAX_SIZE,MEM3_MAX_SIZE};							//内存总大小
        
        //内存管理控制器
        struct _m_mallco_dev mallco_dev=
        {
        	my_mem_init,						//内存初始化
        	my_mem_perused,						//内存使用率
        	mem1base,mem2base,mem3base,			//内存池
        	mem1mapbase,mem2mapbase,mem3mapbase,//内存管理状态表
        	0,0,0,  		 					//内存管理未就绪
        };
        
        //复制内存
        //*des:目的地址
        //*src:源地址
        //n:需要复制的内存长度(字节为单位)
        void mymemcpy(void *des,void *src,u32 n)  
        {  
            u8 *xdes=des;
        	u8 *xsrc=src; 
            while(n--)*xdes++=*xsrc++;  
        }  
        //设置内存
        //*s:内存首地址
        //c :要设置的值
        //count:需要设置的内存大小(字节为单位)
        void mymemset(void *s,u8 c,u32 count)  
        {  
            u8 *xs = s;  
            while(count--)*xs++=c;  
        }	
        //内存管理初始化  
        //memx:所属内存块
        void my_mem_init(u8 memx)  
        {  
            mymemset(mallco_dev.memmap[memx],0,memtblsize[memx]*4);	//内存状态表数据清零  
         	mallco_dev.memrdy[memx]=1;								//内存管理初始化OK  
        }  
        //获取内存使用率
        //memx:所属内存块
        //返回值:使用率(扩大了10倍,0~1000,代表0.0%~100.0%)
        u16 my_mem_perused(u8 memx)  
        {  
            u32 used=0;  
            u32 i;  
            for(i=0;i<memtblsize[memx];i++)  
            {  
                if(mallco_dev.memmap[memx][i])used++; 
            } 
            return (used*1000)/(memtblsize[memx]);  
        }  
        //内存分配(内部调用)
        //memx:所属内存块
        //size:要分配的内存大小(字节)
        //返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址 
        u32 my_mem_malloc(u8 memx,u32 size)  
        {  
            signed long offset=0;  
            u32 nmemb;	//需要的内存块数  
        	u32 cmemb=0;//连续空内存块数
            u32 i;  
            if(!mallco_dev.memrdy[memx])mallco_dev.init(memx);//未初始化,先执行初始化 
            if(size==0)return 0XFFFFFFFF;//不需要分配
            nmemb=size/memblksize[memx];  	//获取需要分配的连续内存块数
            if(size%memblksize[memx])nmemb++;  
            for(offset=memtblsize[memx]-1;offset>=0;offset--)//搜索整个内存控制区  
            {     
        		if(!mallco_dev.memmap[memx][offset])cmemb++;//连续空内存块数增加
        		else cmemb=0;								//连续内存块清零
        		if(cmemb==nmemb)							//找到了连续nmemb个空内存块
        		{
                    for(i=0;i<nmemb;i++)  					//标注内存块非空 
                    {  
                        mallco_dev.memmap[memx][offset+i]=nmemb;  
                    }  
                    return (offset*memblksize[memx]);//返回偏移地址  
        		}
            }  
            return 0XFFFFFFFF;//未找到符合分配条件的内存块  
        }  
        //释放内存(内部调用) 
        //memx:所属内存块
        //offset:内存地址偏移
        //返回值:0,释放成功;1,释放失败;  
        u8 my_mem_free(u8 memx,u32 offset)  
        {  
            int i;  
            if(!mallco_dev.memrdy[memx])//未初始化,先执行初始化
        	{
        		mallco_dev.init(memx);    
                return 1;//未初始化  
            }  
            if(offset<memsize[memx])//偏移在内存池内. 
            {  
                int index=offset/memblksize[memx];			//偏移所在内存块号码  
                int nmemb=mallco_dev.memmap[memx][index];	//内存块数量
                for(i=0;i<nmemb;i++)  						//内存块清零
                {  
                    mallco_dev.memmap[memx][index+i]=0;  
                }  
                return 0;  
            }else return 2;//偏移超区了.  
        }  
        //释放内存(外部调用) 
        //memx:所属内存块
        //ptr:内存首地址 
        void myfree(u8 memx,void *ptr)  
        {  
        	u32 offset;   
        	if(ptr==NULL)return;//地址为0.  
         	offset=(u32)ptr-(u32)mallco_dev.membase[memx];     
            my_mem_free(memx,offset);	//释放内存      
        }  
        //分配内存(外部调用)
        //memx:所属内存块
        //size:内存大小(字节)
        //返回值:分配到的内存首地址.
        void *mymalloc(u8 memx,u32 size)  
        {  
            u32 offset;   
        	offset=my_mem_malloc(memx,size);  	   	 	   
            if(offset==0XFFFFFFFF)return NULL;  
            else return (void*)((u32)mallco_dev.membase[memx]+offset);  
        }  
        //重新分配内存(外部调用)
        //memx:所属内存块
        //*ptr:旧内存首地址
        //size:要分配的内存大小(字节)
        //返回值:新分配到的内存首地址.
        void *myrealloc(u8 memx,void *ptr,u32 size)  
        {  
            u32 offset;    
            offset=my_mem_malloc(memx,size);   	
            if(offset==0XFFFFFFFF)return NULL;     
            else  
            {  									   
        	    mymemcpy((void*)((u32)mallco_dev.membase[memx]+offset),ptr,size);	//拷贝旧内存内容到新内存   
                myfree(memx,ptr);  											  		//释放旧内存
                return (void*)((u32)mallco_dev.membase[memx]+offset);  				//返回新内存首地址
            }  
        }
        

         

      2. 参考原子
    7. 下载验证
    8. 总结
    9. 参考资料
      1. 正点原子:STM32F7 开发指南(HAL 库版)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值