本文共 11007 字,大约阅读时间需要 36 分钟。
url : git@github.com:lisider/u-boot.gitbranch : ok6410acommit id : e63a4077ad3aea53107495b0b68b95e720fe6033config : ok6410a_mini_defconfig// 涉及的 .S .s .c 文件 有 67个
// 运行在 0x0c00 0000// 入口 为 arch/arm/lib/vectors.S 中的 _start 标号处的 b resetreset arch/arm/cpu/arm1176/start.S 39 lowlevel_init(108) board/samsung/ok6410a/lowlevel_init.S 72 _main(110) arch/arm/lib/crt0.S 91 board_init_f(117) board/samsung/ok6410a/ok6410a.c 266 debug_uart_init(271) include/debug_uart.h 193 _debug_uart_init(196) drivers/serial/s3c64xx_serial.c 315 board_init_r(177) common/spl/spl.c 589 spl_board_init(641) board/samsung/ok6410a/ok6410a.c 255 spl_boot_mmc(258) board/samsung/ok6410a/bl2_mmc_copy.c 18 mmc_bl2_copy(23) board/samsung/ok6410a/bl2_mmc_copy.c 7 CopyMovitoMem(HSMMC_CHANNEL, MOVI_BL2_POS, MOVI_BL2_BLKCNT, bl2_base, MOVI_INIT_REQUIRED)(13) arch/arm/mach-s3c64xx/include/mach/movi.h 25 bl2base(24) // 跳转到 u-boot 的u-boot镜像
// common/init/board_init.c// register volatile gd_t *gd asm ("r9");// arch/arm/include/asm/global_data.h:112:#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9")reset save_boot_params // null mrs r0, cpsr bic r0, r0, #0x3f // 清 bit[4:0] 为0 // 设置 mode 为 system // 清 bit[5] 为 0 // 设置 T 为0 , 指令集 为 ARM orr r0, r0, #0xd3 // 与 0b11010011 // 设置mode 为 Supervisor // 设置 I 为 1,disable IRQ // 设置 F 为 1,disable FIQ msr cpsr, r0 // 设置 cpsr lowlevel_init spl_config_uart_baudrate ulong val = spl_uart_getclk(is_mpll) / 115200; _UBRDIV = val / 16 - 1; _UDIVSLOT = udivslot[val % 16]; mem_ctrl_asm_init _main board_init_f_alloc_reserve // 申请 struct global_data 个字节 用来存储 gd_t *gd 指向的 gd_t 结构体 // include/asm-generic/global_data.h 中 有 gd_t 的 定义 board_init_f_init_reserve // 初始化 gd_t *gd 指向的 gd_t 结构体 空间 为 0 // 初始化 gd_t *gd 指向的 gd_t 结构体 的 成员 malloc_base // 问题: spl 阶段初始化好的 gd结构体空间 , u-boot 阶段继承了吗? // u-boot 阶段没阶段,清空了. // 但是 u-boot 阶段不清空的话,就可以继承 spl 初始化好的数据 // 在spl加载u-boot过程中,r9没变化,且r9指向的空间也没被破坏 /* 下面的这几行有两个目标 // 此时开始布局ddr中的内存,而不是0x0c00 0000在的iram // i-ram 只用作 u-boot-spl.bin(最多8KB) 的存储,所以如果在这8KB使用堆栈,则有可能破坏 i-ram 中的 u-boot-spl.bin 1. 设置sp 2. 存储gd指针变量并clear gd指针变量指向的空间,并设置 gd->malloc_base = 0x5f9f ff20; ldr r0, =((0x5FB00000 - 0x0C)) => r0 : 5FAF FFF4 bic r0, r0, #7 => r0 : 5FAF FFF0 mov sp, r0 => sp : 5FAF FFF0 bl board_init_f_alloc_reserve => r0 : 5f9f ff20 (5FAF FFF0 - 0x10 0000 - 0xD0) mov sp, r0 => sp : 5f9f ff20 ***** 设置了 栈指针 mov r9, r0 => r9 : 5f9f ff20 ***** 存储了 gd指针变量的值 bl board_init_f_init_reserve => 初始化 (5f9fff20 - 5f9fff20+0xD0) 的空间 */ /* // .code .rodata .data .bss .stack .heap 此时i-ram的内存分布 0C00 2000---------------------0C00 2000 8KB(0x2000)大小,用于存储8KB的u-boot-spl.bin// 不管u-boot-spl.bin有没有8KB,都会从mmc上拷贝8KB过来 内存中的u-boot.bin 中存在 .bss段 内存中的u-boot.bin 也存在 .code .rodata .data 0C00 0000---------------------0C00 0000 此时ddr的内存分布 5FFF FFFF---------------------5FFF FFFF 5120KB(0x500000)大小,空洞 5FB0 0000--------------------- 16B(0x10)大小,空洞 5FAF FFF0--------------------- 1024KB(0x100000)大小,用于sys_malloc 5F9F FFF0--------------------- 208B(0xD0)大小,用于gd 5F9F FF20--------------------- 255999KB(约250MB)大小,用于栈 5000 0000---------------------5000 0000 */ board_init_f debug_uart_init // 被调用时第一次使用栈(sp指针) board_debug_uart_init // null _debug_uart_init struct s3c64xx_uart *uart = (struct s3c64xx_uart *)0x7F005000; s3c64xx_serial_init(uart); uart->UFCON = 0; uart->UMCON = 0; uart->ULCON = 3; uart->UCON =0xa45; s3c64xx_serial_baud(uart, get_uart_clk(0), 115200); val = (uclk / baudrate) % 16; uart->UBRDIV = uclk / baudrate / 16 - 1; uart->UDIVSLOT = udivslot[val]; for (val = 0; val < 100; val++) __asm__ __volatile__("": : :"memory"); CLEAR_BSS ldr r0, =__bss_start ldr r3, =__bss_end mov r1, #0x00000000 subs r2, r3, r0 bl memset // lib/string.c spl_relocate_stack_gd // null board_init_r spl_set_bd // common/spl/spl.c static struct bd_info bdata __attribute__ ((section(".data"))); // gd->bd = &bdata; // 填充bd , 为填充板子数据做准备 spl_init // spl_common_init(1) // gd->malloc_limit = 0x100000; // gd->malloc_ptr = 0; // gd->flags |= GD_FLG_SPL_INIT; // include/asm-generic/global_data.h // 为 malloc 做准备 timer_init // 设置 s3c6410的timer // 0x7F006000 // 设置 gd->arch.timer_rate_hz // 设置 gd->arch.lastinc // 设置 gd->arch.timer_reset_value // 为 delay 做准备 spl_board_init spl_boot_mmc ulong bl2base=0x5FB00000; mmc_bl2_copy writel(readl(HM_CONTROL4) | (0x3 << 16), HM_CONTROL4); // ({ u32 __v = ({ u32 __v = (*(volatile unsigned int *)((0x8c))); asm volatile ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0)); __v; }) | (0x3 << 16); asm volatile ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0)); (*(volatile unsigned int *)((0x8c)) = (__v)); __v; }); ret = CopyMovitoMem(HSMMC_CHANNEL, MOVI_BL2_POS, MOVI_BL2_BLKCNT, bl2_base, MOVI_INIT_REQUIRED); // ret = (((int(*)(int, uint, ushort, uint *, int))(*((uint *)(0x0C004000 + 0x8))))(0,((*((volatile unsigned int*)(0x0C004000 - 0x4)) - ((1 * 1024) / 512)) - ((8 * 1024) / 512) - ((512 * 1024) / 512) - (0x4000 / 512)),((512 * 1024) / 512),bl2_base,0)); bl2base
可以看出来 spl 的流程 1. 上电 2. 设置 cpsr 3. 调用 lowlevel_init 初始化clock和uart和ddr和中断和gpio 4. 调用_main 4.1 整理ddr的内存布局 .code .bss .data .rodata 在iram .heap .stack 在 ddr 4.2 重新初始化uart 4.3 清BSS (与4.1为一体) 4.4 填充gd 为填充板子数据做准备 为malloc做准备 初始化timer,为delay做准备 4.5 直接 调用 i-tcm 的函数拷贝 u-boot 到 ddr , 并跳转到 u-boot A. 初始化但是没有用到的东西 uart 与 timer 与 中断 与 gpio .heap gd与已经初始化的gd成员
mov r12, lr // GPKCON0 ldr r0, =0x7f008000 ldr r1, =0x55555555 str r1, [r0, #0x800] // GPKCON1 ldr r1, =0x55555555 str r1, [r0, #0x804] // GPLCON0 ldr r1, =0x22222666 str r1, [r0, #0x810] mov r0, #0 bl lcd_backlight_switch // GPMCON ldr r0, =0x7f008000 ldr r1, =0x00111111 str r1, [r0, #0x820] // GPMPUD ldr r1, =0x00000555 str r1, [r0, #0x828] // GPMDAT ldr r1, =0x002a str r1, [r0, #0x824] // MEM1DRVCON ldr r1, =0 str r1, [r0, #0x1D4] // Watchdog ldr r0, =0x7e000000 @0x7e004000 orr r0, r0, #0x4000 mov r1, #0 str r1, [r0] // EINTPEND ldr r0, =(0x7f008000 +0x924) ldr r1, [r0] str r1, [r0] // VIC0 ldr r0, =(0x71200000) @0x71200000 // VIC1 ldr r1, =(0x71300000) @0x71300000 // Disable all interrupts mvn r3, #0x0 str r3, [r0, #(0x14)] str r3, [r1, #(0x14)] // Set all interrupts as IRQ mov r3, #0x0 str r3, [r0, #(0x0C)] str r3, [r1, #(0x0C)] // Pending Interrupt Clear mov r3, #0x0 str r3, [r0, #(0xF00)] str r3, [r1, #(0xF00)]# 141 "../board/samsung/ok6410a/lowlevel_init.S" // ELFIN_CLOCK_POWER_BASE ldr r0, =0x7e00f000 ldr r1, [r0, #0x1C] orr r1, r1, #0x2000 str r1, [r0, #0x1C] mov r0, # 1 bl spl_config_uart_baudrate bl uart_asm_init mov r0, #0x4F @'O' bl asm_putc mov r0, #0x4B @'K' bl asm_putc# 184 "../board/samsung/ok6410a/lowlevel_init.S" mov r0, #0x2B @'+' bl asm_putc // Memory subsystem ldr r0, =0x7e00f120 mov r1, #0x0D str r1, [r0] mov r0, #0x2B @'+' bl asm_putc // ddr bl mem_ctrl_asm_init mov r0, #0x2D @'-' bl asm_putc mov r0, #0x2D @'-' bl asm_putc // Wakeup support ldr r0, =(0x7e00f000 + 0x904) ldr r1, [r0] bic r1, r1, #0xfffffff7 cmp r1, #0x8 beq wakeup_reset1: mov lr, r12 mov pc, lr
.globl mem_ctrl_asm_initmem_ctrl_asm_init: ldr r0, =0x7e001000 ldr r1, =0x4 str r1, [r0, #(0x04)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 7800) - 1) / 1000000) str r1, [r0, #(0x10)] ldr r1, =(3<<1) str r1, [r0, #(0x14)] ldr r1, =1 str r1, [r0, #(0x18)] ldr r1, =2 str r1, [r0, #(0x1C)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 45) - 1) / 1000000 + 1) str r1, [r0, #(0x20)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 68) - 1) / 1000000 + 1) str r1, [r0, #(0x24)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 23) - 1) / 1000000 + 1) ldr r2, =(((((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 23) - 1) / 1000000 + 1) - 3) << 3) orr r1, r1, r2 str r1, [r0, #(0x28)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 80) - 1) / 1000000 + 1) ldr r2, =(((((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 80) - 1) / 1000000 + 1) - 3) << 5) orr r1, r1, r2 str r1, [r0, #(0x2C)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 23) - 1) / 1000000 + 1) ldr r2, =(((((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 23) - 1) / 1000000 + 1) - 3) << 3) orr r1, r1, r2 str r1, [r0, #(0x30)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 15) - 1) / 1000000 + 1) str r1, [r0, #(0x34)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 15) - 1) / 1000000 + 1) str r1, [r0, #(0x38)] ldr r1, =2 str r1, [r0, #(0x3C)] ldr r1, =2 str r1, [r0, #(0x40)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 120) - 1) / 1000000 + 1) str r1, [r0, #(0x44)] ldr r1, =(((((12000000/(3<<1)*266)/(1 +1)/(1 +1)) / 1000 * 120) - 1) / 1000000 + 1) str r1, [r0, #(0x48)] ldr r1, =0x0001001a str r1, [r0, #(0x0C)] ldr r1, =0xB45 str r1, [r0, #(0x4C)] ldr r1, =0x150F0 str r1, [r0, #(0x200)] ldr r1, =0x0 str r1, [r0, #(0x304)] ldr r1, =0x0c0000 str r1, [r0, #(0x08)] ldr r1, =0x000000 str r1, [r0, #(0x08)] ldr r1, =0x040000 str r1, [r0, #(0x08)] str r1, [r0, #(0x08)] ldr r1, =0x0a0000 str r1, [r0, #(0x08)] ldr r1, =0x080032 str r1, [r0, #(0x08)] mov r1, #0x0 str r1, [r0, #(0x04)]check_dmc1_ready: ldr r1, [r0, #(0x00)] mov r2, #0x3 and r1, r1, r2 cmp r1, #0x1 bne check_dmc1_ready nop mov pc, lr
gd_t // include/asm-generic/global_data.h arch // arch/arm/include/asm/global_data.h lastinc timer_reset_value timer_rate_hz struct bd_info *bd; unsigned long flags; unsigned int baudrate; unsigned long cpu_clk; unsigned long bus_clk; unsigned long pci_clk; unsigned long mem_clk; unsigned long fb_base; unsigned long malloc_limit; unsigned long malloc_ptr;
// 硬件部分// base : 0x7F006000// 相对地址typedef struct { S3C64XX_REG32 TCFG0; S3C64XX_REG32 TCFG1; S3C64XX_REG32 TCON; S3C64XX_TIMER ch[4]; S3C64XX_REG32 TCNTB4; S3C64XX_REG32 TCNTO4; } S3C64XX_TIMERS;
lib/time.c 中 有 __weak 声明的 函数(get_ticks get_timer timer_init)arm/mach-s3c64xx/timer.c 实现(get_ticks get_timer timer_init 和 get_tbclk) 提供给lib/time.c 如下函数 : get_tbclk get_ticks 提供给common/spl/spl.c 如下函数 : timer_init目的是在 spl/lib/time.c 中 提供 delay/udelay 函数使用者 命令中的 reset drivers/serial/serial.c 中的 U_BOOT_ENV_CALLBACK(baudrate, on_baudrate); // 当前版本中 在 spl 中 无 实际作用 用于 assert fail 和 panic
转载地址:http://sbigi.baihongyu.com/