| 
									
										
										
										
											2023-06-10 11:52:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-28 18:08:38 +08:00
										 |  |  | #define MEM_TEMP_PTR_NUM  800
 | 
					
						
							| 
									
										
										
										
											2023-06-10 11:52:00 +08:00
										 |  |  | 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); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |