rt-thread源码分析篇八:rt_system_heap_init函数分析

一、前言

rt_system_heap_initrt_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_BEGINRAM空闲区的开始地址
HEAP_ENDRAM结束地址

三、Image$$RW_IRAM1$$ZI$$Limit分析

ARM链接器用户指南中描述如下:
在这里插入图片描述
映像结构如下图:
在这里插入图片描述
RW_IRAM1为程序RWZI区加载地址,在分散加载文件中描述:
在这里插入图片描述

四、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_addrRAM空闲区开始地址

end_addrRAM结束地址

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_MEMstruct heap_memRT_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

flagRT_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
在这里插入图片描述
typeRT_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_semname字段
2、初始化heap_semtype字段
3、将heap_sem添加到rt_object_container列表中

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数组太长,不太方便,省略没使用部分。简化后如下图:
在这里插入图片描述

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值