【正点原子阿波罗STM32F429IGT开发板试用体验】+内存管理

  • apleilx
  • LV5工程师
  • |      2017-11-27 09:24:09
  • 浏览量 3741
  • 回复:0
编译器标准库的动态存储管理从heap区分配内存,只能对单一存储体进行管理,并且分配时间不确定。 正点原子例程提供的一组内存管理程序可以用来管理多个存储体,不过原代码是在MDK下运行的,不适合IAR的内存分配方法。 下面给它改造一下,让它不再依赖编译器。 原子的内存管理主要分为两部分:内存块(用来被分配),内存状态表。 每个存储体划分为若干尺寸相同的存储块,状态表放在对应存储体的顶部,记录存储块的分配状态。使用mymalloc请求内存时,从存储区顶部开始搜索指定尺寸的内存,命中后将目标内存块的状态修改为本次请求的存储块数量。 原代码:
//内存池(32字节对齐)

__align(32) u8 mem1base;													//内部SRAM内存池

__align(32) u8 mem2base __attribute__((at(0XC01F4000)));					//外部SDRAM内存池,前面2M给LTDC用了(1280*800*2)

__align(32) u8 mem3base __attribute__((at(0X10000000)));					//内部CCM内存池

//内存管理表

u32 mem1mapbase;													//内部SRAM内存池MAP

u32 mem2mapbase __attribute__((at(0XC01F4000+MEM2_MAX_SIZE)));	//外部SRAM内存池MAP

u32 mem3mapbase __attribute__((at(0X10000000+MEM3_MAX_SIZE)));	//内部CCM内存池MAP

以上代码使用编译器先分配内存给管理程序用,MDK没问题。但在IAR里面不大合适,需要把RW变量修改到指定的存储体,但放置在SDRAM是有问题的。下面把存储体的访问基准设为指针形式,这样就算对应内存对编译器不可见也可以访问。
//内存池(32字节对齐)

__ALIGN_BEGIN

static u8 mem1base; //内部SRAM内存池

__ALIGN_END



#define mem2base ((u8*)(MEM2_BASE))	           			                        //外部SDRAM内存池,前面2M给LTDC用了(1280*800*2)

#define mem3base ((u8*)(MEM3_BASE))					                            //内部CCM内存池



//内存管理表

static u32 mem1mapbase; //内部SRAM内存池MAP

#define mem2mapbase ((u32*)(MEM2_BASE + MEM2_MAX_SIZE))                         //外部SRAM内存池MAP  //存储区顶部作为分配表

#define mem3mapbase ((u32*)(MEM3_BASE + MEM3_MAX_SIZE))	                        //内部CCM内存池MAP   //存储区顶部作为分配表

存储器分配程序会修改内存分配状态表,如果要在OS里面使用,还要添加互斥锁,否则在分配过程中被高优先级任务打断同时也请求了内存的话,可能会出错。下面给UCOS改一个:
//释放内存(外部调用) 

//memx:所属内存块

//ptr:内存首地址 



void myfree(u8 memx, void *ptr) {

    u32 offset;

    OS_ERR      os_err;

    CPU_TS      cpu_ts;

    

    OSMutexPend (&MutexObjMemMan, 500,  OS_OPT_PEND_BLOCKING, &cpu_ts, &os_err);

    

    if (ptr != NULL){ //地址为0.  

        offset = (u32) ptr - (u32) mallco_dev.membase;

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

    }

    

    OSMutexPost (&MutexObjMemMan,  OS_OPT_POST_NONE, &os_err);

}

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

//memx:所属内存块

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

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



void *mymalloc(u8 memx, u32 size) {

    u32 offset;

    void *pDes;

    

    OS_ERR      os_err;

    CPU_TS      cpu_ts;

    

    OSMutexPend (&MutexObjMemMan, 500,  OS_OPT_PEND_BLOCKING, &cpu_ts, &os_err);

    

    offset = my_mem_malloc(memx, size);

    if (offset == 0XFFFFFFFF) 

        pDes = NULL;

    else 

        pDes = (void*) ((u32) mallco_dev.membase + offset);



    OSMutexPost (&MutexObjMemMan,  OS_OPT_POST_NONE, &os_err);

    

    return pDes;

}



访问分配表前加锁,分配好后释放锁。
  • 0
  • 收藏
  • 举报
  • 分享
我来回复

登录后可评论,请 登录注册

所有回答 数量:0
x
收藏成功!点击 我的收藏 查看收藏的全部帖子