OpenEdv-开源电子网

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

【ALIENTEK 战舰STM32开发板例程系列连载+教学】第四十三章 内存管理实验

[复制链接]

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-4-3 22:57:55 | 显示全部楼层 |阅读模式
 

第四十三章 内存管理实验

上一节,我们学会了使用STM32驱动外部SRAM,以扩展STM32的内存,加上STM32本身自带的64K字节内存,我们可供使用的内存还是比较多的。如果我们所用的内存都像上一节的testsram那样,定义一个数组来使用,显然不是一个好办法。

本章,我们将学习内存管理,实现对内存的动态管理。本章分为如下几个部分:

43.1 内存管理简介

43.2 硬件设计

43.3 软件设计

43.4 下载验证

43.1 内存管理简介

内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。内存管理的实现方法有很多种,他们其实最终都是要实现2个函数:mallocfreemalloc函数用于内存申请,free函数用于内存释放。

本章,我们介绍一种比较简单的办法来实现:分块式内存管理。下面我们介绍一下该方法的实现原理,如图43.1.1所示:


43.1.1 分块式内存管理原理

       从上图可以看出,分块式内存管理由内存池和内存管理表两部分组成。内存池被等分为n块,对应的内存管理表,大小也为n,内存管理表的每一个项对应内存池的一块内存。

       内存管理表的项值代表的意义为:当该项值为0的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。比如某项值为10,那么说明包括本项对应的内存块在内,总共分配了10个内存块给外部的某个指针。

内寸分配方向如图所示,是从顶à底的分配方向。即首先从最末端开始找空内存。当内存管理刚初始化的时候,内存表全部清零,表示没有任何内存块被占用。

分配原理

当指针p调用malloc申请内存的时候,先判断p要分配的内存块数(m),然后从第n项开始,向下查找,直到找到m块连续的空内存块(即对应内存管理表项为0),然后将这m个内存管理表项的值都设置为m(标记被占用),最后,把最后的这个空内存块的地址返回指针p,完成一次分配。注意,如果当内存不够的时候(找到最后也没找到连续的m块空闲内存),则返回NULLp,表示分配失败。

释放原理

p申请的内存用完,需要释放的时候,调用free函数实现。free函数先判断p指向的内存地址所对应的内存块,然后找到对应的内存管理表项目,得到p所占用的内存块数目m(内存管理表项目的值就是所分配内存块的数目),将这m个内存管理表项目的值都清零,标记释放,完成一次内存释放。

关于分块式内存管理的原理,我们就介绍到这里。

 

43.2 硬件设计

本章实验功能简介:开机后,显示提示信息,等待外部输入。KEY0用于申请内存,每次申请2K字节内存。KEY1用于写数据到申请到的内存里面。KEY2用于释放内存。WK_UP用于切换操作内存区(内部内存/外部内存)。DS0用于指示程序运行状态。本章我们还可以通过USMART调试,测试内存管理函数。

本实验用到的硬件资源有:

1)  指示灯DS0

2)  四个按键

3)  串口

4)  TFTLCD模块

5)  IS62WV51216

这些我们都已经介绍过,接下来我们开始软件设计。

43.3 软件设计

本章,我们将内存管理部分单独做一个分组,在工程目录下新建一个MALLOC的文件夹,然后新建malloc.cmalloc.h两个文件,将他们保存在MALLOC文件夹下。

MDK新建一个MALLOC的组,然后将malloc.c文件加入到该组,并将MALLOC文件夹添加到头文件包含路径。

       打开malloc.c文件,输入如下代码:

#include "malloc.h"         

//内存池(4字节对齐)

__align(4) u8 mem1base[MEM1_MAX_SIZE]; //内部SRAM内存池                                 

__align(4) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000)));

//外部SRAM内存池

//内存管理表

u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE];  //内部SRAM内存池MAP                        u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000+

MEM2_MAX_SIZE))); //外部SRAM内存池MAP

//内存管理参数       

const u32 memtblsize[2]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE};        //内存表大小

const u32 memblksize[2]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE};                                //内存分块大小

const u32 memsize[2]={MEM1_MAX_SIZE,MEM2_MAX_SIZE};                                            //内存总大小

//内存管理控制器

struct _m_mallco_dev mallco_dev=

{

       mem_init,                                   //内存初始化

       mem_perused,                             //内存使用率

       mem1base,mem2base,                  //内存池

       mem1mapbase,mem2mapbase,      //内存管理状态表

       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 mem_init(u8 memx) 

    mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);//内存状态表数据清零 

       mymemset(mallco_dev.membase[memx], 0,memsize[memx]);   //内存池所有数据清零 

       mallco_dev.memrdy[memx]=1;                                              //内存管理初始化OK 

//获取内存使用率

//memx:所属内存块

//返回值:使用率(0~100)

u8 mem_perused(u8 memx) 

    u32 used=0; 

    u32 i; 

    for(i=0;i<memtblsize[memx];i++) if(mallco_dev.memmap[memx])used++;

    return (used*100)/(memtblsize[memx]); 

//内存分配(内部调用)

//memx:所属内存块

//size:要分配的内存大小(字节)

//返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址

u32 mem_malloc(u8 memx,u32 size) 

    signed long offset=0; 

    u16 nmemb;   //需要的内存块数 

       u16 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 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]; 

    mem_free(memx,offset);//释放内存    

//分配内存(外部调用)

//memx:所属内存块

//size:内存大小(字节)

//返回值:分配到的内存首地址.

void *mymalloc(u8 memx,u32 size) 

    u32 offset;                                                                  

       offset=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=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); //返回新内存首地址

    } 

}

       这里,我们通过内存管理控制器mallco_dev结构体(mallco_dev结构体见malloc.h),实现对两个内存池的管理控制。一个是外部内存池,定义为:

       __align(4) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000)));                         另一个是内部内存池,定义为:

__align(4) u8 mem1base[MEM1_MAX_SIZE];  

       其中,MEM1_MAX_SIZEMEM2_MAX_SIZE为在malloc.h里面定义的内存池大小,外部内存池指定地址为0X68000000,也就是从外部SRAM的首地址开始的,内部内存则由编译器自动分配。__align(4)定义内存池为4字节对齐,这个非常重要!如果不加这个限制,在某些情况下(比如分配内存给结构体指针),可能出现错误,所以一定要加上这个。

此部分代码的核心函数为:mem_mallocmem_free,分别用于内存申请和内存释放。思路就是我们在43.1接所介绍的那样分配和释放内存,不过这两个函数只是内部调用,外部调用我们使用的是mymallocmyfree两个函数。其他函数我们就不多介绍了,保存malloc.c,然后,打开malloc.h,在该文件里面输入如下代码:

#ifndef __MALLOC_H

#define __MALLOC_H

typedef unsigned long  u32;

typedef unsigned short u16;

typedef unsigned char  u8;    

#ifndef NULL

#define NULL 0

#endif

#define SRAMIN   0     //内部内存池

#define SRAMEX  1    //外部内存池

//mem1内存参数设定.mem1完全处于内部SRAM里面

#define MEM1_BLOCK_SIZE                   32         //内存块大小为32字节

#define MEM1_MAX_SIZE                40*1024       //最大管理内存 40K

#define MEM1_ALLOC_TABLE_SIZE       MEM1_MAX_SIZE/MEM1_BLOCK_SIZE      

//内存表大小

//mem2内存参数设定.mem2的内存池处于外部SRAM里面,其他的处于内部SRAM里面

#define MEM2_BLOCK_SIZE                   32         //内存块大小为32字节

#define MEM2_MAX_SIZE                200*1024      //最大管理内存200K

#define MEM2_ALLOC_TABLE_SIZE       MEM2_MAX_SIZE/MEM2_BLOCK_SIZE      

//内存表大小

//内存管理控制器

struct _m_mallco_dev

{

       void (*init)(u8);                                 //初始化

       u8 (*perused)(u8);                          //内存使用率

       u8   *membase[2];                             //内存池 管理2个区域的内存

       u16 *memmap[2];                                    //内存管理状态表

       u8  memrdy[2];                               //内存管理是否就绪

};

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

void mymemset(void *s,u8 c,u32 count);            //设置内存

void mymemcpy(void *des,void *src,u32 n)       ;      //复制内存    

void mem_init(u8 memx);                                 //内存管理初始化函数(/内部调用)

u32 mem_malloc(u8 memx,u32 size);                //内存分配(内部调用)

u8 mem_free(u8 memx,u32 offset);                   //内存释放(内部调用)

u8 mem_perused(u8 memx);                             //获得内存使用率(/内部调用)

////////////////////////////////////////////////////////////////////////////////

//用户调用函数

void myfree(u8 memx,void *ptr);                     //内存释放(外部调用)

void *mymalloc(u8 memx,u32 size);                  //内存分配(外部调用)

void *myrealloc(u8 memx,void *ptr,u32 size);    //重新分配内存(外部调用)

#endif

这部分代码,定义了很多关键数据,比如内存块大小的定义:MEM1_BLOCK_SIZEMEM2_BLOCK_SIZE,都是32字节。内存池总大小,内部为40K,外部为200K(最大支持到近1M字节,不过为了方便演示,这里只管理200K内存)。MEM1_ALLOC_TABLE_SIZEMEM2_ALLOC_TABLE_SIZE,则分别代表内存池12的内存管理表大小。

从这里可以看出,如果内存分块越小,那么内存管理表就越大,当分块为2字节1个块的时候,内存管理表就和内存池一样大了(管理表的每项都是u16类型)。显然是不合适的,我们这里取32字节,比例为1:16,内存管理表相对就比较小了。

其他就不多说了,大家自行看代码理解就好。保存此部分代码。最后,打开test.c文件,修改代码如下:

int main(void)

{           

       u8 key; u8 i=0; u8 *p=0;       u8 *tp=0;             

       u8 paddr[18];                       //存放P Addr:+p地址的ASCII

       u8 sramx=0;                        //默认为内部sram

      Stm32_Clock_Init(9);           //系统时钟设置

       uart_init(72,9600);             //串口初始化为9600

       delay_init(72);                         //延时初始化

       LED_Init();                        //初始化与LED连接的硬件接口

       LCD_Init();                       //初始化LCD

       usmart_dev.init(72);             //初始化USMART       

      KEY_Init();                         //按键初始化 

      FSMC_SRAM_Init();           //初始化外部SRAM

       mem_init(SRAMIN);            //初始化内部内存池

       mem_init(SRAMEX);           //初始化外部内存池

      POINT_COLOR=RED;//设置字体为红色

       LCD_ShowString(60,50,200,16,16,"WarShip STM32");   

       LCD_ShowString(60,70,200,16,16,"MALLOC TEST");    

       LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");

       LCD_ShowString(60,110,200,16,16,"2012/9/16"); 

       LCD_ShowString(60,130,200,16,16,"KEY0:Malloc  KEY2:Free");

       LCD_ShowString(60,150,200,16,16,"KEY_UP:SRAMx KEY1:Read");

      POINT_COLOR=BLUE;//设置字体为蓝色

       LCD_ShowString(60,170,200,16,16,"SRAMIN");

       LCD_ShowString(60,190,200,16,16,"SRAMIN USED:   %");

       LCD_ShowString(60,210,200,16,16,"SRAMEX USED:   %");

      while(1)

       {    

              key=KEY_Scan(0);//不支持连按 

              switch(key)

              {

                     case 0://没有按键按下  

                            break;

                     case KEY_RIGHT: //KEY0按下

                            p=mymalloc(sramx,2048);//申请2K字节

                            if(p!=NULL)sprintf((char*)p,"Memory Malloc Test%03d",i);

//p写入一些内容

                            break;

                     case KEY_DOWN: //KEY1按下    

                            if(p!=NULL)

                            {

                                   sprintf((char*)p,"Memory Malloc Test%03d",i);//更新显示内容       

                                   LCD_ShowString(60,250,200,16,16,p);                     //显示P的内容

                            }

                            break;

                     case KEY_LEFT:   //KEY2按下   

                            myfree(sramx,p);//释放内存

                            p=0;               //指向空地址

                            break;

                     case KEY_UP:       //KEY UP按下

                           sramx=!sramx;//切换当前malloc/free操作对象

                            if(sramx)LCD_ShowString(60,170,200,16,16,"SRAMEX");

                            else LCD_ShowString(60,170,200,16,16,"SRAMIN");

                            break;

              }

              if(tp!=p)

              {

                     tp=p;

                     sprintf((char*)paddr,"P Addr:0X%08X",(u32)tp);

                     LCD_ShowString(60,230,200,16,16,paddr);              //显示p的地址

                     if(p)LCD_ShowString(60,250,200,16,16,p);              //显示P的内容

                  else LCD_Fill(60,250,239,266,WHITE);            //p=0,清除显示

              }

              delay_ms(10);  

              i++;

              if((i%20)==0)//DS0闪烁.

              {

                     LCD_ShowNum(60+96,190,mem_perused(SRAMIN),3,16);

//显示内部内存使用率

                     LCD_ShowNum(60+96,210,mem_perused(SRAMEX),3,16);

//显示外部内存使用率

                    LED0=!LED0;

             }

       }       

}

       该部分代码比较简单,主要是对mymallocmyfree的应用。不过这里提醒大家,如果对一个指针进行多次内存申请,而之前的申请又没释放,那么将造成“内存泄露”,这是内存管理所不希望发生的,久而久之,可能导致无内存可用的情况!所以,在使用的时候,请大家一定记得,申请的内存在用完以后,一定要释放。

       另外,本章希望利用USMART调试内存管理,所以在USMART里面添加了mymallocmyfree两个函数,用于测试内存分配和内存释放。大家可以通过USMART自行测试。

43.4 下载验证

在代码编译成功之后,我们通过下载代码到ALIENTEK战舰STM32开发板上,得到如图43.4.1所示界面:


43.4.1 程序运行效果图

可以看到,内外内存的使用率均为0%,说明还没有任何内存被使用,此时我们按下KEY0,就可以看到内部内存被使用5%了,同时看到下面提示了指针p所指向的地址(其实就是被分配到的内存地址)和内容。多按几次KEY0,可以看到内存使用率持续上升(注意对比p的值,可以发现是递减的,说明是从顶部开始分配内存!),此时如果按下KEY2,可以发现内存使用率降低了5%,但是再按KEY2将不再降低,说明“内存泄露”了。这就是前面提到的对一个指针多次申请内存,而之前申请的内存又没释放,导致的“内存泄露”。

       KEY_UP按键,可以切换当前操作内存(内部内存/外部内存),KEY1键用于更新p的内容,更新后的内容将重新显示在LCD模块上面。

       本章,我们还可以借助USMART,测试内存的分配和释放,有兴趣的朋友可以动手试试。如图43.4.2所示:


43.4.2 USMART测试内存管理函数

 

《STM32开发指南》第四十三章 内存管理实验.rar

574.29 KB, 下载次数: 562

实验38 内存管理实验.rar

189.19 KB, 下载次数: 511

我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

54

主题

537

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2012-2-27
在线时间
7 小时
发表于 2013-4-20 09:35:39 | 显示全部楼层
有点不明白,在malloc.h中用了#include "sys.h" 这个实验里好像没有用的sys.h东西吧,为什么要加这个文件呢
我注释掉之后报了一堆错误,u8无法识别等等。
这是为什么呢,我看了手册sys主要是设置端口操作,以及define 是否使用ucos。这里为什么它必不可少啊。太迷惑了
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-4-20 13:13:46 | 显示全部楼层
回复【2楼】wwjdwy:
---------------------------------
关键是要包括map.h,里面又有其他头文件...
比如u8的定义之类的.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-4-20 17:28:42 | 显示全部楼层
这个内存管理对flash不知道麻不麻烦 
因为FLASH的解锁好像挺麻烦
就是每次申请都要
写内容 包括初始化都要解锁- -!
我的理解
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-4-20 18:08:31 | 显示全部楼层
回复【4楼】charlieholy:
---------------------------------
对flash不用管理了...
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-4-20 18:50:59 | 显示全部楼层
e  可能是我想多了 我想FLASH比较大 如果可以利用起来当RAM的话也挺好 而且掉电不会丢失
可能属于文件管理系统的范畴了 - -!纠结

但是感觉linux里面的内存池管理是基于链表实现的吧 
哪个更好呢
回复 支持 反对

使用道具 举报

108

主题

1433

帖子

2

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2234
金钱
2234
注册时间
2012-4-30
在线时间
7 小时
发表于 2013-4-20 19:00:52 | 显示全部楼层
回复【6楼】charlieholy:
---------------------------------
flash操作总会要频繁擦除的,擦多了影响芯片寿命....
回复 支持 反对

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-4-20 19:07:54 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
p1-->20002028     //申请2K
p2-->20001828
p3-->20001028
p4-->20000828
p5-->20000028
以前没注意 今天malloc出来看了才发现RAM是逆生长的
我知道ARM的栈是逆生长的 是因为放在RAM中的缘故吗
还是所有的RAM都是逆生长的
还是说就是arm自带的RAM是逆生长的
回复 支持 反对

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-4-20 19:22:45 | 显示全部楼层
回复【8楼】charlieholy:
---------------------------------
仔细看了下才发现真像是这样- -!
for(offset=memtblsize[memx]-1;offset>=0;offset--)
源码是为了配合RAM逆生长的机制啊
回复 支持 反对

使用道具 举报

54

主题

537

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2012-2-27
在线时间
7 小时
发表于 2013-4-20 19:33:57 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
是的不包含时候是会报错,u8等等定义不识别
回复 支持 反对

使用道具 举报

54

主题

537

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2012-2-27
在线时间
7 小时
发表于 2013-4-20 19:38:56 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
这个map.h是如何包含的啊?我跟踪了找不到。。。。。。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

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

使用道具 举报

54

主题

537

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2012-2-27
在线时间
7 小时
发表于 2013-4-20 21:57:14 | 显示全部楼层


 
怎么都搜不到啊原子哥。
另外战舰板子能播放视频么?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-4-20 22:16:14 | 显示全部楼层
回复【13楼】wwjdwy:
---------------------------------
寄存器版本代码才有!!!
stm32f10x_map.h
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-4-20 22:16:26 | 显示全部楼层
在SYSTEM文件夹的SYS文件夹里面!
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

54

主题

537

帖子

0

精华

高级会员

Rank: 4

积分
797
金钱
797
注册时间
2012-2-27
在线时间
7 小时
发表于 2013-6-7 14:36:23 | 显示全部楼层
释放原理

当p申请的内存用完,需要释放的时候,调用free函数实现。free函数先判断p指向的内存地址所对应的内存块,然后找到对应的内存管理表项目,得到p所占用的内存块数目m(内存管理表项目的值就是所分配内存块的数目),将这m个内存管理表项目的值都清零,标记释放,完成一次内存释放。

原子哥内存管理的释放其实就是标记一下这块地址是否还用,不用了就把map记为0.但其实对于里面的数据没做任何处理,我们的数据还是在里面的对么?没做任何处理
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

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

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-6-26 19:58:57 | 显示全部楼层
这个外部ram是stm32自带的吗       at(0X68000000)));
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-6-26 20:56:45 | 显示全部楼层
回复【18楼】charlieholy:
---------------------------------
要外加芯片的
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-6-27 09:42:29 | 显示全部楼层
大哥你用的是哪款芯片- -容量是多大
回复 支持 反对

使用道具 举报

50

主题

201

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
423
金钱
423
注册时间
2013-4-9
在线时间
1 小时
发表于 2013-6-27 09:43:20 | 显示全部楼层
回复【19楼】正点原子:
---------------------------------
大哥你用的是哪款芯片- -容量是多大 使用什么接口- -
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-6-27 10:32:58 | 显示全部楼层
看我们开发板的原理图
IS62WV51216,1M字节.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

25

主题

163

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
443
金钱
443
注册时间
2012-4-29
在线时间
38 小时
发表于 2013-8-20 21:10:00 | 显示全部楼层
回复【22楼】正点原子:

看我们开发板的原理图
IS62WV51216,1M字节.

---------------------------------
原子同志,你的这个“分块式内存管理”是自己独创的还是简化了一些成熟的内存管理方法?
只是用来演示这个实验的吗?做到产品中。。。可行?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-8-20 22:31:11 | 显示全部楼层
回复【23楼】ilikerome:
---------------------------------
不是独创,早有人想出来了。
当然可以用于产品了,这东西又不收费...
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

8

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2013-8-27
在线时间
0 小时
发表于 2013-8-27 10:12:05 | 显示全部楼层
回复【3楼】正点原子:
-----------------------------
原子哥你好,  mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);//内存状态表数据清零 

为什么要乘以2?不懂了、、、求指点
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-8-27 11:44:19 | 显示全部楼层
回复【25楼】funny_cy:
---------------------------------
因为是16位数据长度。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

1

主题

4

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2013-11-27
在线时间
0 小时
发表于 2013-11-27 20:31:15 | 显示全部楼层
各位大哥,  請問為什麼我在编译器debug 
__align(4) u8 mem1base[MEM1_MAX_SIZE]; //内部SRAM内存池                                 

__align(4) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000)));
這兩句的時候会报错, 不能解译 __align(4) 和 __attribute__
我因為學習的關係, 需要用到IAR Embedded Workbench 這個编程器,
我要如何補上定义?
請各位大哥幫忙, 感謝
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2013-11-27 23:26:10 | 显示全部楼层
回复【27楼】bm123:
---------------------------------
可能IAR不支持这两个指令,得找下替代方法.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

8

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
116
金钱
116
注册时间
2014-2-25
在线时间
16 小时
发表于 2014-2-25 12:28:22 | 显示全部楼层
//内存管理控制器

struct _m_mallco_dev mallco_dev=

{

       mem_init,                                   //内存初始化

       mem_perused,                             //内存使用率

       mem1base,mem2base,                  //内存池

       mem1mapbase,mem2mapbase,      //内存管理状态表

       0,0,                                   //内存管理未就绪

};

//内存管理控制器

struct _m_mallco_dev

{

       void (*init)(u8);                                 //初始化

       u8 (*perused)(u8);                          //内存使用率

       u8   *membase[2];                             //内存池 管理2个区域的内存

       u16 *memmap[2];                                    //内存管理状态表

       u8  memrdy[2];                               //内存管理是否就绪

};

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

mallco.c和mallco.h这两个结构体是同一个吗?看起来怎么又不一样?
ST华南代理,做新项目的网友,如果有用到ST的单片机可向我申请免费样品,QQ:945689011
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-2-25 21:03:54 | 显示全部楼层
回复【29楼】荡荡:
---------------------------------
一样的.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

267

主题

376

帖子

0

精华

QQ游客

积分
1079
金钱
1079
注册时间
2012-2-23
在线时间
12 小时
发表于 2014-3-17 11:53:45 | 显示全部楼层
回复【30楼】正点原子:

回复【29楼】荡荡:
---------------------------------
一样的.

---------------------------------
这个内存管理算是动态还是静态的呢?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-3-17 20:13:38 | 显示全部楼层
回复【31楼】xujiangyu0619:
---------------------------------
怎么定义动态还是静态?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

267

主题

376

帖子

0

精华

QQ游客

积分
1079
金钱
1079
注册时间
2012-2-23
在线时间
12 小时
发表于 2014-3-20 10:32:38 | 显示全部楼层
回复【32楼】正点原子:

回复【31楼】xujiangyu0619:
---------------------------------
怎么定义动态还是静态?

---------------------------------
没试过,应该是要分动态分配和静态分配的。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-3-20 18:03:30 | 显示全部楼层
回复【33楼】xujiangyu0619:
---------------------------------
具体怎么区分?
何谓动态分配?
何谓静态分配?
可否举例说明?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

267

主题

376

帖子

0

精华

QQ游客

积分
1079
金钱
1079
注册时间
2012-2-23
在线时间
12 小时
发表于 2014-3-21 21:21:26 | 显示全部楼层
回复【34楼】正点原子:

回复【33楼】xujiangyu0619:
---------------------------------
具体怎么区分?
何谓动态分配?
何谓静态分配?
可否举例说明?

---------------------------------
http://wenku.baidu.com/link?url=ZG9Jvd-V-vLXE_3AFHTaaw03duMXdYsLWNKDvdECqcj3HnC4rwcjfzv1tp_qWti14p-_q2Ao4gqXSdGLce_lnxweIbNMiCMfoRte_egXjZ7
原子哥,你看看这个如何
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-3-22 00:15:45 | 显示全部楼层
回复【35楼】xujiangyu0619:
---------------------------------
这里的动态,就是我楼主位实现的功能。
静态,就是指MDK编译器编译的时候分配的内存,比如你函数里面的变量,都是属于这个类型,编译的时候就确定了的。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2013-10-5
在线时间
9 小时
发表于 2014-7-29 23:13:24 | 显示全部楼层
原子哥:
#define MEM1_BLOCK_SIZE 32      //内存块大小为32字节
#define MEM1_MAX_SIZE 40*1024   //最大管理内存 40K
#define MEM1_ALLOC_TABLE_SIZE MEM1_MAX_SIZE/MEM1_BLOCK_SIZE  //内存表大小

__align(4) u8 mem1base[MEM1_MAX_SIZE]; //内部SRAM内存池
这个就相当于开辟40k的空间
u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; //内部SRAM内存池MAP 
而这个就是40*1024/32 *2=2560Byte=2.5k的空间
为什么要分内存池和内存块出来呢?两者没联系的吧?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-7-30 00:21:09 | 显示全部楼层
回复【37楼】岁月已无声:
---------------------------------
你了解我这个内存管理的原理了么?
好好了解下吧。

或者,你不用内存管理表,有更好的办法实现内存管理,也可以。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2013-10-5
在线时间
9 小时
发表于 2014-7-30 10:59:06 | 显示全部楼层
回复【38楼】正点原子:
---------------------------------
有点懂了。
内存管理表存的是本次分配的内存块个数,一个u16 mem1mapbase存的是对应的一个内存块的占用情况。为什么不定义为u8呢?因为如果要
分配超过256*32Byte=8k的内存,那内存管理表存不下去了。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-7-30 23:36:13 | 显示全部楼层
回复【39楼】岁月已无声:
---------------------------------
如果用u8,才会出现你这个情况.
u16,就是 65535*32byte了.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2013-10-5
在线时间
9 小时
发表于 2014-7-31 10:54:17 | 显示全部楼层
回复【40楼】正点原子:
---------------------------------
原子哥,为什么释放内存块的时候,只是将内存管理状态表清0,而不用将内存池清0?

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;           /*   这里是将内存管理表清0吧?  */
        }  
        return 0;  
    }else return 2;//偏移超区了.>
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-7-31 23:50:12 | 显示全部楼层
回复【41楼】岁月已无声:
---------------------------------
本来就不用清零内存池。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

67

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2013-10-5
在线时间
9 小时
发表于 2014-8-1 11:09:07 | 显示全部楼层
回复【42楼】正点原子:
---------------------------------
那这是不是意味着内存没有被释放掉?也就说实际内存使用率没变?原子哥写的内存使用率是根据内存管理表判断的而不是内存池,这样子可以吗?
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-8-2 00:20:10 | 显示全部楼层
回复【43楼】岁月已无声:
---------------------------------
不是。
内存管理有没有释放,是看内存管理表的。而不是看内存池的。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

15

主题

115

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
396
金钱
396
注册时间
2013-7-12
在线时间
64 小时
发表于 2014-9-17 16:26:03 | 显示全部楼层
请问原子哥,为何是4字节对齐,为何不是8字节对齐,你是怎么知道要4字节对齐的?
提供工业物联网整体解决方案!
https://shop469761648.taobao.com/?spm=2013.1.0.0.3e0568ccstLyMK
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-9-17 23:14:59 | 显示全部楼层
回复【45楼】zxcmcu:
---------------------------------
你可以用8字节对齐。
不四字节对齐可能死机。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2013-3-20
在线时间
6 小时
发表于 2014-12-17 18:05:21 | 显示全部楼层
原子兄,这个内存管理算法应该可以用于外部SRAM内存管理吧?我有几个问题,请教一下,
1、如果用外部SRAM,void *mymalloc(u8 memx,u32 size) 函数怎么用,memx参数的意思是所属内存块,不是很理解,0代表内部SRAM,那外部SRAM传什么参数。
2、另外外部SRAM地址设置为0X68000000,可以设置成 FMC bank1 0X60000000这个地址么,我设置成这个地址,编译器报错。


我用的外部SRAM是IS61LV25616,编译器配置外部SRAM如下



回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
 楼主| 发表于 2014-12-17 23:05:20 | 显示全部楼层
回复【47楼】lucjn:
---------------------------------
可以的。
1,就是个标记,因为同时管理2个内存区域,必须传入一个参数,表示从那块申请。外部SRAM就是1了。
2,可以,前提是你这个地址没有被使用。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

3

主题

15

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2013-3-20
在线时间
6 小时
发表于 2014-12-18 11:12:09 | 显示全部楼层
谢谢原子兄!!
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
36
金钱
36
注册时间
2013-8-6
在线时间
2 小时
发表于 2015-1-7 10:49:49 | 显示全部楼层
回复【48楼】正点原子:
---------------------------------
请教一个问题:这里所说的内部内存管理指的是对 堆进行管理吗? 管理内存的起始地址是多少? 大小是怎么分配的?
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-27 06:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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