STM32F7xx —— 内存管理

                            STM32F7xx —— 内存管理

 

 

目的:高效、快速的分配,并在适当的时候回收内存资源。最终就是实现malloc和free函数。(实现方法参考原子哥)

#define CONFIG_SRAM_OUT_ENABLE     0

typedef enum
{
  SRAM_TYPE_IN,   // 内部内存池
#if(CONFIG_SRAM_OUT_ENABLE == 1)
  SRAM_YPE_OUT,   // 外部内存池(SDRAM)
#endif
  SRAM_TYPE_DTCM, // DTCM内存池(此部分SRAM仅仅CPU可以访问!!!)
  SRAM_TYPE_MAX,  // 最多支持的SRAM块数.
} sram_type_t;

// 内部SRAM
#define SRAM_IN_BLOCK_SIZE        64            // 内存块大小为64字节
#define SRAM_IN_MAX_SIZE          (160 * 1024)  // 最大管理内存160K
#define SRAM_IN_ALLOC_TABLE_SIZE  (SRAM_IN_MAX_SIZE / SRAM_IN_BLOCK_SIZE)

#if(CONFIG_SRAM_OUT_ENABLE == 1)
// 外部SDRAM里面
#define SRAM_OUT_BLOCK_SIZE       64            // 内存块大小为64字节
#define SRAM_OUT_MAX_SIZE         (100 *1024)   // 最大管理内存100K
#define SRAM_OUT_ALLOC_TABLE_SIZE (SRAM_OUT_MAX_SIZE / SRAM_OUT_BLOCK_SIZE)
#endif

// CCM,用于管理DTCM(特别注意,这部分SRAM,仅CPU可以访问!!)
#define SRAM_DTCM_BLOCK_SIZE      64                  //内存块大小为64字节
#define SRAM_DTCM_MAX_SIZE        (100 *1024)             //最大管理内存60K
#define SRAM_DTCM_ALLOC_TABLE_SIZE  (SRAM_DTCM_MAX_SIZE/SRAM_DTCM_BLOCK_SIZE)
//内存池(32字节对齐)
__align(32) uint8_t sram_in_base[SRAM_IN_MAX_SIZE];                                      // 内部SRAM内存池
uint32_t sram_in_map_base[SRAM_IN_ALLOC_TABLE_SIZE];

#if(CONFIG_SRAM_OUT_ENABLE == 1)
__align(32) uint8_t sram_out_base[SRAM_OUT_MAX_SIZE] __attribute__((at(0xC01F4000)));   // 外部SDRAM内存池
uint32_t sram_out_map_base[SRAM_OUT_ALLOC_TABLE_SIZE] __attribute__((at(0xC01F4000 + SRAM_OUT_MAX_SIZE))); // 外部SRAM内存池MAP
#endif

__align(32) uint8_t sram_dtcm_base[SRAM_DTCM_MAX_SIZE] __attribute__((at(0x20000000))); // 内部DTCM内存池
uint32_t sram_dtcm_map_base[SRAM_DTCM_ALLOC_TABLE_SIZE] __attribute__((at(0x20000000 + SRAM_DTCM_MAX_SIZE))); //内部DTCM内存池MAP

static const uint32_t memtblsize[SRAM_TYPE_MAX] = {SRAM_IN_ALLOC_TABLE_SIZE,
#if(CONFIG_SRAM_OUT_ENABLE == 1)
                                            SRAM_OUT_ALLOC_TABLE_SIZE,
#endif
                                            SRAM_DTCM_ALLOC_TABLE_SIZE
                                           }; //内存表大小

static const uint32_t memblksize[SRAM_TYPE_MAX] = {SRAM_IN_BLOCK_SIZE,
#if(CONFIG_SRAM_OUT_ENABLE == 1)
                                            SRAM_OUT_BLOCK_SIZE,
#endif
                                            SRAM_DTCM_BLOCK_SIZE
                                           };     //内存分块大小

static const uint32_t memsize[SRAM_TYPE_MAX] = {SRAM_IN_MAX_SIZE,
#if(CONFIG_SRAM_OUT_ENABLE == 1)
                                         SRAM_OUT_MAX_SIZE,
#endif
                                         SRAM_DTCM_MAX_SIZE
                                        };          //内存总大小

void mymem_init(uint8_t type);
uint16_t mymem_perused(uint8_t type);

typedef struct
{
	void (* init)(uint8_t );
	uint16_t (* perused)(uint8_t);		 // 内存使用率
	uint8_t 	*membase[SRAM_TYPE_MAX]; // 内存池 管理SRAMBANK个区域的内存
	uint32_t *memmap[SRAM_TYPE_MAX]; 	 // 内存管理状态表
	uint8_t  memrdy[SRAM_TYPE_MAX];    // 内存管理是否就绪
} sram_dev_t;

//内存管理控制器
static sram_dev_t sram_dev =
{
  mymem_init,        // 内存初始化
  mymem_perused,     // 内存使用率
  sram_in_base,

#if(CONFIG_SRAM_OUT_ENABLE == 1)
  sram_out_base,
#endif
  sram_dtcm_base,  // 内存池
  sram_in_map_base,
#if(CONFIG_SRAM_OUT_ENABLE == 1)
  sram_out_map_base,
#endif
  sram_dtcm_map_base,
  0,
#if(CONFIG_SRAM_OUT_ENABLE == 1)
  0,
#endif
  0,
};

// 内存管理初始化
static void mymem_init(uint8_t memx)
{
  memset(sram_dev.memmap[memx], 0, memtblsize[memx] * 4); // 内存状态表数据清零
  sram_dev.memrdy[memx] = 1;                              // 内存管理初始化OK
}

// 获取内存使用率
// type:所属内存块
// 返回值:使用率(扩大了10倍,0~1000,代表0.0%~100.0%)
static uint16_t mymem_perused(uint8_t type)
{
  uint32_t used = 0;
  uint32_t i;
  for(i = 0; i < memtblsize[type]; ++i)
  {
    if(sram_dev.memmap[type][i])
    {
      used++;
    }
  }
	
  return (used * 1000) / (memtblsize[type]);
}

// 内存分配(内部调用)
// type:所属内存块
// size:要分配的内存大小(字节)
// 返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址
static uint32_t mymem_malloc(uint8_t type, uint32_t size)
{
  signed long offset = 0;
  uint32_t nmemb;     // 需要的内存块数
  uint32_t cmemb = 0; // 连续空内存块数
  uint32_t i;

  if(!sram_dev.memrdy[type])
  {
    sram_dev.init(type);  // 未初始化,先执行初始化
  }
  if(size == 0)
  {
    return 0xFFFFFFFF;  // 不需要分配
  }
  nmemb = size / memblksize[type]; // 获取需要分配的连续内存块数
  if(size % memblksize[type])
  {
    nmemb++;
  }
  for(offset = memtblsize[type] - 1; offset >= 0; offset--) // 搜索整个内存控制区
  {
    if(!sram_dev.memmap[type][offset])
    {
      cmemb++;    // 连续空内存块数增加
    }
    else
    {
      cmemb = 0;  // 连续内存块清零
    }
    if(cmemb == nmemb)                // 找到了连续nmemb个空内存块
    {
      for(i = 0; i < nmemb; i++)      // 标注内存块非空
      {
        sram_dev.memmap[type][offset + i] = nmemb;
      }
      return (offset * memblksize[type]); // 返回偏移地址
    }
  }
  return 0xFFFFFFFF; // 未找到符合分配条件的内存块
}

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

void MemInit(uint8_t type)
{
  memset(sram_dev.memmap[type], 0, memtblsize[type] * 4); // 内存状态表数据清零
  sram_dev.memrdy[type] = 1;              // 内存管理初始化OK
}

// 释放内存(外部调用)
// type:所属内存块
// ptr:内存首地址
void MemFree(uint8_t type, void *ptr)
{
  uint32_t offset;
  if(ptr == NULL)
  {
    return;  // 地址为0.
  }
  offset = (uint32_t)ptr - (uint32_t)sram_dev.membase[type];
  mymem_free(type, offset); // 释放内存
}

// 分配内存
void *MemAlloc(uint8_t type, uint32_t size)
{
  uint32_t offset;
  offset = mymem_malloc(type, size);
  if(offset == 0XFFFFFFFF)
  {
    return NULL;
  }
  else
  {
    return (void*)((uint32_t)sram_dev.membase[type] + offset);
  }
}

// 重新分配内存
void *MemRealloc(uint8_t type, void *ptr, uint32_t size)
{
  uint32_t offset;
  offset = mymem_malloc(type, size);
  if(offset == 0xFFFFFFFF)
  {
    return NULL;
  }
  else
  {
    memcpy((void*)((uint32_t)sram_dev.membase[type] + offset), ptr, size); // 拷贝旧内存内容到新内存
    MemFree(type, ptr);                                                     // 释放旧内存
    return (void*)((uint32_t)sram_dev.membase[type] + offset);              // 返回新内存首地址
  }
}

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值