388 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			388 lines
		
	
	
		
			7.0 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 (9*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;  
 | |
|   int used=0;
 | |
| 	void *ret_addr=NULL;
 | |
| 	offset=mem_malloc(size); 
 | |
| 	if (offset!=0XFFFFFFFF)
 | |
| 	{
 | |
| 		ret_addr=(void*)((uint32_t)self->membase+offset);  
 | |
| 	}
 | |
|   else{
 | |
|     used=mem_perused();
 | |
|     param_check(used);
 | |
|   }
 | |
| 	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;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| void *malloc(size_t size)
 | |
| {
 | |
|   return rt_malloc_align(size,4);
 | |
| }
 | |
| void *calloc(size_t nmemb,size_t size)
 | |
| {
 | |
|   return rt_calloc(nmemb,size);
 | |
| }
 | |
| void *realloc(void *p,size_t size)
 | |
| {
 | |
|   return rt_realloc(p,size);
 | |
| }
 | |
| static void self_free(void *p)
 | |
| {
 | |
|   rt_free(p);
 | |
| }
 | |
| 
 | |
| void mem_init(void)
 | |
| {
 | |
| }
 | |
| int mem_perused(void)
 | |
| {
 | |
|   uint32_t used,total,max_used;
 | |
|   rt_memory_info(&total,&used,&max_used);
 | |
|   return used;
 | |
| }
 | |
| 
 | |
| 
 | |
| */
 | |
| 
 | |
| 
 | |
| #define MEM_TEMP_PTR_NUM  800
 | |
| 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)
 | |
| {
 | |
|   temp_def *t=&g_tempptr;
 | |
|   void *ret=NULL;
 | |
|   if(p==NULL) return p;
 | |
|   rt_mutex_take(t->mutex,RT_WAITING_FOREVER);
 | |
|   {
 | |
|     if(tempptr_find(t,p)==0)
 | |
|     {
 | |
|       ret= tempptr_append(t,p,del);
 | |
|     }else{
 | |
|       ret=p;
 | |
|     }
 | |
|   }
 | |
|   rt_mutex_release(t->mutex);
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| // 释放内存,如果在临时表中则退出
 | |
| void free(void *p)
 | |
| {
 | |
|   if(p==NULL) return;
 | |
|   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);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | 
