358 lines
6.8 KiB
C
358 lines
6.8 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;
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
#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)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
|