#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 (64*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;imemtblsize;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;imemmap[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(offsetmemsize) { int index=offset/self->memblksize; int nmemb=self->memmap[index]; for(i=0;imemmap[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;iusedbitmap,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;ibitmap,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); } }