• uboot启动流程-涉及_main汇编函数


    一.  uboot启动流程涉及函数

    本文简单分析一下 save_boot_params_ret调用的函数:_main汇编函数。

    本文继之前文章的学习,地址如下:

    uboot启动流程-涉及s_init汇编函数_凌肖战的博客-CSDN博客

    二.  uboot启动流程涉及的 _main汇编函数

    经过之前文章的分析,uboot启动流程的汇编函数调用关系:

    下面来分析 _main 函数。

    _main 函数定义在文件 arch/arm/lib/crt0.S 中,_main函数的前部分代码内容如下:

    1. 67 ENTRY(_main)
    2. 68
    3. 69 /*
    4. 70 * Set up initial C runtime environment and call board_init_f(0).
    5. 71 */
    6. 72
    7. 73 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
    8. 74 ldr sp, =(CONFIG_SPL_STACK)
    9. 75 #else
    10. 76 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
    11. 77 #endif
    12. 78 #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC
    13. destination */
    14. 79 mov r3, sp
    15. 80 bic r3, r3, #7
    16. 81 mov sp, r3
    17. 82 #else
    18. 83 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
    19. 84 #endif
    20. 85 mov r0, sp
    21. 86 bl board_init_f_alloc_reserve

    76 行,设置 sp 指针为 CONFIG_SYS_INIT_SP_ADDR ,也就是 sp 指向 0X0091FF00
    83 行, sp 8 字节对齐。
    85 行,读取 sp 到寄存器 r0 里面,此时 r0=0X0091FF00
    第 86 行,调用 board_init_f_alloc_reserve 函数 ,此函数有一个参数,参数为 r0 中的值,也 就是 0X0091FF00 ,此函数定义在文件 common/init/board_init.c 中,内容如下:
    1. 56 ulong board_init_f_alloc_reserve(ulong top)
    2. 57 {
    3. 58 /* Reserve early malloc arena */
    4. 59 #if defined(CONFIG_SYS_MALLOC_F)
    5. 60 top -= CONFIG_SYS_MALLOC_F_LEN;
    6. 61 #endif
    7. 62 /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */
    8. 63 top = rounddown(top-sizeof(struct global_data), 16);
    9. 64
    10. 65 return top;
    11. 66 }

    函数 board_init_f_alloc_reserve 主要是留出早期的 malloc 内存区域和 gd 内存区域,其中,CONFIG_SYS_MALLOC_F_LEN=0X400( 在文件 include/generated/autoconf.h 中定义 ) sizeof(struct global_data)=248(GD_SIZE 值),完成以后的内存分布如下:

    board_init_f_alloc_reserve 是有返回值的,返回值为新的 top 值,从上面的内存分布 可知, 此时, top=0X0091FA00

    继续分析_main 函数,如下是继以上代码:

    1. 87 mov sp, r0
    2. 88 /* set up gd here, outside any C code */
    3. 89 mov r9, r0
    4. 90 bl board_init_f_init_reserve
    87 行,将 r0 写入到 sp 里面,r0 保存着 board_init_f_alloc_reserve 函数的返回值,所以这一句也就是设置 sp=0X0091FA00
    89 行,将 r0 寄存器的值写到寄存器 r9 里面,因为 r9 寄存器存放着全局变量 gd 的地址, 在文件 arch/arm/include/asm/global_data.h 中。如下所示:

    可以看出, uboot 中定义了一个指向 gd_t 的指针 gd gd 存放在寄存器 r9 里面的,因此 gd 是个全局变量。 gd_t 是个结构体,在 include/asm-generic/global_data.h 里面有定义, gd_ 定义如下:

    1. 27 typedef struct global_data {
    2. 28 bd_t *bd;
    3. 29 unsigned long flags;
    4. 30 unsigned int baudrate;
    5. 31 unsigned long cpu_clk; /* CPU clock in Hz! */
    6. 32 unsigned long bus_clk;
    7. 33 /* We cannot bracket this with CONFIG_PCI due to mpc5xxx */
    8. 34 unsigned long pci_clk;
    9. 35 unsigned long mem_clk;
    10. 36 #if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
    11. 37 unsigned long fb_base; /* Base address of framebuffer mem */
    12. 38 #endif
    13. ......
    14. 121 #ifdef CONFIG_DM_VIDEO
    15. 122 ulong video_top; /* Top of video frame buffer area */
    16. 123 ulong video_bottom; /* Bottom of video frame buffer area */
    17. 124 #endif
    18. 125 } gd_t;

    因此,_main函数的第 89 行代码就是设置 gd 所指向的位置,也就是 gd 指向 0X0091FA00

    90 行调用函数 board_init_f_init_reserve ,此函数在文件common/init/board_init.c 中有定义,函数内容如下:
    1. 110 void board_init_f_init_reserve(ulong base)
    2. 111 {
    3. 112 struct global_data *gd_ptr;
    4. 113 #ifndef _USE_MEMCPY
    5. 114 int *ptr;
    6. 115 #endif
    7. 116
    8. 117 /*
    9. 118 * clear GD entirely and set it up.
    10. 119 * Use gd_ptr, as gd may not be properly set yet.
    11. 120 */
    12. 121
    13. 122 gd_ptr = (struct global_data *)base;
    14. 123 /* zero the area */
    15. 124 #ifdef _USE_MEMCPY
    16. 125 memset(gd_ptr, '\0', sizeof(*gd));
    17. 126 #else
    18. 127 for (ptr = (int *)gd_ptr; ptr < (int *)(gd_ptr + 1); )
    19. 128 *ptr++ = 0;
    20. 129 #endif
    21. 130 /* set GD unless architecture did it already */
    22. 131 #if !defined(CONFIG_ARM)
    23. 132 arch_setup_gd(gd_ptr);
    24. 133 #endif
    25. 134 /* next alloc will be higher by one GD plus 16-byte alignment */
    26. 135 base += roundup(sizeof(struct global_data), 16);
    27. 136
    28. 137 /*
    29. 138 * record early malloc arena start.
    30. 139 * Use gd as it is now properly set for all architectures.
    31. 140 */
    32. 141
    33. 142 #if defined(CONFIG_SYS_MALLOC_F)
    34. 143 /* go down one 'early malloc arena' */
    35. 144 gd->malloc_base = base;
    36. 145 /* next alloc will be higher by one 'early malloc arena' size */
    37. 146 base += CONFIG_SYS_MALLOC_F_LEN;
    38. 147 #endif
    39. 148 }

    可以看出,此函数用于初始化 gd ,其实就是清零处理。另外,此函数还设置了 gd->malloc_base gd 基地址 +gd 大小 =0X0091FA00+248=0X0091FAF8 ,在做 16 字节对齐,最 gd->malloc_base=0X0091FB00 ,这个也就是 early malloc 的起始地址。

    继续分析_main 函数,如下是继以上代码:

    1. 92 mov r0, #0
    2. 93 bl board_init_f
    3. 94
    4. 95 #if ! defined(CONFIG_SPL_BUILD)
    5. 96
    6. 97 /*
    7. 98 * Set up intermediate environment (new sp and gd) and call
    8. 99 * relocate_code(addr_moni). Trick here is that we'll return
    9. 100 * 'here' but relocated.
    10. 101 */
    11. 102
    12. 103 ldr sp, [r9, #GD_START_ADDR_SP] /* sp = gd->start_addr_sp */
    13. 104 #if defined(CONFIG_CPU_V7M) /* v7M forbids using SP as BIC
    14. destination */
    15. 105 mov r3, sp
    16. 106 bic r3, r3, #7
    17. 107 mov sp, r3
    18. 108 #else
    19. 109 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
    20. 110 #endif
    21. 111 ldr r9, [r9, #GD_BD] /* r9 = gd->bd */
    22. 112 sub r9, r9, #GD_SIZE /* new GD is below bd */

    92 行设置 R0 0
    93 行,调用 board_init_f 函数,此函数定义在文件 common/board_f.c 中!主要用来初始化 DDR ,定时器,完成代码拷贝等等,此函数我们后面在详细的分析。
    第 103 行,重新设置环境(sp 和 gd)、获取 gd->start_addr_sp 的值赋给 sp,在函数 board_init_f 中会初始化 gd 的所有成员变量,其中 gd->start_addr_sp=0X9EF44E90, 所以这里相当于设置
    sp=gd->start_addr_sp=0X9EF44E90。0X9EF44E90 是 DDR 中的地址,说明新的 sp 和 gd 将会存 放到 DDR 中,而不是内部的 RAM 了。
    第 109 行,sp 做 8 字节对齐。
    第 111 行,获取 gd->bd 的地址赋给 r9,此时 r9 存放的是老的 gd,这里通过获取 gd->bd 的地址来计算出新的 gd 的位置。GD_BD=0。
    第 112 行,新的 gd 在 bd 下面,所以 r9 减去 gd 的大小就是新的 gd 的位置,获取到新的 gd 的位置以后赋值给 r9。

    下一篇文章继续分析 _main函数。

  • 相关阅读:
    程序员转行做运营,曾被逼得每天想离职,最后...
    求链表的相交节点
    4-2计算小于1000的正整数的平方根
    微信小程序订单页面怎么写啊,刚开始接触这个自己没有头绪不知道怎么下手
    写给小白 : 如何学习编程?
    基于SpringBoot和Vue的商品秒杀系统设计与实现
    React-4 组件知识
    【最长递增系列】动态规划法和贪心法
    Leetcode2656. K 个元素的最大和
    【工具】OCR方法|不用下载额外的软件,提取扫描中英文PDF的目录文本的最优解!(一)
  • 原文地址:https://blog.csdn.net/wojiaxiaohuang2014/article/details/133432838