buildroot構建項目(七)--- u-boot 2017.11 適配開發板修改 4 ---- 系統啟動初始化之四
阿新 • • 發佈:2018-01-27
ack tar span mov tel 變量初始化 清零 ppi ntb
設置完寄存器控制器後,則跳出cpu_init_crit,進入_main 函數。即進入crt0.S (arch\arm\lib)
跟著代碼流程慢慢走
一、crt0.S
1.1 第一步執行代碼
1 /* 預設堆棧指針為CONFIG_SYS_INIT_SP_ADDR */ 2 /* #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - GENERATED_GBL_DATA_SIZE) */ 3 /* #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 */ 4/* #define PHYS_SDRAM_1 0x30000000 SDRAM Bank #1 */ 5 /* #define GENERATED_GBL_DATA_SIZE 176 */ 6 /* CONFIG_SYS_INIT_SP_ADDR = 0x3000 0000 + 0x1000 - 176 */ 7 /* 這裏是預設的堆棧地址,而不是最終的堆棧地址 */ 8 ldr r0, =(CONFIG_SYS_INIT_SP_ADDR) /* 0x3000 0f52*/ 9 bic r0, r0, #7 /* 8字節對齊後為,0x3000 0f50 */ 10 mov sp, r0 /*sp 指針指向 0x3000 0f50 */ 11 bl board_init_f_alloc_reserve /* 給 gd 分配內存大小, 通過 u-boot.dis 文件可知 gd 大小為168 */
跳轉到 board_init_f_alloc_reserve 中執行:
1 /* 這個函數用於給global_data分配空間,在relocation之前調用 2 * 傳入的參數是頂部地址,但是不一定是要內存頂部的地址,可以自己進行規劃 3 */ 4 ulong board_init_f_alloc_reserve(ulong top) 5 { 6 /* Reserve early malloc arena*/ 7 /* 先從頂部向下分配一塊CONFIG_SYS_MALLOC_F_LEN大小的空間給early malloc使用 */ 8 /* 關於CONFIG_SYS_MALLOC_F_LEN可以參考README */ 9 /* 這塊內存是用於在relocation前用於給malloc函數提供內存池。 */ 10 #if CONFIG_VAL(SYS_MALLOC_F_LEN) 11 top -= CONFIG_VAL(SYS_MALLOC_F_LEN); 12 #endif 13 /* LAST : reserve GD (rounded up to a multiple of 16 bytes) */ 14 /* 繼續向下分配sizeof(struct global_data)大小的內存給global_data使用,向下16byte對齊 */ 15 /* 這時候得到的地址就是global_data的地址。 */ 16 top = rounddown(top-sizeof(struct global_data), 16); 17 18 return top; /* 將top,也就是global_data的地址返回 */ 19 }
設置完後,返回繼續執行crt0.S中的代碼:
1 mov sp, r0 /* 分配後的棧頂為 3000 0de0,16字節對其後為 3000 0de0 */ 2 /* set up gd here, outside any C code */ 3 mov r9, r0 4 bl board_init_f_init_reserve /* 啟動前初始化完成 */
進入 board_init_f_init_reserve 中執行:
1 /* 這個函數用於對global_data區域進行初始化,也就是清空global_data區域 */ 2 /* 傳入的參數就是global_data的基地址 */ 3 void board_init_f_init_reserve(ulong base) 4 { 5 struct global_data *gd_ptr; 6 7 /* 8 * clear GD entirely and set it up. 9 * Use gd_ptr, as gd may not be properly set yet. 10 */ 11 12 gd_ptr = (struct global_data *)base; 13 /* zero the area, 先通過memset函數對global_data數據結構進行清零 */ 14 memset(gd_ptr, ‘\0‘, sizeof(*gd)); 15 /* set GD unless architecture did it already */ 16 #if !defined(CONFIG_ARM) 17 arch_setup_gd(gd_ptr); 18 #endif 19 /* next alloc will be higher by one GD plus 16-byte alignment */ 20 /* global_data區域是16Byte對齊的,對齊後,後面的地址就是early malloc的內存池的地址 */ 21 /* 這裏就獲取了early malloc的內存池的地址,S3C2440中我們沒有分配此內存池。*/ 22 /* roundup計算處來的大小為 176,基地址為 0x3000 0e90 */ 23 base += roundup(sizeof(struct global_data), 16); 24 25 /* 26 * record early malloc arena start. 27 * Use gd as it is now properly set for all architectures. 28 */ 29 30 #if CONFIG_VAL(SYS_MALLOC_F_LEN) 31 /* go down one ‘early malloc arena‘ */ 32 gd->malloc_base = base; 33 /* next alloc will be higher by one ‘early malloc arena‘ size */ 34 base += CONFIG_VAL(SYS_MALLOC_F_LEN); 35 #endif 36 }
上面進行的初始化,只是臨時的初始化,執行完後,跳出,繼續在 crt0.S中執行
1 mov r0, #0 /* r0 清零 */ 2 bl board_init_f /* 啟動前初始化完成 */
1.2 執行 board_init_f
進入 board_init_f 則正式進入了C語言部分的初始化:
1 /* 啟動前,板初始化,傳入參數 boot_flags = 0 */ 2 void board_init_f(ulong boot_flags) 3 { 4 gd->flags = boot_flags; 5 gd->have_console = 0; 6 7 /* 初始化 函數 結構體數組鏈表 */ 8 if (initcall_run_list(init_sequence_f)) 9 hang(); 10 11 #if !defined(CONFIG_ARM) && !defined(CONFIG_SANDBOX) && 12 !defined(CONFIG_EFI_APP) && !CONFIG_IS_ENABLED(X86_64) 13 /* NOTREACHED - jump_to_copy() does not return */ 14 hang(); 15 #endif 16 }
整個代碼就是在執行 init_sequence_f 中的函數
1 static const init_fnc_t init_sequence_f[] = { 2 setup_mon_len, /* 獲取 u-boot 的大小 */ 3 initf_malloc, /* early malloc的大小,沒有設置,為0 */ 4 initf_bootstage, /* uses its own timer, so does not need DM */ 5 initf_console_record, /* 直接返回0,沒定義宏 */ 6 7 #if !defined(CONFIG_M68K) 8 timer_init, /* initialize timer,初始化PWM定時器 */ 9 #endif 10 env_init, /* initialize environment,環境變量初始化 */ 11 init_baud_rate, /* initialze baudrate settings,串口波特率初始化115200 */ 12 serial_init, /* serial communications setup,串口初始化 */ 13 console_init_f, /* stage 1 init of console,階段1初始化終端 */ 14 display_options, /* say that we are here,打印緩存信息 */ 15 display_text_info, /* show debugging info if required,打印u-boot 的大小 */ 16 17 #if defined(CONFIG_DISPLAY_CPUINFO) 18 print_cpuinfo, /* display cpu info (and speed),打印CPU信息 */ 19 #endif 20 21 #if defined(CONFIG_DISPLAY_BOARDINFO) 22 show_board_info, /* 打印板信息*/ 23 #endif 24 announce_dram_init, /* DRAM打印初始化 */ 25 /* 給gd->bd中內存信息表賦值而已。 */ 26 /* gd->ram_size = PHYS_SDRAM_1_SIZE; */ 27 dram_init, /* configure available RAM banks,DRAM初始化,RAM SIZE大小獲取 64M */ 28 /* 29 * Now that we have DRAM mapped and working, we can 30 * relocate the code and continue running from DRAM. 31 * 32 * Reserve memory at end of RAM for (top down in that order): 33 * - area that won‘t get touched by U-Boot and Linux (optional) 34 * - kernel log buffer 35 * - protected RAM 36 * - LCD framebuffer 37 * - monitor code 38 * - board info struct 39 */ 40 setup_dest_addr, /* 設置重定向的地址為 0x3400 0000 */ 41 reserve_round_4k, /* 4字節對齊後為 0x3400 0000 */ 42 #ifdef CONFIG_ARM 43 reserve_mmu, /* 直接返回0,其中的宏未定義 */ 44 #endif 45 reserve_video, /* 直接返回0,其中的宏未定義 */ 46 reserve_trace, /* 直接返回0,其中的宏未定義 */ 47 reserve_uboot, /* 保留 u-boot 區域,u-boot 的啟動地址為當前減去u-boot大小後的地址 */ 48 reserve_malloc, /* 分配堆區大小 為 4M */ 49 reserve_board, /* bd-t 結構體大小 */ 50 setup_machine, /* 直接返回0,其中的宏未定義 */ 51 reserve_global_data,/* gd-t 結構體大小 */ 52 reserve_fdt, /* fdt 大小 棧在此處*/ 53 reserve_bootstage, /* 直接返回0,其中的宏未定義 */ 54 reserve_arch, /* 直接返回0,其中的宏未定義 */ 55 reserve_stacks, /* 直接返回0,其中的宏未定義 */ 56 dram_init_banksize, /* banksize 大小設定 */ 57 show_dram_config, /* dram 配置 */ 58 display_new_sp, /* 打印當前棧位置 */ 59 reloc_fdt, /* 設置 gd->fdt_blob */ 60 reloc_bootstage, /* 直接返回0,其中的宏未定義 */ 61 setup_reloc, /* 設置 gd->reloc_off為 0x3400 0000 */ 62 NULL, 63 };
1.2.1 setup_mon_len
1 /* #define CONFIG_SYS_MONITOR_LEN (448 * 1024) */ 2 /* #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_FLASH_BASE */ 3 /* #define CONFIG_SYS_FLASH_BASE PHYS_FLASH_1 */ 4 /* #define PHYS_FLASH_1 0x00000000 /* Flash Bank #0 */ */ 5 static int setup_mon_len(void) 6 { 7 /* TODO: use (ulong)&__bss_end - (ulong)&__text_start; ? */ 8 /* 設置gd->mon_len 為編譯出來的 u-boot.bin+bss 段的大小 */ 9 gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE; 10 return 0; 11 }
1.2.2 timer_init
1 /* PWM定時器設置 */ 2 int timer_init(void) 3 { 4 /* 獲取定時器的基地址 */ 5 struct s3c24x0_timers *timers = s3c24x0_get_base_timers(); 6 ulong tmr; 7 8 /* use PWM Timer 4 because it has no output */ 9 /* prescaler for Timer 4 is 16 */ 10 writel(0x0f00, &timers->tcfg0); /* 啟動定時器4 */ 11 if (gd->arch.tbu == 0) { 12 /* 13 * for 10 ms clock period @ PCLK with 4 bit divider = 1/2 14 * (default) and prescaler = 16. Should be 10390 15 * @33.25MHz and 15625 @ 50 MHz 16 */ 17 gd->arch.tbu = get_PCLK() / (2 * 16 * 100); 18 gd->arch.timer_rate_hz = get_PCLK() / (2 * 16); 19 } 20 /* load value for 10 ms timeout */ 21 writel(gd->arch.tbu, &timers->tcntb4); 22 /* auto load, manual update of timer 4 */ 23 tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000; 24 writel(tmr, &timers->tcon); 25 /* auto load, start timer 4 */ 26 tmr = (tmr & ~0x0700000) | 0x0500000; 27 writel(tmr, &timers->tcon); 28 gd->arch.lastinc = 0; 29 gd->arch.tbl = 0; 30 31 return 0; 32 }
1.2.3 setup_dest_addr
/* 設置重定向的地址為 0x3400 0000 */
1 static int setup_dest_addr(void) 2 { 3 #ifdef CONFIG_SYS_SDRAM_BASE 4 gd->ram_top = CONFIG_SYS_SDRAM_BASE; /* SDRAM 基地址 0x3000 0000,棧頂此時在此處 */ 5 #endif 6 gd->ram_top += get_effective_memsize(); /* SDRAM 棧頂為 0x3400 0000 = 0x3000 000 + 400 0000 */ 7 gd->ram_top = board_get_usable_ram_top(gd->mon_len); /* SDRAM 棧頂為 0x3400 0000 */ 8 gd->relocaddr = gd->ram_top; /* 重定向的地址為 0x3400 0000 */ 9 return 0; 10 }
1.2.4 reserve_uboot
保留 u-boot 區域,u-boot 的啟動地址為當前減去u-boot大小後的地址
1 static int reserve_uboot(void) 2 { 3 /* 4 * reserve memory for U-Boot code, data & bss 5 * round down to next 4 kB limit 6 */ 7 gd->relocaddr -= gd->mon_len; /* 減去 u-boot 大小 */ 8 gd->relocaddr &= ~(4096 - 1); /* gd->relocaddr 地址在u-boot的起始地址 */ 9 gd->start_addr_sp = gd->relocaddr; /* 棧地址為當前減去u-boot大小後的地址 */ 10 11 return 0; 12 }
1.2.5 reserve_malloc
1 /* reserve memory for malloc() area */ 2 /* malloc大小 */ 3 static int reserve_malloc(void) 4 { 5 /* #define CONFIG_SYS_MALLOC_LEN (4 * 1024 * 1024) 40 0000*/ 6 gd->start_addr_sp = gd->start_addr_sp - TOTAL_MALLOC_LEN; 7 debug("Reserving %dk for malloc() at: %08lx\n", 8 TOTAL_MALLOC_LEN >> 10, gd->start_addr_sp); 9 return 0; 10 }
1.2.6 reserve_board
給 gd->bd 分配大小
1 static int reserve_board(void) 2 { 3 if (!gd->bd) { 4 gd->start_addr_sp -= sizeof(bd_t); 5 gd->bd = (bd_t *)map_sysmem(gd->start_addr_sp, sizeof(bd_t)); 6 memset(gd->bd, ‘\0‘, sizeof(bd_t)); 7 debug("Reserving %zu Bytes for Board Info at: %08lx\n", 8 sizeof(bd_t), gd->start_addr_sp); 9 } 10 return 0; 11 }
1.2.7 reserve_global_data
gd大小分配,gd在bd的下方
1 static int reserve_global_data(void) 2 { 3 gd->start_addr_sp -= sizeof(gd_t); 4 gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t)); 5 debug("Reserving %zu Bytes for Global Data at: %08lx\n", 6 sizeof(gd_t), gd->start_addr_sp); 7 return 0; 8 }
1.2.8 reserve_fdt
fdt大小分配
1 static int reserve_fdt(void) 2 { 3 #ifndef CONFIG_OF_EMBED 4 /* 5 * If the device tree is sitting immediately above our image then we 6 * must relocate it. If it is embedded in the data section, then it 7 * will be relocated with other data. 8 */ 9 if (gd->fdt_blob) { 10 gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); 11 12 gd->start_addr_sp -= gd->fdt_size; 13 /* gd->new_fdt 指向當前棧地址 */ 14 gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size); 15 debug("Reserving %lu Bytes for FDT at: %08lx\n", 16 gd->fdt_size, gd->start_addr_sp); 17 } 18 #endif 19 20 return 0; 21 }
1.2.9 dram_init_banksize
設置DRAM
1 /* 設置物理地址 bank,這裏只設置了SDRAM的bank */ 2 __weak int dram_init_banksize(void) 3 { 4 /* #define CONFIG_NR_DRAM_BANKS 1 */ 5 /* #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 0x3000 0000 */ 6 #if defined(CONFIG_NR_DRAM_BANKS) && defined(CONFIG_SYS_SDRAM_BASE) 7 gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; 8 gd->bd->bi_dram[0].size = get_effective_memsize(); 9 #endif 10 11 return 0; 12 }
1.2.10 setup_reloc
1 static int setup_reloc(void) 2 { 3 if (gd->flags & GD_FLG_SKIP_RELOC) { 4 debug("Skipping relocation due to flag\n"); 5 return 0; 6 } 7 8 /* #define CONFIG_SYS_TEXT_BASE 0x0 */ 9 #ifdef CONFIG_SYS_TEXT_BASE 10 /* gd->relocaddr 為 0x3400 0000 - u-boot 大小,即在u-boot的起始地址處 */ 11 gd->reloc_off = gd->relocaddr - CONFIG_SYS_TEXT_BASE; 12 #endif 13 memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); 14 15 return 0; 16 }
buildroot構建項目(七)--- u-boot 2017.11 適配開發板修改 4 ---- 系統啟動初始化之四