完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1)实验平台:正点原子Linux开发板 2)摘自《正点原子I.MX6U嵌入式Linux驱动开发指南》 关注官方微信号公众号,获取更多资料:正点原子 32.2.4_main函数详解_main函数定义在文件arch/arm/lib/crt0.S中,函数内容如下: 示例代码32.2.4.1 crt0.S代码段 63/* 64 * entry point of crt0 sequence 65 */ 66 67 ENTRY(_main) 68 69/* 70 * Set up initial C runtime environment and call board_init_f(0). 71 */ 72 73 #if defined(CONFIG_SPL_BUILD)&& defined(CONFIG_SPL_STACK) 74 ldr sp,=(CONFIG_SPL_STACK) 75 #else 76 ldr sp,=(CONFIG_SYS_INIT_SP_ADDR) 77 #endif 78 #if defined(CONFIG_CPU_V7M)/* v7M forbids using SP as BIC destination */ 79 mov r3, sp 80 bic r3, r3, #7 81 mov sp, r3 82 #else 83 bic sp, sp, #7/* 8-byte alignment for ABI compliance */ 84 #endif 85 mov r0, sp 86 bl board_init_f_alloc_reserve 87 mov sp, r0 88/* set up gd here, outside any C code */ 89 mov r9, r0 90 bl board_init_f_init_reserve 91 92 mov r0, #0 93 bl board_init_f 94 95 #if! defined(CONFIG_SPL_BUILD) 96 97/* 98 * Set up intermediate environment (new sp and gd) and call 99 * relocate_code(addr_moni). Trick here is that we'll return 100 * 'here' but relocated. 101 */ 102 103 ldr sp,[r9, #GD_START_ADDR_SP]/* sp = gd->start_addr_sp */ 104 #if defined(CONFIG_CPU_V7M)/* v7M forbids using SP as BIC destination */ 105 mov r3, sp 106 bic r3, r3, #7 107 mov sp, r3 108 #else 109 bic sp, sp, #7/* 8-byte alignment for ABI compliance */ 110 #endif 111 ldr r9,[r9, #GD_BD]/* r9 = gd->bd */ 112 sub r9, r9, #GD_SIZE /* new GD is below bd */ 113 114 adr lr, here 115 ldr r0,[r9, #GD_RELOC_OFF]/* r0 = gd->reloc_off */ 116 add lr, lr, r0 117 #if defined(CONFIG_CPU_V7M) 118 orr lr, #1/* As required by Thumb-only */ 119 #endif 120 ldr r0,[r9, #GD_RELOCADDR]/* r0 = gd->relocaddr */ 121 b relocate_code 122 here: 123/* 124 * now relocate vectors 125 */ 126 127 bl relocate_vectors 128 129/* Set up final (full) environment */ 130 131 bl c_runtime_cpu_setup /* we still call old routine here */ 132 #endif 133 #if!defined(CONFIG_SPL_BUILD)|| defined(CONFIG_SPL_FRAMEWORK) 134 # ifdef CONFIG_SPL_BUILD 135/* Use a DRAM stack for the rest of SPL, if requested */ 136 bl spl_relocate_stack_gd 137 cmp r0, #0 138 movne sp, r0 139 movne r9, r0 140 # endif 141 ldr r0,=__bss_start /* this is auto-relocated! */ 142 143 #ifdef CONFIG_USE_ARCH_MEMSET 144 ldr r3,=__bss_end /* this is auto-relocated! */ 145 mov r1, #0x00000000/* prepare zero to clear BSS */ 146 147 subs r2, r3, r0 /* r2 = memset len */ 148 bl memset 149 #else 150 ldr r1,=__bss_end /* this is auto-relocated! */ 151 mov r2, #0x00000000/* prepare zero to clear BSS */ 152 153 clbss_l:cmp r0, r1 /* while not at end of BSS */ 154 #if defined(CONFIG_CPU_V7M) 155 itt lo 156 #endif 157 strlo r2,[r0]/* clear 32-bit BSS word */ 158 addlo r0, r0, #4/* move to next */ 159 blo clbss_l 160 #endif 161 162 #if! defined(CONFIG_SPL_BUILD) 163 bl coloured_LED_init 164 bl red_led_on 165 #endif 166/* call board_init_r(gd_t *id, ulong dest_addr) */ 167 mov r0, r9 /* gd_t */ 168 ldr r1,[r9, #GD_RELOCADDR]/* dest_addr */ 169/* call board_init_r */ 170 #if defined(CONFIG_SYS_THUMB_BUILD) 171 ldr lr,=board_init_r /* this is auto-relocated! */ 172 bx lr 173 #else 174 ldr pc,=board_init_r /* this is auto-relocated! */ 175 #endif 176/* we should not return here. */ 177 #endif 178 179 ENDPROC(_main) 第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中,内容如下: 示例代码32.2.4.2 board_init.c代码段 56 ulong board_init_f_alloc_reserve(ulong top) 57{ 58 /* Reserve early malloc arena */ 59 #if defined(CONFIG_SYS_MALLOC_F) 60 top -= CONFIG_SYS_MALLOC_F_LEN; 61 #endif 62 /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */ 63 top = rounddown(top-sizeof(struct global_data),16); 64 65 return top; 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值),完成以后的内存分布如图32.2.4.1所示: 图32.2.4.1 内存分布图 函数board_init_f_alloc_reserve是有返回值的,返回值为新的top值,从图32.2.4.1可知,此时top=0X0091FA00。 继续回到示例代码32.2.4.1中,第87行,将r0写入到sp里面,r0保存着函数board_init_f_alloc_reserve的返回值,所以这一句也就是设置sp=0X0091FA00。 第89行,将r0寄存器的值写到寄存器r9里面,因为r9寄存器存放着全局变量gd的地址,在文件arch/arm/include/asm/global_data.h中有如图32.2.4.2所示宏定义: 图32.2.4.2 DECLARE_GLOBAL_DATA_PTR宏定义 从图32.2.4.2可以看出,uboot中定义了一个指向gd_t的指针gd,gd存放在寄存器r9里面的,因此gd是个全局变量。gd_t是个结构体,在include/asm-generic/global_data.h里面有定义,gd_定义如下: 示例代码32.2.4.3 global_data.h代码段 27typedefstruct global_data { 28 bd_t *bd; 29unsignedlong flags; 30unsignedint baudrate; 31unsignedlong cpu_clk;/* CPU clock in Hz! */ 32unsignedlong bus_clk; 33/* We cannot bracket this with CONFIG_PCI due to mpc5xxx */ 34unsignedlong pci_clk; 35unsignedlong mem_clk; 36 #if defined(CONFIG_LCD)|| defined(CONFIG_VIDEO) 37unsignedlong fb_base;/* Base address of framebuffer mem */ 38 #endif ...... 121 #ifdef CONFIG_DM_VIDEO 122 ulong video_top;/* Top of video frame buffer area */ 123 ulong video_bottom;/* Bottom of video frame buffer area */ 124 #endif 125} gd_t; 因此这一行代码就是设置gd所指向的位置,也就是gd指向0X0091FA00。 继续回到示例代码32.2.4.1中,第90行调用函数board_init_f_init_reserve,此函数在文件common/init/board_init.c中有定义,函数内容如下: 示例代码32.2.4.4 board_init.c代码段 110void board_init_f_init_reserve(ulong base) 111{ 112struct global_data *gd_ptr; 113 #ifndef _USE_MEMCPY 114int*ptr; 115 #endif 116 117/* 118 * clear GD entirely and set it up. 119 * Use gd_ptr, as gd may not be properly set yet. 120 */ 121 122 gd_ptr =(struct global_data *)base; 123/* zero the area */ 124 #ifdef _USE_MEMCPY 125 memset(gd_ptr,' |