博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OK6410A 开发板 (三) 13 u-boot-2021.01 boot 解析 SPL 镜像运行部分 boot 详细解析
阅读量:4286 次
发布时间:2019-05-27

本文共 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成员
  • 详细解析 lowlevel_init
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
  • 详细解析mem_ctrl_asm_init
.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
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;
  • 详细解析之 timer
// 硬件部分// 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/

你可能感兴趣的文章
Linux与Windows的8个不同
查看>>
如何给超链接设置宽度和高度
查看>>
趣文:你对程序员适不适合做老公的看法是?
查看>>
仿照某商城首页的源代码及效果
查看>>
网络大牛如何回答Chrome的15个刁钻面试题?
查看>>
某网站静态首页的实现小结
查看>>
常用的正则表达式归纳—JavaScript正则表达式
查看>>
jq实现图片轮播:圆形焦点+左右控制+自动轮播
查看>>
问题:关于贴友分类菜单的实现
查看>>
PHP图像操作:3D图、缩放、旋转、裁剪、添加水印(二)
查看>>
PHP图像操作:3D图、缩放、旋转、裁剪、添加水印(三)
查看>>
document.body、document.documentElement和window获取视窗大小的区别
查看>>
教你利用iframe在网页中显示天气
查看>>
利用Javascript获取当前日期的农历日期
查看>>
利用原生JavaScript获取样式的方式小结
查看>>
PHP制作验证码
查看>>
常用的CSS Hack技术集锦
查看>>
IE 8兼容:X-UA-Compatible的解释
查看>>
关于form.submit()不能提交表单的错误原因
查看>>
初识HTML 5:关于它的三个三
查看>>