bs_bcu_app/bsp/bsp_malloc.c

260 lines
8.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
****************************************************************************************************
* @file bsp_delay.c
* @author
* @version V1.0
* @date 2024-02-10
* @brief 内存申请
****************************************************************************************************
*/
#include "bsp_malloc.h"
#if !(__ARMCC_VERSION >= 6010050) /* 不是AC6编译器即使用AC5编译器时 */
/* 内存池(64字节对齐) */
static __align(64) uint8_t mem1base[MEM1_MAX_SIZE]; /* 内部SRAM内存池 */
static __align(64) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((at(0x10000000))); /* 内部CCM内存池 */
static __align(64) uint8_t mem3base[MEM3_MAX_SIZE] __attribute__((at(0x68000000))); /* 外部SRAM内存池 */
/* 内存管理表 */
static MT_TYPE mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; /* 内部SRAM内存池MAP */
static MT_TYPE mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0x10000000 + MEM2_MAX_SIZE))); /* 内部CCM内存池MAP */
static MT_TYPE mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((at(0x68000000 + MEM3_MAX_SIZE))); /* 外部SRAM内存池MAP */
#else /* 使用AC6编译器时 */
/* 内存池(64字节对齐) */
static __ALIGNED(64) uint8_t mem1base[MEM1_MAX_SIZE]; /* 内部SRAM内存池 */
static __ALIGNED(64) uint8_t mem2base[MEM2_MAX_SIZE] __attribute__((section(".bss.ARM.__at_0x10000000"))); /* 内部CCM内存池 */
static __ALIGNED(64) uint8_t mem3base[MEM3_MAX_SIZE] __attribute__((section(".bss.ARM.__at_0x68000000"))); /* 外部SRAM内存池 */
/* 内存管理表 */
static MT_TYPE mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; /* 内部SRAM内存池MAP */
static MT_TYPE mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((section(".bss.ARM.__at_0x1000F000"))); /* 内部CCM内存池MAP */
static MT_TYPE mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((section(".bss.ARM.__at_0x680F0C00"))); /* 外部SRAM内存池MAP */
#endif
/* 内存管理参数 */
const uint32_t memtblsize[SRAMBANK] = {MEM1_ALLOC_TABLE_SIZE, MEM2_ALLOC_TABLE_SIZE, MEM3_ALLOC_TABLE_SIZE}; /* 内存表大小 */
const uint32_t memblksize[SRAMBANK] = {MEM1_BLOCK_SIZE, MEM2_BLOCK_SIZE, MEM3_BLOCK_SIZE}; /* 内存分块大小 */
const uint32_t memsize[SRAMBANK] = {MEM1_MAX_SIZE, MEM2_MAX_SIZE, MEM3_MAX_SIZE}; /* 内存总大小 */
/* 内存管理控制器 */
struct _m_mallco_dev mallco_dev =
{
my_mem_init, /* 内存初始化 */
my_mem_perused, /* 内存使用率 */
mem1base, mem2base, mem3base, /* 内存池 */
mem1mapbase, mem2mapbase, mem3mapbase, /* 内存管理状态表 */
0, 0, 0, /* 内存管理未就绪 */
};
/**
* @brief 复制内存
* @param *des : 目的地址
* @param *src : 源地址
* @param n : 需要复制的内存长度(字节为单位)
* @retval 无
*/
void my_mem_copy(void *des, void *src, uint32_t n)
{
uint8_t *xdes = des;
uint8_t *xsrc = src;
while (n--)*xdes++ = *xsrc++;
}
/**
* @brief 设置内存值
* @param *s : 内存首地址
* @param c : 要设置的值
* @param count : 需要设置的内存大小(字节为单位)
* @retval 无
*/
void my_mem_set(void *s, uint8_t c, uint32_t count)
{
uint8_t *xs = s;
while (count--)*xs++ = c;
}
/**
* @brief 内存管理初始化
* @param memx : 所属内存块
* @retval 无
*/
void my_mem_init(uint8_t memx)
{
uint8_t mttsize = sizeof(MT_TYPE); /* 获取memmap数组的类型长度(uint16_t /uint32_t)*/
my_mem_set(mallco_dev.memmap[memx], 0, memtblsize[memx]*mttsize); /* 内存状态表数据清零 */
mallco_dev.memrdy[memx] = 1; /* 内存管理初始化OK */
}
/**
* @brief 获取内存使用率
* @param memx : 所属内存块
* @retval 使用率(扩大了10倍,0~1000,代表0.0%~100.0%)
*/
uint16_t my_mem_perused(uint8_t memx)
{
uint32_t used = 0;
uint32_t i;
for (i = 0; i < memtblsize[memx]; i++)
{
if (mallco_dev.memmap[memx][i])used++;
}
return (used * 1000) / (memtblsize[memx]);
}
/**
* @brief 内存分配(内部调用)
* @param memx : 所属内存块
* @param size : 要分配的内存大小(字节)
* @retval 内存偏移地址
* @arg 0 ~ 0xFFFFFFFE : 有效的内存偏移地址
* @arg 0xFFFFFFFF : 无效的内存偏移地址
*/
static uint32_t my_mem_malloc(uint8_t memx, uint32_t size)
{
signed long offset = 0;
uint32_t nmemb; /* 需要的内存块数 */
uint32_t cmemb = 0; /* 连续空内存块数 */
uint32_t i;
if (!mallco_dev.memrdy[memx])
{
mallco_dev.init(memx); /* 未初始化,先执行初始化 */
}
if (size == 0) return 0xFFFFFFFF; /* 不需要分配 */
nmemb = size / memblksize[memx]; /* 获取需要分配的连续内存块数 */
if (size % memblksize[memx]) nmemb++;
for (offset = memtblsize[memx] - 1; offset >= 0; offset--) /* 搜索整个内存控制区 */
{
if (!mallco_dev.memmap[memx][offset])
{
cmemb++; /* 连续空内存块数增加 */
}
else
{
cmemb = 0; /* 连续内存块清零 */
}
if (cmemb == nmemb) /* 找到了连续nmemb个空内存块 */
{
for (i = 0; i < nmemb; i++) /* 标注内存块非空 */
{
mallco_dev.memmap[memx][offset + i] = nmemb;
}
return (offset * memblksize[memx]); /* 返回偏移地址 */
}
}
return 0xFFFFFFFF; /* 未找到符合分配条件的内存块 */
}
/**
* @brief 释放内存(内部调用)
* @param memx : 所属内存块
* @param offset : 内存地址偏移
* @retval 释放结果
* @arg 0, 释放成功;
* @arg 1, 释放失败;
* @arg 2, 超区域了(失败);
*/
static uint8_t my_mem_free(uint8_t memx, uint32_t offset)
{
int i;
if (!mallco_dev.memrdy[memx]) /* 未初始化,先执行初始化 */
{
mallco_dev.init(memx);
return 1; /* 未初始化 */
}
if (offset < memsize[memx]) /* 偏移在内存池内. */
{
int index = offset / memblksize[memx]; /* 偏移所在内存块号码 */
int nmemb = mallco_dev.memmap[memx][index]; /* 内存块数量 */
for (i = 0; i < nmemb; i++) /* 内存块清零 */
{
mallco_dev.memmap[memx][index + i] = 0;
}
return 0;
}
else
{
return 2; /* 偏移超区了. */
}
}
/**
* @brief 释放内存(外部调用)
* @param memx : 所属内存块
* @param ptr : 内存首地址
* @retval 无
*/
void myfree(uint8_t memx, void *ptr)
{
uint32_t offset;
if (ptr == NULL)return; /* 地址为0. */
offset = (uint32_t)ptr - (uint32_t)mallco_dev.membase[memx];
my_mem_free(memx, offset); /* 释放内存 */
}
/**
* @brief 分配内存(外部调用)
* @param memx : 所属内存块
* @param size : 要分配的内存大小(字节)
* @retval 分配到的内存首地址.
*/
void *mymalloc(uint8_t memx, uint32_t size)
{
uint32_t offset;
offset = my_mem_malloc(memx, size);
if (offset == 0xFFFFFFFF) /* 申请出错 */
{
return NULL; /* 返回空(0) */
}
else /* 申请没问题, 返回首地址 */
{
return (void *)((uint32_t)mallco_dev.membase[memx] + offset);
}
}
/**
* @brief 重新分配内存(外部调用)
* @param memx : 所属内存块
* @param *ptr : 旧内存首地址
* @param size : 要分配的内存大小(字节)
* @retval 新分配到的内存首地址.
*/
void *myrealloc(uint8_t memx, void *ptr, uint32_t size)
{
uint32_t offset;
offset = my_mem_malloc(memx, size);
if (offset == 0xFFFFFFFF) /* 申请出错 */
{
return NULL; /* 返回空(0) */
}
else /* 申请没问题, 返回首地址 */
{
my_mem_copy((void *)((uint32_t)mallco_dev.membase[memx] + offset), ptr, size); /* 拷贝旧内存内容到新内存 */
myfree(memx, ptr); /* 释放旧内存 */
return (void *)((uint32_t)mallco_dev.membase[memx] + offset); /* 返回新内存首地址 */
}
}