OK6410A 开发板 (三) 12 u-boot-2021.01 boot 解析 U-boot 镜像运行部分 boot 详细解析1

url 		: git@github.com:lisider/u-boot.git
branch 		: ok6410a
commit id 	: e63a4077ad3aea53107495b0b68b95e720fe6033
config 		: ok6410a_mini_defconfig
// 涉及的 .S .s .c 文件 有 223个
reset														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)									common/board_f.c 954
			initcall_run_list(init_sequence_f)(959) 		include/initcall.h 21
				init_sequence_f								common/board_f.c 818
		board_init_r(177) 									common/board_r.c 901
			initcall_run_list(init_sequence_r)(927) 		include/initcall.h 21
				init_sequence_r 							common/board_f.c 695
					run_main_loop(898)						common/board_r.c 678
						main_loop(685) 						common/main.c 39

  • 解析概要
// 入口 为 arch/arm/lib/vectors.S 中的 _start 标号处的 b reset
reset
	lowlevel_init
		时钟
		串口
		ddr
	_main
		// 从代码运行起始位置0x5FB00000 往下 找 gd 和栈 的位置
		bl board_init_f_alloc_reserve
		// 设置栈
		mov sp, r0
		// 设置gd 
		mov r9, r0
		// 初始化gd
		bl board_init_f_init_reserve 


		bl board_init_f 
			查找 设备树的地址
			准备 early malloc
			驱动模型的前期准备
			定时器初始化,为delay做准备
			env 初始化,为查找环境变量做准备
			串口波特率环境变量的查找和串口波特率的设置,为printf做准备
			从 ddr 顶端 0x5FFF FFFF 往下 找 空间
				1. mmu
				2. u-boot
				3. malloc
				4. new_gd
				5. fdt
				6. irq 栈
				7. 栈
			搬移 gd
			搬移设备树(fdt)
			
		// 搬移 u-boot 并 fixloop
		b relocate_code

		// 搬移向量表 到 0x0000 0000
		bl relocate_vectors

		CLEAR_BSS
		// 清.bss 段 , 这是u-boot阶段第一次清, relocate 之前没有清过

		ldr pc,=board_init_r

			// 开 icache 和 dcache
			initr_caches

			// 为 full malloc 做准备
			initr_malloc

			// 驱动模型的后期准备
			initr_dm

			// 初始化 board ID
			board_init

			// 串口及控制台的初始化
			stdio_init_tables
			serial_initialize 
			stdio_add_devices
			console_init_r

			// 其他设备的初始化
			initr_mmc
			initr_ethaddr
			initr_net

			// env 的后初始化
			initr_env

			// 跳转表???
			// the jump table contains pointers to exported functions.
			// A pointer to the jump table is passed to standalone applications.
			// 也就是 说 导出 让 standalone 应用用的
			// u-boot 命令行 可以 加载 bin 文件,并执行 这些bin文件就是 standalone applications
			// 查看 doc/README.standalone
			initr_jumptable

			// 中断相关的初始化(开中断,相关变量)
			interrupt_init


			main_loop
				bootcmd以及cmdline
  • 详细解析

// 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 // 运行在 5FB0 0000// sdram : 0x5000_0000 0x5FFF_FFFF
	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
		// ddr初始化
	_main
		board_init_f_alloc_reserve // 算出gd的地址为 0x5f9fff20
			// 过程与数据和spl 完全一样
			申请 struct global_data 个字节 用来存储 gd_t *gd 指向的 gd_t 结构体
			// include/asm-generic/global_data.h 中 有 gd_t 的 定义
		board_init_f_init_reserve // 根据 gd的地址 0x5f9fff20 算出结构体
			// 过程与数据和spl 完全一样
			初始化 gd_t *gd 指向的 gd_t 结构体 空间 为 0
			初始化 gd_t *gd 指向的 gd_t 结构体 的 成员 malloc_base = 5F9F FFF0
			
			// u-boot过程和 spl 过程用到的 gd 指针是同一个位置
			// 但是 内容不同,因为在 初始化的时候,已经将 gd指针指向的位置全部 memset 0 了	
			// spl 加载 u-boot 的过程中, 就是 A加载B
			// A 加载 B 可以 通过 寄存器 来传值
			// 但是 spl 加载 u-boot 的过程中可以说没有传递任何值
			// 虽然 都用r9 保存了 gd的指针值,但是 r9 是算出来的,不是 spl 传过来的.
			
		/*
		下面的这几行有两个目标
		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
		此时的内存分布
		5FFF FFFF---------------------5FFF FFFF
					5120KB(0x500000)大小,被512KB u-boot.bin占据 // 不管u-boot.bin有没有512KB,都会从mmc上拷贝512KB过来 // U-boot.bin实际大小 248K
					内存中的u-boot.bin 中存在 .bss段,起始为5FB3 61F0,结束为5FB3 BAD4
					内存中的u-boot.bin 也存在 .code .rodata .data
		5FB0 0000---------------------
					16B(0x10)大小,空洞
		5FAF FFF0---------------------
					1024KB(0x100000)大小,用于sys_malloc (.heap)
		5F9F FFF0---------------------
					208B(0xD0)大小,用于gd (很特殊的一个全局变量)
		5F9F FF20---------------------
					255999KB(约250MB)大小,用于栈 (.stack)
		5000 0000---------------------5000 0000
		*/




		board_init_f // 被调用的时候传递的参数为 0 ,用来设置flags.
			gd->flags = 0;
			gd->have_console = 0;

			setup_mon_len // 第一次使用栈,(sp) // 重要参考点1
				gd->mon_len = (ulong)&__bss_end - (ulong)_start;
				// = 0x3bc4c
				// 为 reserve_uboot 做准备
			fdtdec_setup // 为设备树的解析做准备
				gd->fdt_blob = board_fdt_blob_setup();
					return (ulong *)&_end;
				gd->fdt_blob = map_sysmem (env_get_ulong("fdtcontroladdr", 16, (unsigned long)map_to_sysmem(gd->fdt_blob)), 0);
					// 解码fdtcontroladdr环境变量的值,16进制,如果为空则为gd->fdt_blob
				fdtdec_prepare_fdt 
					// 检查gd->fdt_blob为空,则报错
				fdtdec_board_setup
					// null
			initf_malloc // 为 early malloc 做准备
				// 用于 early malloc
				// 此前 gd->malloc_base 已经被初始化为 5F9F FFF0 // base address of early malloc
				gd->malloc_limit = 0x100000; // limit address of early malloc
				gd->malloc_ptr = 0; // current address of early malloc
			log_init
				// null
			initf_bootstage
				bootstage_init(1)
					// null
				bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f")
					show_boot_progress(id);
						//null // TODO, 另一个路径大概率是 printf
			setup_spl_handoff
				// null
			initf_console_record
				// null
			arch_cpu_init
				// null
			mach_cpu_init
				// null
			initf_dm // dm 架构(driver-model),比较复杂,后续有空更新专题 // 为 驱动和设备的注册做准备
				bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f");
					// null
				dm_init_and_scan(1)
					dm_init(0)
						INIT_LIST_HEAD(&(((gd_t *)gd)->uclass_root));
							list->next = list;
							list->prev = list;
						device_bind_by_name(0,0,&root_info, &(((gd_t *)gd)->dm_root)));
							lists_driver_lookup_name(info->name);
							device_bind_common(parent, drv, info->name, (void *)info->platdata, 0, ofnode_null(), platdata_size, devp);
						(((gd_t *)gd)->dm_root)->node = offset_to_ofnode(0)
						device_probe((((gd_t *)gd)->dm_root))
					dm_scan_platdata(1)
						lists_bind_drivers((((gd_t *)gd)->dm_root), 1)
					dm_extended_scan_fdt(gd->fdt_blob, 1)
						dm_scan_fdt(gd->fdt_blob,1)
							dm_scan_fdt_node(gd->dm_root, blob, 0, 1);
						for_each_node dm_scan_fdt_ofnode_path(blob, nodes[i], 1);
							
					dm_scan_other(1)
						// null
				bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F);
					// null
			arch_cpu_init_dm
				// null
			timer_init // 为 delay 做准备
				// 设置 s3c6410的 硬件timer
				gd->arch.timer_rate_hz = pre_freq/1;
				gd->arch.timer_rate_hz *= 1000;
				gd->arch.lastinc = timers->TCNTB4 = gd->arch.timer_rate_hz;
				gd->arch.timer_reset_value = 0;
			env_init
				env_driver_lookup
					env_get_location
						return env_locations[prio] ; // ENVL_MMC
					_env_driver_lookup
						n_ents = xxx
						in section .u_boot_list_2_env_driver ,根据 ENVL_MMC 找到对应的 驱动对应的结构体 struct env_driver
				drv->init	 // drv 为找到的结构体 struct env_driver _u_boot_list_2_env_driver_2_mmc 中没有 init 成员
				env_set_inited(drv->location)
					gd->env_has_init |= (1UL << (location));
					
				gd->env_addr = (ulong)&default_environment[0]; // 待研究
				gd->env_valid = ENV_VALID;
			init_baud_rate
				gd->baudrate = env_get_ulong("baudrate", 10, 115200);
					const char *str = env_get(name);
						env_get_f
							env_get_char
							env_match
					return str ? simple_strtoul(str,0,10) : default_val;
					
			serial_init
				serial_find_console_or_panic
					serial_check_stdout
						str = fdtdec_get_chosen_prop(blob, "stdout-path");
						node = fdt_path_offset_namelen(blob, str, namelen);
						lists_bind_fdt
						device_probe(&dev)
					gd->cur_serial_dev = dev;
				gd->flags |= GD_FLG_SERIAL_READY;
				serial_setbrg
					gd->cur_serial_dev->driver->ops->setbrg(gd->cur_serial_dev, gd->baudrate)// s3c_serial_setbrg
						s3c_serial_setbrg_internal((struct s3c64xx_uart * )CONFIG_DEBUG_UART_BASE, 0 /*CFG_SERIAL_ID*/,CONFIG_BAUDRATE);
							u32 uclk = get_uart_clk(id)
							s3c64xx_serial_baud(uart, uclk, baudrate);
								uart->UBRDIV = uclk / baudrate / 16 - 1;
								uart->UDIVSLOT = udivslot[val];
								barrier(); // 内存顺序模型相关
			console_init_f
				gd->have_console = 1;
				console_update_silent
					// null
				print_pre_console_buffer(PRE_CONSOLE_FLUSHPOINT1_SERIAL);
					// null TODO
					// PRE_CONSOLE_BUFFER
			display_options // printf 可以使用 // 重要参考点2
				display_options_get_banner(true, buf, sizeof(buf));
					display_options_get_banner_priv
						snprintf
				printf("%s", buf);
			display_text_info
				bss_start = (ulong)&__bss_start;
				bss_end = (ulong)&__bss_end;
				text_base = 0x5FB00000;
			checkcpu
				// null
			print_cpuinfo
				printf("**    Updated for OK6410A Board        **\r\n");
			show_board_info
				model = fdt_getprop(gd->fdt_blob, 0, "model", ((void *)0));
				printf("Model: %s\n", model);
				// 实际打印 为 Model: Samsung SMDK6410 based on S3C6410
				// 打印的字符串为 arch/arm/dts/s3c64xx-ok6410a.dts 中的 model 节点的属性
				checkboard
					printf("Board:   OK6410A\n");
			announce_dram_init
				puts("DRAM:  ");
			dram_init
				gd->ram_size += SDRAM_BANK_SIZE; // = 0x1000 0000
			setup_dest_addr
				gd->ram_base = 0x50000000;
				gd->ram_top = gd->ram_base + get_effective_memsize();
					// get_effective_memsize: gd->ram_size
					// = 0x6000 0000
				gd->ram_top = board_get_usable_ram_top(gd->mon_len);
					// = gd->ram_top 
					// = 0x6000 0000
				gd->relocaddr = gd->ram_top;
					// = 0x6000 0000
			reserve_round_4k
				gd->relocaddr &= ~(4096 - 1);
					// hex 后三位与0
					// 0x6000 0000
			arch_reserve_mmu
				arm_reserve_mmu
					gd->arch.tlb_size = (4096 * 4);
						// 0x4000 16K
					gd->relocaddr -= gd->arch.tlb_size;
						// 0x5FFF C000
					gd->relocaddr &= ~(0x10000 - 1);
						// hex 后四位 与0
						// 0x5fff 0000
					gd->arch.tlb_addr = gd->relocaddr;
						// 0x5fff 0000
			reserve_video
				// null
			reserve_trace
				// null
			reserve_uboot
				gd->relocaddr -= gd->mon_len;
					// = 5FFB 33B4
				gd->relocaddr &= ~(4096 - 1);
					// hex 后三位与0
					// 5FFB 3000
				gd->start_addr_sp = gd->relocaddr;
					// 5FFB 3000
			reserve_malloc
				gd->start_addr_sp = reserve_stack_aligned((1024*1024));
					// 0x5feb3000
			reserve_board
					// gd->bd 不为null , 什么都不做
			setup_machine
				gd->bd->bi_arch_number = 1626;
			reserve_global_data
				gd->start_addr_sp = reserve_stack_aligned(sizeof(gd_t));
					// 0x5feb2f30
				gd->new_gd = (gd_t *)map_sysmem(gd->start_addr_sp, sizeof(gd_t));
					// 0x5feb2f30
			reserve_fdt
				gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32);
					// 0xe80
				gd->start_addr_sp = reserve_stack_aligned(gd->fdt_size);
					// 0x5feb20b0
				gd->new_fdt = map_sysmem(gd->start_addr_sp, gd->fdt_size);
					// 0x5feb20b0
			reserve_bootstage
				// null
			reserve_bloblist
				// null
			reserve_arch
				// null
			reserve_stacks
				gd->start_addr_sp = reserve_stack_aligned(16);
					// 这16个字节应该用于 irq的栈
					// 0x5feb20a0
				arch_reserve_stacks
					gd->irq_sp = gd->start_addr_sp;
						// 0x5feb20a0
			dram_init_banksize // 只有一个bank
				for_each_bank
					gd->bd->bi_dram[i].start = addr;
						// 0x50000000
					gd->bd->bi_dram[i].size = (0x10000000);
						// 0x10000000
			show_dram_config
				for_each_bank // 只有一个bank
					size += gd->bd->bi_dram[i].size;
						// 0x10000000
				print_size(size, "");
					// 实际打印 256 MiB
				board_add_ram_info(0);
					null
				putc('\n');
			setup_bdinfo
				// null
			display_new_sp
				// null
			reloc_fdt
				gd->fdt_blob = gd->new_fdt;
			reloc_bootstage
				// null
			reloc_bloblist
				// null
			setup_reloc
				gd->reloc_off = gd->relocaddr - 0x5FB00000;
					// 004b4000
					// 该值是 u-boot的code段 搬移目标地址 与 当前地址的差值
				memcpy(gd->new_gd, (char *)gd, sizeof(gd_t));
			clear_bss
				// null
			// 运行到此时,sp还没更改
			// u-boot 还没搬运
			// 此时,搬运了 gd和设备树
		
		// 此时 r9里面存放的还是gd
		ldr r0, [r9, #72] // 72 是 start_addr_sp
		bic r0, r0, #7 // 与上0b1000 , 第三位清0
		mov sp, r0 // 更改 sp
		
		ldr r9, [r9, #80] // 此时 r9 中存放的 是 new_gd

		adr lr, here // 存放 lr, 为  b(跳转) 做准备
		ldr r0, [r9, #76] // 将 new_gd 中的 reloc_off 存放到r0,用作新的lr的计算
		add lr, lr, r0 	 // 更改lr ,让 relocate_code 返回时,跳转到 已经 搬移好的代码 中去,
		ldr r0, [r9, #56] // 将 new_gd 中的 relocaddr存放到r0,作为第一个参数
		b relocate_code
			// 搬移 u-boot的 code 段
			arch/arm/lib/relocate.S +80
			搬移,修复绝对地址???

		// 此时已经在 搬移过后的代码 中
		bl relocate_vectors // TODO
			// arch/arm/lib/relocate.S +28
			ldr r0, [r9, #56] // 将 new_gd 中的 relocaddr存放到r0
			mcr p15, 0, r0, c12, c0, 0
		bl c_runtime_cpu_setup
			// null
		CLEAR_BSS
			// 问题,搬移过后,__bss_start的值有变化吗?
			// 宏汇编
			// ldr r0, =__bss_start                                                            
			// ldr r3, =__bss_end                                                              
			// mov r1, #0x00000000                                                             
			// subs r2, r3, r0                                                                 
			// bl memset
		bl coloured_LED_init
			// null
		bl red_led_on
			// null





		/*
		// .code .rodata .data .bss .stack .heap
		此时的内存分布
		5FFF FFFF---------------------5FFF FFFF
					mmu
					(0x4000B,16KB)
		5FFF C000---------------------
					空洞
					(0xC000B,48KB)
		5FFF 0000--------------------- // 5FFF 0000 存放在 gd->arch.tlb_addr 中
					u-boot.bin (包括.code .data .ro-data .bss)
					(0x3D000B,244KB)
		5FFB 3000--------------------- // 5FFB 3000 存放在 new_gd->relocaddr 中
					malloc
					(0x100000B,1024KB)
		5FEB 3000---------------------
					new_gd
					(0xD0B,208B)
		5FEB 2F30--------------------- // 5FEB 2F30 存放在 r9中
					fdt
					(0xE80B,3KB)
		5FEB 20B0---------------------
					空洞
					(0x10,16B)
		5FEB 20A0--------------------- // 5FEB 20A0 存放在 start_addr_sp 中
					栈
					(254.695465MB)
		5000 0000---------------------
		*/




		

		mov r0, r9 		// 将 new_gd 的地址 存放到r0,作为第一个参数
		ldr r1, [r9, #56] // 将 new_gd 中的 relocaddr 存放到r1,作为第二个参数
		ldr pc,=board_init_r
			gd->flags &= ~GD_FLG_LOG_READY;
				// 虽然这里用的是gd,但是和用new_gd 效果一样
				// 因为 gd指针的值 是寄存器(r9中的值
				// new_gd指针的值 也是寄存器(r9)中的值
			initr_trace
				// null
			initr_reloc
				gd->flags |= GD_FLG_RELOC | GD_FLG_FULL_MALLOC_INIT;
				// 表示 code was relocated to RAM
				// 表示 full malloc() is ready
			initr_caches
				enable_caches
					icache_enable
						cache_enable((1 << 12));
							reg = get_cr();
							set_cr(reg | cache_bit);
					dcache_enable
						cache_enable((1 << 2));
							if !mmu_enabled() mmu_setup();
							reg = get_cr();
							set_cr(reg | cache_bit);
			// 此时mmu 没有enable
							
			initr_reloc_global_data
				monitor_flash_len = _end - __image_copy_start
				// 计算出 monitor_flash_len
				// 之后用来填充 gd->bd->bi_flashoffset
				// reserved area for startup monitor // 不知道用来干什么的
				// struct bd_info 定义在 include/asm-generic/u-boot.h
			initr_barrier
				// null
			initr_malloc
				malloc_start = gd->relocaddr - (1024*1024);
				// = 5FEB 3000
				// malloc 的区域 在 5FEB 3000 - 5FFB 3000 , 有 1024KB
				mem_malloc_init((ulong)map_sysmem(malloc_start, (1024*1024)), (1024*1024));
					mem_malloc_start = start;
						// 5FEB 3000
					mem_malloc_end = start + size;
						// 5FFB 3000
					mem_malloc_brk = start;
					memset((void *)mem_malloc_start, 0x0, size);
					malloc_bin_reloc();
						// null
			log_init
				// null
			initr_bootstage
				bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_R, "board_init_r");
			initr_console_record
				// null
			initr_of_live
				// null
			initr_dm
				gd->dm_root_f = gd->dm_root;
				gd->dm_root = 0;
				dm_init_and_scan(0);
				bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_R);

			board_init
				cs8900_pre_init // 这里不是cs8900,而是dm9000a
					// SROM 控制器的初始化
					(*(vu_long *)(0x70000000 +0x0)) &= ~(0xf << 4);
					(*(vu_long *)(0x70000000 +0x0)) |= (1 << 7) | (1 << 6) | (1 << 4);
					(*(vu_long *)(0x70000000 +0x8)) = (((0x0) << 28) + ((0x4) << 24) + ((0xE) << 16) + ((0x1) << 12) + ((0x4) << 8) + ((0x6) << 4) + (0x0));
					// 0x7000_0000 0x700F_FFFF SROM SFR
					
					
				gd->bd->bi_arch_number = 1626;
				// CONFIG_MACH_TYPE
				// unique id for this board 
				gd->bd->bi_boot_params = (0x50000000 +0x100);
				// where this board expects params
			initr_binman
				// null
			initr_dm_devices
				// null
			stdio_init_tables
				INIT_LIST_HEAD(&devs.list);
			serial_initialize 
				serial_init
			initr_announce
				// null
			power_init_board
				// null
			initr_mmc
				puts("MMC:   ");
				mmc_initialize(gd->bd);
			initr_env
				env_set_default(0,0)
				image_load_addr = env_get_ulong("loadaddr", 16, image_load_addr);
			initr_secondary_cpu
				cpu_secondary_init_r
					// null
			stdio_add_devices
				drv_system_init
				serial_stdio_init
			initr_jumptable
				jumptable_init
					gd->jt = malloc(sizeof(struct jt_funcs));
					gd->jt->get_version = get_version;
					gd->jt->getc = getchar;
					gd->jt->tstc = tstc;
					gd->jt->putc = putc;
					gd->jt->puts = puts;
					gd->jt->printf = printf;
					gd->jt->install_hdlr = dummy;
					gd->jt->free_hdlr = dummy;
					gd->jt->malloc = malloc;
					gd->jt->free = free;
					gd->jt->udelay = udelay;
					gd->jt->get_timer = get_timer;
					gd->jt->vprintf = vprintf;
					gd->jt->do_reset = do_reset;
					gd->jt->env_get = env_get;
					gd->jt->env_set = env_set;
					gd->jt->simple_strtoul = simple_strtoul;
					gd->jt->strict_strtoul = strict_strtoul;
					gd->jt->simple_strtol = simple_strtol;
					gd->jt->strcmp = strcmp;
					gd->jt->i2c_write = dummy;
					gd->jt->i2c_read = dummy;
					gd->jt->spi_setup_slave = dummy;
					gd->jt->spi_free_slave = dummy;
					gd->jt->spi_claim_bus = dummy;
					gd->jt->spi_release_bus = dummy;
					gd->jt->spi_xfer = dummy;
					gd->jt->ustrtoul = ustrtoul;
					gd->jt->ustrtoull = ustrtoull;
					gd->jt->strcpy = strcpy;
					gd->jt->mdelay = mdelay;
					gd->jt->memset = memset;
			console_init_r
				gd->flags |= GD_FLG_DEVINIT;
				print_pre_console_buffer(flushpoint);
			interrupt_init
				IRQ_STACK_START_IN = gd->irq_sp + 8;
					// gd->irq_sp 上面有16字节可用
					// 现在IRQ_STACK_START_IN在 gd->irq_sp 上面8字节
					// 且arm栈向下移动
					// 所以irq栈应该只有8个字节可用
					// 此举和 之前的 relocate_vectors有关
				enable_interrupts
					// null
			initr_ethaddr
				eth_env_get_enetaddr("ethaddr", bd->bi_enetaddr);
			initr_net
				puts("Net:   ");
				eth_initialize
			run_main_loop
				main_loop

猜你喜欢

转载自blog.csdn.net/u011011827/article/details/115132454