u-boot新结构浏览
u-boot新结构浏览
213 /* Set stackpointer in internal RAM to call board_init_f */
214 call_board_init_f:
215 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
216 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
217 ldr r0,=0x00000000
218 bl board_init_f
CONFIG_SYS_INIT_SP_ADDR在板级头文件定义
228 /* additions for new relocation code, must be added to all boards */
229 #define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
230 #define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x1000 - \
231 GENERATED_GBL_DATA_SIZE)
232
233 #define CONFIG_BOARD_EARLY_INIT_F 根据TQ2440硬件信息定义,PHY_SDRAM_1 = 0X3000 0000,那么0x3000 0000 + 4k -128B
此为堆栈地址,GENERATED_GBL_DATA_SIZE为全局数据的大小即gd_t全局指针所指向的单元大小
216行使sp指针8字节对齐以符合ABI规则,R0 = 0,作为参数传递给board_init_f().
arch/arm/lib/board.c:
CONFIG_SYS_INIT_SP_ADDR 指向栈底,也是全局数据指针的区的首地址,
265 void board_init_f(ulong bootflag)
266 {
267 bd_t *bd;
268 init_fnc_t **init_fnc_ptr;
269 gd_t *id;
270 ulong addr, addr_sp;
271 #ifdef CONFIG_PRAM
272 ulong reg;
273 #endif
274
275 bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");
276
277 /* Pointer is writable since we allocated a register for it */
278 gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07); /*以R8作为全局数据指针的存储器,并始终保持*/
279 /* compiler optimization barrier needed for GCC >= 3.4 */
280 __asm__ __volatile__("": : :"memory");
281
282 memset((void *)gd, 0, sizeof(gd_t)); /* 清零全局数据区*/
283
284 gd->mon_len = _bss_end_ofs; /* 整个u-boot映像大小*/
285 #ifdef CONFIG_OF_EMBED
286 /* Get a pointer to the FDT */
287 gd->fdt_blob = _binary_dt_dtb_start;
288 #elif defined CONFIG_OF_SEPARATE
289 /* FDT is at end of image */
290 gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
291 #endif
292 /* Allow the early environment to override the fdt address */
293 gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,
294 (uintptr_t)gd->fdt_blob);
在旧版u-boot中,init_fnc_ptr()的执行是放在启动代码第二段中,难道这里就相当与原来的stage2?
在慢慢分析
295
296 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
297 if ((*init_fnc_ptr)() != 0) {
298 hang ();
299 }
300 }
301
302 #ifdef CONFIG_OF_CONTROL
303 /* For now, put this check after the console is ready */
304 if (fdtdec_prepare_fdt()) {
305 panic("** CONFIG_OF_CONTROL defined but no FDT - please see "
306 "doc/README.fdt-control");
307 }
308 #endif
309
310 debug("monitor len: %08lX\n", gd->mon_len);
311 /*
312 * Ram is setup, size stored in gd !!
313 */
314 debug("ramsize: %08lX\n", gd->ram_size);
init_fnc_t *init_sequence[]这个函数指针数组变化不大,只跟踪关心的部分,
234 init_fnc_t *init_sequence[] = {
235 arch_cpu_init, /* basic arch cpu dependent setup */
236
237 #if defined(CONFIG_BOARD_EARLY_INIT_F)
238 board_early_init_f, /*原来叫board_init */
239 #endif
跟踪到board/samsung/smdk2410/smdk2410.c中
board_early_init_f(),另外还有board_init(),有点小疑问,怎么由两个板级初始化,研读了代码,
发现这两个函数都执行了,在不同的阶段.贴一下代码:
70 int board_early_init_f(void)
71 {
72 struct s3c24x0_clock_power * const clk_power =
73 s3c24x0_get_base_clock_power();
74 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
75
76 /* to reduce PLL lock time, adjust the LOCKTIME register */
77 writel(0xFFFFFF, &clk_power->locktime);
78
79 /* configure MPLL */
80 writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
81 &clk_power->mpllcon);
82
83 /* some delay between MPLL and UPLL */
84 pll_delay(4000);
85
86 /* configure UPLL */
87 writel((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV,
88 &clk_power->upllcon);
89
90 /* some delay between MPLL and UPLL */
91 pll_delay(8000);
。。。
111 }
113 int board_init(void)
114 {
115 /* arch number of SMDK2410-Board */
116 gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
117
118 /* adress of boot parameters */
119 gd->bd->bi_boot_params = 0x30000100;
120
121 icache_enable();
122 dcache_enable();
123
124 return 0;
125 } 熟悉u-boot的可以看出了,其实这两个函数的功能就是以前board_init的功能,即时钟初始和GPIO配置,和传递参数配置,
只是现在进行了拆分,这样u-boot越来越规范,硬件的初始化与上层明确划分,不得不说这是一个好的方向。由此有些问题也能解释了,
void board_init_f();
void board_init_r(); 这是板级初始化的前半部和后半部,board_init_f()进行最基本的初始化,可以说是SOC的初始化,比如内存
串口,初始化gd_t,规划内存等...
然后返回汇编部分进行代码搬运,并初始化bss等,此时又回调用void board_init_r();且看说明
453 /*
454 ************************************************************************
455 *
456 * This is the next part if the initialization sequence: we are now
457 * running from RAM and have a "normal" C environment, i. e. global
458 * data can be written, BSS has been cleared, the stack size in not
459 * that critical any more, etc.
460 *
461 ************************************************************************
462 */ 代码到这里已经“正常”运行在SDRAM上了,即所需的环境在前面已经搭建好了,这里会进行更高以及的初始化:
比如nand ,net,LCD然后进入命令模式。了解了大概流程,才恍然其结构与以前u-boot大致一样,不过更加标准了。
还是返回到board_init_f();看其具体流程。
328
329 addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size; /*整个sdram大小0x3000 0000 + 0x400 0000,
gd->ram_size在dram_init()中被初始化*/
349 #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
350 /* reserve TLB table */
351 addr -= (4096 * 4);
352
353 /* round down to next 64 kB limit */
354 addr &= ~(0x10000 - 1);
355
356 gd->tlb_addr = addr;
357 debug("TLB table at: %08lx\n", addr);
358 #endif
360 /* round down to next 4 kB limit */
361 addr &= ~(4096 - 1); /* 舍去掉不足4KB的地址空间,为什么是4KB.? */
362 debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
378 addr -= gd->mon_len; /* 减去u-boot镜像大小,镜像包括Code,Data,bss区,此时addr应该和TEXT_BASE相同*/
379 addr &= ~(4096 - 1); /* 舍去不足4K的地址空间*/
380
381 debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);
/* 调试信息:u-boot加载地址且预留多少空间给U-BOOT */
382
383 #ifndef CONFIG_SPL_BUILD
384 /*
385 * reserve memory for malloc() arena
386 */
387 addr_sp = addr - TOTAL_MALLOC_LEN; /* 没有特殊定义,这里heap应该为4M,因为会作为解压缓冲区,所以分配大些*/
388 debug("Reserving %dk for malloc() at: %08lx\n",
389 TOTAL_MALLOC_LEN >> 10, addr_sp);
390 /*
391 * (permanently) allocate a Board Info struct
392 * and a permanent copy of the "global" data
393 */
394 addr_sp -= sizeof (bd_t); /* 分配heap以后,继续分配bd_t结构体,此时addr_sp指向该结构首地址*/
395 bd = (bd_t *) addr_sp;
396 gd->bd = bd; /* 将该首地址赋值给gd_t->bd初始化*/
397 debug("Reserving %zu Bytes for Board Info at: %08lx\n",
398 sizeof (bd_t), addr_sp);
399
400 #ifdef CONFIG_MACH_TYPE
401 gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
402 #endif
403
404 addr_sp -= sizeof (gd_t); /* 接着再次分配gd_t结构体,前面已经分配一次,是因为刚进入C代码,堆栈还具体划分,只做临时保存*/
405 id = (gd_t *) addr_sp; /* 剩下的空间,才是真正的用户栈区,S3C2440采用栈方式为FD,满栈递减向下生长*/
406 debug("Reserving %zu Bytes for Global Data at: %08lx\n",
407 sizeof (gd_t), addr_sp);
408
409 /* setup stackpointer for exeptions */
410 gd->irq_sp = addr_sp; /* 如果开启中断,比如使用USB下载功能,这里还不是真正的栈底,还要划分中断栈区*/
411 #ifdef CONFIG_USE_IRQ
412 addr_sp -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);
413 debug("Reserving %zu Bytes for IRQ stack at: %08lx\n",
414 CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ, addr_sp);
415 #endif
416 /* leave 3 words for abort-stack */
417 addr_sp -= 12; /* 留3个字的指令预取中止栈*/
418
419 /* 8-byte alignment for ABI compliance */
420 addr_sp &= ~0x07;
421 #else
422 addr_sp += 128; /* leave 32 words for abort-stack */
423 gd->irq_sp = addr_sp;
424 #endif
425
426 debug("New Stack Pointer is: %08lx\n", addr_sp);
427
428 #ifdef CONFIG_POST
429 post_bootmode_init();
430 post_run(NULL, POST_ROM | post_bootmode_get(0));
431 #endif
432
433 gd->bd->bi_baudrate = gd->baudrate; /* 串口波特率*/
434 /* Ram ist board specific, so move it to board code ... */
435 dram_init_banksize();
436 display_dram_config(); /* and display it */
437
438 gd->relocaddr = addr; /* 镜像重载地址,即TEXT_BASE */
439 gd->start_addr_sp = addr_sp; /* 栈指针*/
440 gd->reloc_off = addr - _TEXT_BASE; /* 重载映像相对与预先指定的地址(TEXT_BASE)的偏移地址,并且始终大于等于0 */
441 debug("relocation Offset is: %08lx\n", gd->reloc_off);
442 memcpy(id, (void *)gd, sizeof(gd_t)); /* 将临时gd_t数据复制进全局结构体*/
443
444 relocate_code(addr_sp, id, addr); /* 调用汇编代码,相当于返回start.进行代码重载,参数为R0-栈指针,
R1-全局数据指针,R2-加载地址. */
445
446 /* NOTREACHED - relocate_code() does not return */
447 }
这里又回到了汇编部分,注意这里传回的地址并不是通过宏CONFIG_SYS_TEXT_BASE指定的地址*/
230 relocate_code:
231 mov r4, r0 /* save addr_sp */
232 mov r5, r1 /* save addr of gd */
233 mov r6, r2 /* save addr of destination */
234
235 /* Set up the stack
236 stack_setup:
237 mov sp, r4 /* 初始化栈指针*/
238
239 adr r0, _start /* 当前_start标号地址,如果没搬运代码,这里为0x0 */
240 cmp r0, r6
241 beq clear_bss /* skip relocation */
242 mov r1, r6 /* r1 <- scratch for copy_loop */
243 ldr r3, _bss_start_ofs
244 add r2, r0, r3 /* r2 <- source end address */
245
246 copy_loop: /* NOR flash搬运到SDRAM,这里只搬运了代码区,数据域并没也编译*/
247 ldmia r0!, {r9-r10} /* copy from source address [r0] */
248 stmia r1!, {r9-r10} /* copy to target address [r1] */
249 cmp r0, r2 /* until source end address [r2] */
250 blo copy_loop
251
252 #ifndef CONFIG_SPL_BUILD
253 /*
254 * fix .rel.dyn relocations ,在链接时指定-pie,编译生成位置无关的映像*/
255 */
256 ldr r0, _TEXT_BASE /* r0 <- Text base */
257 sub r9, r6, r0 /* r9 <- relocation offset */
258 ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
259 add r10, r10, r0 /* r10 <- sym table in FLASH */
260 ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
261 add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
262 ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
263 add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
264 fixloop:
265 ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
266 add r0, r0, r9 /* r0 <- location to fix up in RAM */
267 ldr r1, [r2, #4]
268 and r7, r1, #0xff
269 cmp r7, #23 /* relative fixup? */
270 beq fixrel
271 cmp r7, #2 /* absolute fixup? */
272 beq fixabs
273 /* ignore unknown type of fixup */
274 b fixnext
275 fixabs:
276 /* absolute fix: set location to (offset) symbol value */
277 mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
278 add r1, r10, r1 /* r1 <- address of symbol in table */
279 ldr r1, [r1, #4] /* r1 <- symbol value */
280 add r1, r1, r9 /* r1 <- relocated sym addr */
281 b fixnext
282 fixrel:
283 /* relative fix: increase location by offset */
284 ldr r1, [r0]
285 add r1, r1, r9
286 fixnext:
287 str r1, [r0]
288 add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
289 cmp r2, r3
290 blo fixloop
291 #endif
292
u-boot新结构浏览相关推荐
- Spring Boot项目结构
目录 Spring Boot项目结构 一.代码层结构 二.资源目录结构 三.测试测序目录结构 四.项目结构示例 Spring Boot项目结构 一.代码层结构 根目录:src/main/java 入口 ...
- android boot.img 结构
android 的boot.img 包括 boot header,kernel, ramdisk 首先来看看Makefile是如何产生我们的boot.img的: boot镜像不是普通意义上的文件系统, ...
- 阿里云发布 Spring Boot 新脚手架,真香
作者 | 良名 阿里巴巴技术专家 背景 相信很多人都使用过 start.spring.io 来初始化自己的 Spring Boot 工程,这个工具为开发者提供了丰富的可选组件,并且可以选择多种打包方式 ...
- idea springboot 发布webservice 发布服务_阿里云发布 Spring Boot 新脚手架,真香
作者 | 良名 阿里巴巴技术专家 背景 相信很多人都使用过 start.spring.io 来初始化自己的 Spring Boot 工程,这个工具为开发者提供了丰富的可选组件,并且可以选择多种打包方 ...
- springboot项目层次结构_spring boot项目结构
项目之初,一般我们会根据团队的构成和项目的需求把技术选型.框架定下来,技术选型框架确定后,在团队成员参与开发之前,项目的一些基础服务和组织架构需要资深的负责人或者团队讨论一起分工完成.这样在开始开发后 ...
- spring boot jar包_「Spring Boot 新特性」 jar 大小自动瘦身
自动分析瘦身 Spring Boot 项目最终构建处理 JAR 包大小一直是个诟病,需要把所有依赖包内置最终输出可运行的 jar.当然可以使用其他的插件扩展 实现依赖 JAR 和 可运行 jar 分离 ...
- boot sprint 项目结构_Spring Boot 项目结构
(1)代码层的结构 根目录:com.springboot 1.工程启动类(Application.java)置于com.springboot.build包下 2.实体类(domain)置于com.sp ...
- android boot.img 结构,android boot.img文件结构、拆包、打包
boot.img is not a compressed filesystem image like system.img. It is read by the bootloader, and con ...
- Spring Boot 项目结构介绍
POM文件 <!-- 父工程 --><parent><groupId>org.springframework.boot</groupId><art ...
- 小宇宙爆发!Spring Boot 新特性:节省95%内存占用
作者 | 冷冷 来源 | https://mp.weixin.qq.com/s/0m6ofmMlQTDUQwC7oRRIrQ GraalVM[1] 是一种高性能的虚拟机,它可以显著的提高程序的性能和运 ...
最新文章
- lasTools laszip.exe 点云las/laz的无损压缩/解压缩工具
- mac下homebrew一些总结
- 20080608-昨日回顾今日计划
- php 保护变量,保护PHP中的“包含污染”变量
- 浅谈个性化推荐系统中的非采样学习
- 旗舰杀手!红米旗舰定名 干翻全场?
- CIO必看:跨国集团采购部报表系统的建设经验分享
- android 1024 github,1024 怎么能少了这款高颜值、敲实用的 GitHub 第三方客户端呢?...
- 计算机仿真实验之一 霍尔效应测磁场,2004_01大学物理实验教程_11539522.pdf
- Python数据分析实战(1)数据分析概述
- GitHub项目之12306抢票软件
- 可汗学院公开课——统计学学习:62-81
- 服务器装win7没有硬盘分区,深度win7安装没有磁盘分区怎么办?
- Delphi著名皮肤控件库大全
- 王兴:为什么中国的To B企业都活得这么惨?(演讲全文)
- MATLAB绘制小胖墩
- 云计算助推金融行业信息化发展
- 将Sleuth添加到项目里做链路追踪的三种方式(Greenwich.SR5版)
- 论文解读 | LGD:用于物体检测的标签引导自蒸馏
- 线索二叉树(线索链表遍历,二叉树线索化)
热门文章
- cpp-http 库的使用
- 局域网计算机如何传输文件,局域网文件传输,教您局域网如何传输文件
- UI设计新手怎么求职 UI面试必备攻略是什么
- 查询计算机的配置命令是什么,查看电脑配置指令大全
- “元宇宙”是什么?涂子沛:人可在数据空间“复活”
- K-means算法实现及分析
- 数据字典的作用是什么,它有哪些条目?
- html5控制gif速度,用gifsicle优化GIF动图
- QCA6174A方案PCI-E接口双频蓝牙WiFi二合一模块8274B-PR
- matlab中wavread函数,关于wavread函数的用法