353 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			353 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
 | 
						|
#include "stdint.h"
 | 
						|
#include "string.h"
 | 
						|
#include "rtthread.h"
 | 
						|
#include "board.h"
 | 
						|
#include "debug.h"
 | 
						|
 | 
						|
 | 
						|
typedef struct 
 | 
						|
{
 | 
						|
  uint8_t *membase;   // 内存池
 | 
						|
  uint8_t memrdy;     // 内存管理是否就绪
 | 
						|
  uint16_t *memmap;   // 内存管理状态表
 | 
						|
  // 内存管理参数	   
 | 
						|
  uint32_t memtblsize ;		// 内存表大小
 | 
						|
  uint32_t memblksize;		// 内存分块大小
 | 
						|
  uint32_t memsize    ;		// 内存总大小
 | 
						|
  void *mutex;
 | 
						|
}mallco_dev;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#define SRAM_USER_SIZE (80*1024)
 | 
						|
#define MEM_BLOCK_SIZE			  (32)
 | 
						|
#define MEM_MAX_SIZE			    (((SRAM_USER_SIZE))*MEM_BLOCK_SIZE/(MEM_BLOCK_SIZE+2))  						    
 | 
						|
#define MEM_ALLOC_TABLE_SIZE	((MEM_MAX_SIZE/MEM_BLOCK_SIZE)&(~3))
 | 
						|
#define SRAM_USER_ADDR ((uint32_t)g_sram_mem)
 | 
						|
 | 
						|
//分配的内存都是双字对齐的
 | 
						|
#define MEM_BASE ((uint8_t *)(SRAM_USER_ADDR+MEM_ALLOC_TABLE_SIZE*2))
 | 
						|
#define MEMMAP_BASE ((uint16_t *)(SRAM_USER_ADDR))
 | 
						|
 | 
						|
static uint8_t g_sram_mem[SRAM_USER_SIZE];
 | 
						|
//内存管理控制器
 | 
						|
static mallco_dev g_self;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//内存管理初始化  
 | 
						|
void mem_init(void)  
 | 
						|
{  
 | 
						|
  mallco_dev *self=&g_self;
 | 
						|
  if(self->memrdy) return;
 | 
						|
  
 | 
						|
	self->memtblsize = MEM_ALLOC_TABLE_SIZE;
 | 
						|
	self->memblksize = MEM_BLOCK_SIZE;
 | 
						|
	self->memsize    = MEM_MAX_SIZE;
 | 
						|
	self->membase=MEM_BASE;
 | 
						|
	self->memmap=MEMMAP_BASE;
 | 
						|
	
 | 
						|
  memset(self->memmap, 0,self->memtblsize*2);
 | 
						|
	memset(self->membase, 0,self->memsize);
 | 
						|
  self->mutex=rt_mutex_create("mem",RT_IPC_FLAG_FIFO);
 | 
						|
	self->memrdy=1;
 | 
						|
} 
 | 
						|
 
 | 
						|
 | 
						|
 | 
						|
// 获取内存使用率
 | 
						|
// 返回值:使用率(0~100)
 | 
						|
int mem_perused(void)  
 | 
						|
{   
 | 
						|
  mallco_dev *self=&g_self;
 | 
						|
  uint32_t used=0;  
 | 
						|
  uint32_t i;  
 | 
						|
  for(i=0;i<self->memtblsize;i++)  
 | 
						|
  {  
 | 
						|
    if(self->memmap[i])used++; 
 | 
						|
  } 
 | 
						|
  //return (used*100)/(self->memtblsize); 
 | 
						|
  return used;
 | 
						|
}  
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// 内存分配(内部调用)
 | 
						|
// size:要分配的内存大小(字节)
 | 
						|
// 返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址 
 | 
						|
static uint32_t mem_malloc(uint32_t size)  
 | 
						|
{  
 | 
						|
  mallco_dev *self=&g_self;
 | 
						|
  signed long offset=0;  
 | 
						|
  uint16_t nmemb;
 | 
						|
  uint16_t cmemb=0;
 | 
						|
  uint32_t i;  
 | 
						|
  uint32_t ret=0xffffffff;
 | 
						|
  if(size==0)return ret;
 | 
						|
  rt_mutex_take(self->mutex,RT_WAITING_FOREVER);
 | 
						|
  nmemb=size/self->memblksize;
 | 
						|
  if(size%self->memblksize)nmemb++;  
 | 
						|
  for(offset=self->memtblsize-1;offset>=0;offset--)
 | 
						|
  {     
 | 
						|
    if(!self->memmap[offset])cmemb++;
 | 
						|
    else cmemb=0;
 | 
						|
    if(cmemb==nmemb)
 | 
						|
    {
 | 
						|
      for(i=0;i<nmemb;i++)
 | 
						|
      {  
 | 
						|
        self->memmap[offset+i]=nmemb;  
 | 
						|
      }  
 | 
						|
      ret= (offset*self->memblksize);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }  
 | 
						|
  rt_mutex_release(self->mutex);
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
//释放内存(内部调用) 
 | 
						|
//offset:内存地址偏移
 | 
						|
//返回值:0,释放成功;1,释放失败;  
 | 
						|
static int mem_free(uint32_t offset)  
 | 
						|
{  
 | 
						|
  mallco_dev *self=&g_self;
 | 
						|
  int i;
 | 
						|
  int ret=1;
 | 
						|
  rt_mutex_take(self->mutex,RT_WAITING_FOREVER);
 | 
						|
  if(offset<self->memsize)
 | 
						|
  {  
 | 
						|
    int index=offset/self->memblksize;
 | 
						|
    int nmemb=self->memmap[index];
 | 
						|
    for(i=0;i<nmemb;i++)
 | 
						|
    {  
 | 
						|
      self->memmap[index+i]=0;  
 | 
						|
    }  
 | 
						|
    ret= 0;  
 | 
						|
  }
 | 
						|
  rt_mutex_release(self->mutex);
 | 
						|
  return ret;
 | 
						|
}  
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void *malloc(uint32_t size)  
 | 
						|
{  
 | 
						|
  mallco_dev *self=&g_self;
 | 
						|
  uint32_t offset;  
 | 
						|
	void *ret_addr=NULL;
 | 
						|
	offset=mem_malloc(size); 
 | 
						|
	if (offset!=0XFFFFFFFF)
 | 
						|
	{
 | 
						|
		ret_addr=(void*)((uint32_t)self->membase+offset);  
 | 
						|
	}
 | 
						|
	return ret_addr;  
 | 
						|
}  
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static void self_free(void *ptr)  
 | 
						|
{  
 | 
						|
  mallco_dev *self=&g_self;
 | 
						|
	uint32_t offset;  
 | 
						|
	if(ptr==NULL)
 | 
						|
	{
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		offset=(uint32_t)ptr-(uint32_t)self->membase;  
 | 
						|
		mem_free(offset); 
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void *calloc(size_t nmemb, size_t size)
 | 
						|
{
 | 
						|
  void *p;
 | 
						|
  p=malloc(nmemb*size);
 | 
						|
  if(p) memset(p,0,size);
 | 
						|
  return p;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void *realloc(void *p,size_t size)
 | 
						|
{
 | 
						|
  param_check(0);
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#define MEM_TEMP_PTR_NUM  400
 | 
						|
typedef void (*del_fun_def)(void *t);
 | 
						|
 | 
						|
typedef struct{
 | 
						|
  void *temp_ptr[MEM_TEMP_PTR_NUM];
 | 
						|
  void *del_ptr[MEM_TEMP_PTR_NUM];
 | 
						|
  int used;
 | 
						|
  uint32_t bitmap[(MEM_TEMP_PTR_NUM+31)/32];
 | 
						|
  void *mutex;
 | 
						|
}temp_def;
 | 
						|
static temp_def g_tempptr;
 | 
						|
 | 
						|
 | 
						|
// 在位图中找到一个0/1
 | 
						|
static int bitmap_find(uint32_t *bitmap,int num,int bit)
 | 
						|
{
 | 
						|
  for(int i=0;i<num;i++)
 | 
						|
  {
 | 
						|
    if((bitmap[i/32]&(1<<(i%32)))==(bit<<(i%32)))
 | 
						|
    {
 | 
						|
      return i;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return -1;
 | 
						|
}
 | 
						|
// 设置位图中指定位
 | 
						|
static void bitmap_set(uint32_t *bitmap,int index)
 | 
						|
{
 | 
						|
  bitmap[index/32]|=1<<(index%32);
 | 
						|
}
 | 
						|
static void bitmap_clear(uint32_t *bitmap,int index)
 | 
						|
{
 | 
						|
  bitmap[index/32]&=~(1<<(index%32));
 | 
						|
}
 | 
						|
static int bitmap_get(uint32_t *bitmap,int index)
 | 
						|
{
 | 
						|
  return (bitmap[index/32]&(1<<(index%32)))==(1<<(index%32));
 | 
						|
}
 | 
						|
static void *tempptr_append(temp_def *t,void *p,void *del_fun)
 | 
						|
{
 | 
						|
  if(p==NULL) return p;
 | 
						|
  void *ret=NULL;
 | 
						|
  if(del_fun==0) del_fun=self_free;
 | 
						|
  if(t->used<MEM_TEMP_PTR_NUM)
 | 
						|
  {
 | 
						|
    int index=bitmap_find(t->bitmap,MEM_TEMP_PTR_NUM,0);
 | 
						|
    param_check(index>=0);
 | 
						|
    t->temp_ptr[index]=p;
 | 
						|
    t->del_ptr[index]=del_fun;
 | 
						|
    bitmap_set(t->bitmap,index);
 | 
						|
    ret= p;
 | 
						|
    t->used++;
 | 
						|
  }
 | 
						|
  else{
 | 
						|
    param_check(0);
 | 
						|
  }
 | 
						|
  if(ret==NULL) ((del_fun_def)del_fun)(p);
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
// 查询指针是否已存在
 | 
						|
static int tempptr_find(temp_def *t,void *p)
 | 
						|
{
 | 
						|
  int index;
 | 
						|
  for(int i=0;i<MEM_TEMP_PTR_NUM;i++)
 | 
						|
  {
 | 
						|
    if(bitmap_get(t->bitmap,i))
 | 
						|
    {
 | 
						|
      if(t->temp_ptr[i]==p)
 | 
						|
      {
 | 
						|
        return 1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static void tempptr_free(void)
 | 
						|
{
 | 
						|
  int index;
 | 
						|
  void *p=NULL;
 | 
						|
  del_fun_def del=NULL;
 | 
						|
  temp_def *t=&g_tempptr;
 | 
						|
  rt_mutex_take(t->mutex,RT_WAITING_FOREVER);
 | 
						|
  if(index=bitmap_find(t->bitmap,MEM_TEMP_PTR_NUM,1),index>=0)
 | 
						|
  {
 | 
						|
    // DBG_LOG("%s:free tempptr",__func__);
 | 
						|
    p=t->temp_ptr[index];
 | 
						|
    t->temp_ptr[index]=0;
 | 
						|
    del=(del_fun_def)t->del_ptr[index];
 | 
						|
    bitmap_clear(t->bitmap,index);
 | 
						|
    t->used--;
 | 
						|
  }
 | 
						|
  rt_mutex_release(t->mutex);
 | 
						|
  if(del) del(p);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void tempptr_init(void)
 | 
						|
{
 | 
						|
  temp_def *t=&g_tempptr;
 | 
						|
  t->mutex=rt_mutex_create("tempptr",RT_IPC_FLAG_FIFO);
 | 
						|
  rt_thread_idle_sethook(tempptr_free);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// 申请临时内存,在任务结束后自动释放
 | 
						|
void *tmalloc(uint32_t size)
 | 
						|
{
 | 
						|
  void *p;
 | 
						|
  temp_def *t=&g_tempptr;
 | 
						|
  p=malloc(size);
 | 
						|
  rt_mutex_take(t->mutex,RT_WAITING_FOREVER);
 | 
						|
  p=tempptr_append(&g_tempptr,p,NULL);
 | 
						|
  rt_mutex_release(t->mutex);
 | 
						|
  return p;
 | 
						|
}
 | 
						|
 | 
						|
// 把指针添加为临时指针
 | 
						|
void *tappend(void *p,void *del)
 | 
						|
{
 | 
						|
  mallco_dev *self=&g_self;
 | 
						|
  temp_def *t=&g_tempptr;
 | 
						|
  void *ret=NULL;
 | 
						|
  rt_mutex_take(t->mutex,RT_WAITING_FOREVER);
 | 
						|
  if(((uint32_t)p>=(uint32_t)self->membase)&&
 | 
						|
    ((uint32_t)p<(uint32_t)(self->membase+self->memsize)))
 | 
						|
  {
 | 
						|
    if(tempptr_find(t,p)==0)
 | 
						|
    {
 | 
						|
      ret= tempptr_append(t,p,del);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  rt_mutex_release(t->mutex);
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// 释放内存,如果在临时表中则退出
 | 
						|
void free(void *p)
 | 
						|
{
 | 
						|
  if(p==NULL) return;
 | 
						|
  mallco_dev *self=&g_self;
 | 
						|
  temp_def *t=&g_tempptr;
 | 
						|
  int ret=0;
 | 
						|
  rt_mutex_take(t->mutex,RT_WAITING_FOREVER);
 | 
						|
  ret=tempptr_find(t,p);
 | 
						|
  rt_mutex_release(t->mutex);
 | 
						|
  if(ret){
 | 
						|
    return;
 | 
						|
  }else{
 | 
						|
    self_free(p);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 |