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); | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 |