stm32 单片机的__attribute__ ((at())绝对定位及首次适应算法的动态内存管理
本段代码可单独作为一个模块放心使用。
单片机中 __attribute__( at(绝对地址) )的作用分两个,一个是绝对定位到Flash,另个一是绝对定位到RAM/SDRAM。
1、定位到flash中,一般用于固化的信息,如ID卡的ID号,flash标记等等
2、定位到RAM/SDRAM中,一般用于数据量比较大的缓存,如动态内存分配的缓存,串口的接收缓存.
由于单片机的内存空间不够大,硬件设计会外加一个SDRAM等用来扩展存储空间。
这里为了方便动态内存管理所需要的较大缓存空间,就采用__attribute__( at(绝对地址) )定位到SDRAM,
#define MEM_BASE 0xD0700000
mem_TypeDef memory_pool __attribute__((at(MEM_BASE)));
//动态内存分配使用首次适应算法
/* Exported types ------------------------------------------------------------*/
#define SIZE_OF_PAGE 1024
#define MAX_PAGE_NUMBER 1024
#define MSHIFT_BIT 10
//内存表的结构体
typedef struct
{
uint32_t mallocBase; /* Memory pool base address */
uint16_t size[MAX_PAGE_NUMBER]; /* Sizes Table to allow safe deallocation */
uint8_t PageTable[MAX_PAGE_NUMBER]; /* Memory page state table '1'-> Allocated '0' -> Free */
}
mem_TypeDef;
//初始化内存表
void k_MemInit(void)
{
memset(&memory_pool, 0, sizeof(mem_TypeDef));
memory_pool.mallocBase = MEM_BASE + sizeof(mem_TypeDef);
}
void * k_malloc(size_t size)
{
__IO uint16_t index = 0, counter = 0, start = 0;
uint16_t PageCount = 0, NewStart = 0;
if (size > 0)
{
/* look for the first contiguous memory that meet requested size. */
while ( index < (MAX_PAGE_NUMBER))
{
if (memory_pool.PageTable[index++] == 0)
{
counter++;
if (size <= (counter * SIZE_OF_PAGE))
{
PageCount = counter - 1;
NewStart = start;
/* Set memory region state to allocated */
for (index = 0; index <= PageCount;index++)
{
memory_pool.PageTable[NewStart + index] = 1;
}
/* Save size */
memory_pool.size[NewStart] = counter;
/* return pointer to allocated region. */
return (void *)((memory_pool.mallocBase + (start << MSHIFT_BIT)) + sizeof(uint32_t));
// 特别注意红色部分,分配地址的时候偏移4个字节的含义:函数参数传递进来的实际是指针变量,指针变量本身占用4个字节的大小。
}
}
else
{
start = index;
counter = 0;
}
}
}
return NULL;
}
void k_free(void * p)
{
__IO uint16_t index = 0;
uint16_t counter = 0, start = 0;
/* Handle NULL pointers */
if (p == NULL)
return;
/* Find start Index */
start = ((((uint32_t)p - sizeof(uint32_t)) - memory_pool.mallocBase) >> MSHIFT_BIT);
/* Retrieve segment size */
counter = memory_pool.size[start];
/* Set size to zero */
memory_pool.size[start] = 0;
/* Deallocate memory region */
for (index = 0; index < counter; index++)
{
memory_pool.PageTable[start + index] = 0;
}
return;
}