一、前言
rt_system_heap_init
被rt_hw_board_init
调用。
rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
二、参数分析
#define STM32_SRAM_SIZE 64
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN ((void *)&Image$$RW_IRAM1$$ZI$$Limit)
#define HEAP_END STM32_SRAM_END
HEAP_BEGIN
:RAM
空闲区的开始地址
HEAP_END
:RAM
结束地址
三、Image$$RW_IRAM1$$ZI$$Limit
分析
在ARM
链接器用户指南中描述如下:
映像结构如下图:
RW_IRAM1
为程序RW
和ZI
区加载地址,在分散加载文件中描述:
四、rt_system_heap_init函数分析
/**
* @ingroup SystemInit
*
* This function will initialize system heap memory.
*
* @param begin_addr the beginning address of system heap memory.
* @param end_addr the end address of system heap memory.
*/
void rt_system_heap_init(void *begin_addr, void *end_addr)
{
struct heap_mem *mem;
rt_uint32_t begin_align = RT_ALIGN((rt_uint32_t)begin_addr, RT_ALIGN_SIZE);
rt_uint32_t end_align = RT_ALIGN_DOWN((rt_uint32_t)end_addr, RT_ALIGN_SIZE);
RT_DEBUG_NOT_IN_INTERRUPT;
/* alignment addr */
if ((end_align > (2 * SIZEOF_STRUCT_MEM)) &&
((end_align - 2 * SIZEOF_STRUCT_MEM) >= begin_align))
{
/* calculate the aligned memory size */
mem_size_aligned = end_align - begin_align - 2 * SIZEOF_STRUCT_MEM;
}
else
{
rt_kprintf("mem init, error begin address 0x%x, and end address 0x%x\n",
(rt_uint32_t)begin_addr, (rt_uint32_t)end_addr);
return;
}
/* point to begin address of heap */
heap_ptr = (rt_uint8_t *)begin_align;
RT_DEBUG_LOG(RT_DEBUG_MEM, ("mem init, heap begin address 0x%x, size %d\n",
(rt_uint32_t)heap_ptr, mem_size_aligned));
/* initialize the start of the heap */
mem = (struct heap_mem *)heap_ptr;
mem->magic = HEAP_MAGIC;
mem->next = mem_size_aligned + SIZEOF_STRUCT_MEM;
mem->prev = 0;
mem->used = 0;
#ifdef RT_USING_MEMTRACE
rt_mem_setname(mem, "INIT");
#endif
/* initialize the end of the heap */
heap_end = (struct heap_mem *)&heap_ptr[mem->next];
heap_end->magic = HEAP_MAGIC;
heap_end->used = 1;
heap_end->next = mem_size_aligned + SIZEOF_STRUCT_MEM;
heap_end->prev = mem_size_aligned + SIZEOF_STRUCT_MEM;
#ifdef RT_USING_MEMTRACE
rt_mem_setname(heap_end, "INIT");
#endif
rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO);
/* initialize the lowest-free pointer to the start of the heap */
lfree = (struct heap_mem *)heap_ptr;
}
begin_addr
:RAM
空闲区开始地址
end_addr
:RAM
结束地址
1、对begin_addr和end_addr进行字节对齐
rt_uint32_t begin_align = RT_ALIGN((rt_uint32_t)begin_addr, RT_ALIGN_SIZE);
rt_uint32_t end_align = RT_ALIGN_DOWN((rt_uint32_t)end_addr, RT_ALIGN_SIZE);
2、计算对齐的内存大小
#define RT_ALIGN_SIZE 4
#define SIZEOF_STRUCT_MEM RT_ALIGN(sizeof(struct heap_mem), RT_ALIGN_SIZE)
SIZEOF_STRUCT_MEM
为struct heap_mem
按RT_ALIGN_SIZE
进行对齐后的大小。
/* alignment addr */
if ((end_align > (2 * SIZEOF_STRUCT_MEM)) &&
((end_align - 2 * SIZEOF_STRUCT_MEM) >= begin_align))
{
/* calculate the aligned memory size */
mem_size_aligned = end_align - begin_align - 2 * SIZEOF_STRUCT_MEM;
}
else
{
rt_kprintf("mem init, error begin address 0x%x, and end address 0x%x\n",
(rt_uint32_t)begin_addr, (rt_uint32_t)end_addr);
return;
}
mem_size_aligned
保存堆空间减去2个heap_mem
对象尺寸。
3、使用heap_ptr变量指向堆开始地址
/* point to begin address of heap */
heap_ptr = (rt_uint8_t *)begin_align;
4、初始化堆的开始和结束
/* initialize the start of the heap */
mem = (struct heap_mem *)heap_ptr;
mem->magic = HEAP_MAGIC;
mem->next = mem_size_aligned + SIZEOF_STRUCT_MEM;
mem->prev = 0;
mem->used = 0;
#ifdef RT_USING_MEMTRACE
rt_mem_setname(mem, "INIT");
#endif
/* initialize the end of the heap */
heap_end = (struct heap_mem *)&heap_ptr[mem->next];
heap_end->magic = HEAP_MAGIC;
heap_end->used = 1;
heap_end->next = mem_size_aligned + SIZEOF_STRUCT_MEM;
heap_end->prev = mem_size_aligned + SIZEOF_STRUCT_MEM;
#ifdef RT_USING_MEMTRACE
rt_mem_setname(heap_end, "INIT");
#endif
对heap_end
进行初始化。
5、初始化堆信号量
rt_sem_init(&heap_sem, "heap", 1, RT_IPC_FLAG_FIFO);
6、rt_sem_init函数分析
rt_err_t rt_sem_init(rt_sem_t sem,
const char *name,
rt_uint32_t value,
rt_uint8_t flag)
{
RT_ASSERT(sem != RT_NULL);
/* init object */
rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name);
/* init ipc object */
rt_ipc_object_init(&(sem->parent));
/* set init value */
sem->value = value;
/* set parent */
sem->parent.parent.flag = flag;
return RT_EOK;
}
sem
:指向heap_sem
全局变量
name
:“heap”
value
:1
flag
:RT_IPC_FLAG_FIFO
1、rt_object_init函数分析
/**
* This function will initialize an object and add it to object system
* management.
*
* @param object the specified object to be initialized.
* @param type the object type.
* @param name the object name. In system, the object's name must be unique.
*/
void rt_object_init(struct rt_object *object,
enum rt_object_class_type type,
const char *name)
{
register rt_base_t temp;
struct rt_object_information *information;
#ifdef RT_USING_MODULE
struct rt_dlmodule *module = dlmodule_self();
#endif
/* get object information */
information = rt_object_get_information(type);
RT_ASSERT(information != RT_NULL);
/* initialize object's parameters */
/* set object type to static */
object->type = type | RT_Object_Class_Static;
/* copy name */
rt_strncpy(object->name, name, RT_NAME_MAX);
RT_OBJECT_HOOK_CALL(rt_object_attach_hook, (object));
/* lock interrupt */
temp = rt_hw_interrupt_disable();
#ifdef RT_USING_MODULE
if (module)
{
rt_list_insert_after(&(module->object_list), &(object->list));
object->module_id = (void *)module;
}
else
#endif
{
/* insert object into information object list */
rt_list_insert_after(&(information->object_list), &(object->list));
}
/* unlock interrupt */
rt_hw_interrupt_enable(temp);
}
1、参数分析
rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name);
object
:指向heap_sem.parent.parent
type
:RT_Object_Class_Semaphore
name
:"heap"
2、获取对象信息
/* get object information */
information = rt_object_get_information(type);
RT_ASSERT(information != RT_NULL);
3、初始化信息
/* set object type to static */
object->type = type | RT_Object_Class_Static;
/* copy name */
rt_strncpy(object->name, name, RT_NAME_MAX);
4、将heap_sem
插入到rt_object_container
数组后
/* insert object into information object list */
rt_list_insert_after(&(information->object_list), &(object->list));
/**
* @brief insert a node after a list
*
* @param l list to insert it
* @param n new node to be inserted
*/
rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n)
{
l->next->prev = n;
n->next = l->next;
l->next = n;
n->prev = l;
}
5、rt_object_init
作用如下
1、初始化heap_sem
中name
字段
2、初始化heap_sem
中type
字段
3、将heap_sem
添加到rt_object_containe
r列表中
2、rt_ipc_object_init函数分析
/* init ipc object */
rt_ipc_object_init(&(sem->parent));
/**
* This function will initialize an IPC object
*
* @param ipc the IPC object
*
* @return the operation status, RT_EOK on successful
*/
rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc)
{
/* init ipc object */
rt_list_init(&(ipc->suspend_thread));
return RT_EOK;
}
/**
* @brief initialize a list
*
* @param l list to be initialized
*/
rt_inline void rt_list_init(rt_list_t *l)
{
l->next = l->prev = l;
}
1、执行结果如下
3、设置参数
/* set init value */
sem->value = value;
/* set parent */
sem->parent.parent.flag = flag;
4、rt_sem_init执行结果
4、rt_system_heap_init
总结
1、计算堆空间大小
2、将堆起始地址保存到heap_ptr
变量中
3、初始化heap_end
变量
4、初始化heap_sem
变量,并且将heap_sem
插入到rt_object_container
中
5、lfree保存最低空闲地址
5、简化rt_object_container
rt_object_container
数组太长,不太方便,省略没使用部分。简化后如下图: