Files
checker_m4/source/soft/mystdlib.c
2023-06-25 15:30:36 +08:00

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