OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2112|回复: 3

[分享]内存管理代码429开发板,可用于其他系统

[复制链接]

76

主题

88

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
264
金钱
264
注册时间
2017-10-26
在线时间
12 小时
发表于 2017-11-11 11:06:18 | 显示全部楼层 |阅读模式
本帖最后由 mrmzyking 于 2017-11-11 11:17 编辑

头文件
#ifndef __MEM_H__
#define __MEM_H__
#include "stdlib.h"
#include "stdio.h"
#include "stm32f4xx_hal.h"
#define Mem_Total_Size (32*1024*1024L) //需要用户填写
#define Mem_Block_Size (2*64*1024L)    //需要用户填写
#define Mem_Start_Addr (0xC0000000L)   //需要用户填写
#define Mem_Manage_Size (sizeof(struct Mem_Info) * Mem_Block_Num)
#define Mem_Block_Num (Mem_Total_Size/(sizeof(struct Mem_Info)+ Mem_Block_Size ))
struct Memery_Info
{
        unsigned long TotalSizes ;
        unsigned long TotalBlock ;
        unsigned long Bytes_Block ;
        unsigned long FreeSizeBytes ;
        unsigned long FreeBlock ;
        unsigned int Mem_Start ;
        unsigned int Mem_End ;
} ;
struct Mem_Info
{
        unsigned char Flag ; //0:free;1:used
        unsigned long BlkNum ;
        unsigned int Start_Addr ;
        unsigned int End_Addr ;
        unsigned char *Buff ;
} ;


extern unsigned char Init_Memery( void ) ;
extern void *Get_Mem( unsigned long Size) ;
extern unsigned char Free_Mem( void *p ) ;
#endif

实现文件

#include "mem.h"


struct Memery_Info Memry ;
struct Mem_Info Mem[Mem_Block_Num] __attribute__ ((at(Mem_Start_Addr)));;
unsigned char Mem_Buff[Mem_Block_Num][Mem_Block_Size] __attribute__ ((at(Mem_Start_Addr + Mem_Manage_Size)));
unsigned char Init_Memery( void )
{
        unsigned long i ;
        volatile unsigned int tmpreg ;
        
                tmpreg = Mem_Manage_Size + Mem_Block_Num * Mem_Block_Size ;
                if( tmpreg > Mem_Total_Size )
                {
                        tmpreg = Mem_Total_Size/(sizeof(struct Mem_Info)+Mem_Block_Size) ;                        
                        return 0 ;
                }
        Memry.TotalSizes = Mem_Total_Size ;
        Memry.TotalBlock = Mem_Block_Num ;
        Memry.Bytes_Block = Mem_Block_Size ;
        Memry.FreeSizeBytes = Mem_Total_Size ;
        Memry.Mem_Start = Mem_Start_Addr ;
        Memry.FreeBlock = Mem_Block_Num ;
        Memry.Mem_End = Mem_Start_Addr + Mem_Total_Size ;
        for(i = 0 ; i < Mem_Block_Num ; i++ )
        {
                Mem.Flag = 0 ;
                Mem.BlkNum = 0 ;
                Mem.Start_Addr = Memry.Mem_Start + i * Mem_Block_Size ;
                Mem.End_Addr = Memry.Mem_Start + ( i + 1 ) * Mem_Block_Size ;
                Mem.Buff = ( unsigned char *)&Mem_Buff[0] ;
        }
        return 1 ;
}
void *Get_Mem( unsigned long Size)
{
        volatile unsigned long i ,j ;
        volatile unsigned long NeedBlk ;
        volatile unsigned long Blktmp ;
        volatile unsigned char Flag ;
        if(Size > Memry.FreeSizeBytes)
        {
                return NULL ;
        }
        NeedBlk = ( unsigned long )( Size / Mem_Block_Size ) ;
        if( ( Size % Mem_Block_Size ) != 0 )
        {
                NeedBlk++ ;
        }
        if( NeedBlk > Memry.FreeBlock )
        {
                return NULL ;
        }
        Blktmp = 0 ;
        Flag = 0 ;
        for( i = 0 ; i < Mem_Block_Num ; i++ )
        {
                if( Mem.Flag == 0 )
                {
                        for( j = 0 ; j < NeedBlk ; j++ )
                        {
                                if( Mem[ i + j ].Flag == 0  )
                                {
                                        Blktmp++ ;
                                        if( Blktmp == NeedBlk )
                                        {
                                                Flag = 1 ;
                                                break ;
                                        }
                                }
                                else
                                {
                                        break ;
                                }
                        }
                        
                }
                if( Flag == 1 )
                {
                        break ;
                }
        }
        if( Flag == 1 )
        {
                for( j = 0 ; j < NeedBlk ; j++ )
                {
                        Mem[i+j].Flag = 1 ;                        
                }
                Mem.BlkNum = NeedBlk ;               
                Memry.FreeSizeBytes = Memry.TotalSizes - Size ;
                Memry.FreeBlock = Memry.FreeBlock - NeedBlk ;
                return (void *)Mem.Buff ;
        }
        else
        {
                return NULL ;
        }
}
unsigned char Free_Mem( void *p )
{
        unsigned char *q ;
        unsigned long i ;
        unsigned long j ;
        unsigned long tmpreg ;
        if( p==NULL )
        {
                return 0 ;
        }
        q = ( unsigned char *)p ;
        for( i = 0 ; i < Mem_Block_Num ; i++ )
        {
                if( Mem.Start_Addr == ( unsigned int )( q ) )
                {
                        if( Mem.Flag == 1 )
                        {
                                if( Mem.BlkNum == 0 )
                                {
                                        Mem.Flag = 0 ;
                                        Memry.FreeBlock++ ;
                                }
                                else
                                {
                                        tmpreg = Mem.BlkNum ;
                                        for( j = 0 ; j < tmpreg ; j++ )
                                        {
                                                Mem[i+j].Flag = 0 ;
                                                Mem[i+j].BlkNum = 0 ;
                                                Memry.FreeBlock++ ;
                                        }
                                        break ;
                                }
                        }
                        else
                        {
                                return 0 ;
                        }
                }               
        }
        p = (unsigned char *)0 ;
        return 1 ;
}


请大家批评指正
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

558

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
164817
金钱
164817
注册时间
2010-12-1
在线时间
2098 小时
发表于 2017-11-11 11:35:40 | 显示全部楼层
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

76

主题

88

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
264
金钱
264
注册时间
2017-10-26
在线时间
12 小时
 楼主| 发表于 2017-11-11 11:42:53 | 显示全部楼层
本帖最后由 mrmzyking 于 2017-11-11 11:53 编辑

自己写的,测试了一段时间,还不错!用户只需要修改三个参数就可以实现移植:
#define Mem_Total_Size (32*1024*1024L) //需要用户填写
#define Mem_Block_Size (1*64*1024L)    //需要用户填写
#define Mem_Start_Addr (0xC0000000L)   //需要用户填写

内存管理的自身的相关信息都放在了外部内存中,并没有占用MCU内部的RAM,除了一个struct Memery_Info结构体是放在MCU的RAM中,这种方式可以计算内存申请的利用率等等,比较方便,扩展功能就没有做太多了,项目赶进度。以后等有事件了再弄!

内存管理使用的是区块的方式进行管理,用户申请过程中是连续申请区块的方式进行的。
Mem_Total_Size :表示当前内存的最大容量,按照字节计算
Mem_Block_Size :表示用户每个区块的大小
Mem_Start_Addr :表示该扩展内存的首字节地址空间

用户只需要修改这三个参数即可,其余的都扔给程序自己实现。写得比较简单,很初略。有个缺点就是如果你的区块设置的太小了,内存管理struct Mem_Info结构数组就会很多,自己可以在原子提供的429开发板上进行测一下,我反正是测试了,还可以吧,运行还算稳定。后续把其他的文件补齐。

这种类型的内存管理有很大的应用缺陷:
就是如果频繁的进行一个大内存申请,释放后,有进行小内存的申请,如果在内存不足够大的情况下,会造成内存碎片。当然这样应用场景的时候,大家要注意一下,等有时间了弄一个碎片处理程序出来弥补一下这个内存管理的缺陷。
回复 支持 反对

使用道具 举报

25

主题

161

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
269
金钱
269
注册时间
2017-7-17
在线时间
149 小时
发表于 2017-11-12 11:20:48 | 显示全部楼层
这个必须顶  
不忘初心,方得始终!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-3-29 06:42

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表