u-boot-2014.10代码分析及移植说明

1 ENTRY(_main)2
3 /*
4 * Set up initial C runtime environment and call board_init_f(0).5  */
6
7 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
8     ldr    sp, =(CONFIG_SPL_STACK)9 #else
10     ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)11 #endif
12     bic    sp, sp, #7    /*8-byte alignment for ABI compliance*/
13 mov    r2, sp14     sub    sp, sp, #GD_SIZE    /*allocate one GD above SP*/
15     bic    sp, sp, #7    /*8-byte alignment for ABI compliance*/
16     mov    r9, sp        /*GD is above SP*/
17 mov    r1, sp18     mov    r0, #0

1 clr_gd:2     cmp    r1, r2            /*while not at end of GD*/
3     strlo    r0, [r1]        /*clear 32-bit GD word*/
4     addlo    r1, r1, #4        /*move to next*/
5     blo    clr_gd

_main位于crt0.S中,该段主要是给u-boot中最根本最重要的变量gd分配空间并清零。

gd是一个结构体变量,其地址被放置于r9寄存器中(如果没记错的话,以前的版本是放入r8寄存器的),它包含了u-boot程序中最重要的全局信息,包括时钟相关变量,页表,重定位信息等,另外还包括传递给内核的板级信息。

1 #if defined(CONFIG_SYS_MALLOC_F_LEN) && !defined(CONFIG_SPL_BUILD)
2 sub    sp, sp, #CONFIG_SYS_MALLOC_F_LEN3 str    sp, [r9, #GD_MALLOC_BASE]4 #endif
5     /*mov r0, #0 not needed due to above code*/
6     bl    board_init_f

定义relocation之前所需的堆空间地址,之后转入board_init_f程序,从此处起,SPL即BL1阶段代码和U-BOOT即BL2阶段代码分开走向了不同的路线。

如果未定义CONFIG_SYS_GENERIC_BOARD,则为/arch/arm/lib/board.c

如果定了CONFIG_SYS_GENERIC_BOARD,则为common/board_f.c。

想了想,先以/arch/arm/lib/board.c为例讲吧,毕竟这个是针对具体architecture(真实原因是common下那个我还没看过)

1 void board_init_f(ulongbootflag)2 {3     bd_t *bd;4     init_fnc_t **init_fnc_ptr;5     gd_t *id;6     ulongaddr, addr_sp;7 #ifdef CONFIG_PRAM8     ulongreg;9 #endif
10     void *new_fdt =NULL;11     size_t fdt_size = 0;12
13     memset((void *)gd, 0, sizeof(gd_t));

此处又重新将gd清零了,似乎有点多余啊,难道是针对SPL的?(原因是针对common/board_f.c的,该文件中的函数没有gd初始化)

1     gd->mon_len = (ulong)&__bss_end - (ulong)_start;2 #ifdef CONFIG_OF_EMBED3     /*Get a pointer to the FDT*/
4     gd->fdt_blob =__dtb_dt_begin;5 #elif defined CONFIG_OF_SEPARATE
6     /*FDT is at end of image*/
7     gd->fdt_blob = &_end;8 #endif
9     /*Allow the early environment to override the fdt address*/
10     gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,11                         (uintptr_t)gd->fdt_blob);

gd->mon_len为uboot大小。

CONFIG_OF_EMBED决定着是否将dtb编入uboot,libs-$(CONFIG_OF_EMBED) += dts/

CONFIG_OF_SEPARATE也是在同时编译dtb,但是分开编译,并未编入uboot中,Makefile中可以看出,但是没找到为何是放在_end后。

1     for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {2         if ((*init_fnc_ptr)() != 0) {3 hang ();4 }5     }

该段则是进行一部分初始化,init_sequence为一个函数指针数组,

1 init_fnc_t *init_sequence[] ={2     arch_cpu_init,        /*basic arch cpu dependent setup*/
3 mark_bootstage,4 #ifdef CONFIG_OF_CONTROL5 fdtdec_check_fdt,6 #endif
7 #if defined(CONFIG_BOARD_EARLY_INIT_F)
8 board_early_init_f,9 #endif
10     timer_init,        /*initialize timer*/
11 #ifdef CONFIG_BOARD_POSTCLK_INIT12 board_postclk_init,13 #endif
14 #ifdef CONFIG_FSL_ESDHC15 get_clocks,16 #endif
17     env_init,        /*initialize environment*/
18     init_baudrate,        /*initialze baudrate settings*/
19     serial_init,        /*serial communications setup*/
20     console_init_f,        /*stage 1 init of console*/
21     display_banner,        /*say that we are here*/
22     print_cpuinfo,        /*display cpu info (and speed)*/
23 #if defined(CONFIG_DISPLAY_BOARDINFO)
24     checkboard,        /*display board info*/
25 #endif
26 #if defined(CONFIG_HARD_I2C) || defined(CONFIG_SYS_I2C)
27 init_func_i2c,28 #endif
29     dram_init,        /*configure available RAM banks*/
30 NULL,31 };

注意该处实际是个指向函数指针的数组,其好处我能想到的一点是末尾的NULL,通过指针为NULL判断作为结束标志。以下逐一分析各个初始化函数,

1.arch_cpu_init

该函数自然就是需要针对各个芯片自己实现了,通常可以在该函数中实现cache使能的控制

2.mark_bootstage

1     /*Record the board_init_f() bootstage (after arch_cpu_init())*/
2 static int mark_bootstage(void)3 {4     bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");5
6     return 0;7 }

算是uboot的流程中做个标记,bootstage_mark_name函数最终可以通过和板级自己实现的一个函数挂接,实现通过打印或者led灯等各种方式来反应uboot的进程。

3.fdtdec_check_fdt

检测fdt是否存在

4.board_early_init_f

早期的一些初始化

如需要,定义宏CONFIG_BOARD_EARLY_INIT_F,并实现该函数

5.timer_init

timer初始化,题外:u-boot中timer驱动的作用是为了实现delay,因此timer驱动也是围绕udelay展开的。

6.board_postclk_init

早期时钟相关初始化

如需要,定义宏CONFIG_BOARD_POSTCLK_INIT,并实现该函数

7.get_clocks

看起来实际主要是为了获取gd->arch.sdhc_clk时钟,即为了获取sdmmc时钟,不过并不是必要。

如需要,定义宏CONFIG_FSL_ESDHC,并实现该函数

8.env_init

初始化gd中的两个成员,即环境变量表的地址,以及valid值

9.init_baudrate

初始化gd中的波特率成员变量

该处设计BAUDRATE的一个宏定义

10.serial_init

初始化串口驱动

对应串口驱动中必须添加的两个函数default_serial_console,以及serial_device结构体的start成员函数

11.console_init_f

其实没啥,只是在存在CONFIG_PRE_CONSOLE_BUFFER的情况下会有个buffer初始化的过程

12.display_banner

打印uboot版本信息等

13.print_cpuinfo

这个是各个芯片自己实现,打印一些cpu相关信息

14.checkboard

打印board相关信息

15.init_func_i2c

如果有且需要i2c的话,初始化

16.dram_init

自己实现,gd->ram_size的初始化,当然也有吧dram_bank的初始化写在这里

整个init_sequence初始化就结束了。

剩下的下期再说。

转载于:https://www.cnblogs.com/iambobor/p/4185763.html

程序员的圣诞节后-零相关推荐

  1. 圣诞祝福网页_程序员式圣诞祝福,你没试过这种吧?

    一年一度的圣诞节又来啦!在这个越来越被重视的节日里,每个人都有自己浪漫的方式,当然程序员也不例外. 让我们看看程序员如何为节日增添不同的气氛吧. 初级程序员的祝福 1.用canvas功能画出简单的圣诞 ...

  2. 程序员圣诞节相册源码_程序员分享圣诞刷屏源码,这次朋友圈千万不要再@微信官方了!...

    明天就到圣诞节了 每年到这个时候,朋友圈里都会掀起@微信官方要「圣诞皮肤」的骚操作,最常见的就是加个圣诞小帽了. 当然这种事情很多 P 图软件都可以做到,但在使用这些软件时,经常会被要求绑定微信等个人 ...

  3. 为什么程序员都喜欢节后跳槽?内行人告诉你原因

    哪个工作相对来说高薪?你脑海中的职业之一会有程序员.哪个职业跳槽最频繁?你脑海中的职业之一还是会有程序员! 程序员喜欢跳槽,这在行业里面已经算不上什么秘密. 互联网技术发展迅速,有很多的地方都需要优秀 ...

  4. 程序员过圣诞 | 用HTML写出绽放的烟花

    文章目录 一.前言 二.创意名 三.效果展示 四.烟花代码 五.总结 一.前言 2022年圣诞节到来啦,圣诞节是基督教纪念耶稣诞生的重要节日.亦称耶稣圣诞节.主降生节,天主教亦称耶稣圣诞瞻礼.耶稣诞生 ...

  5. proteus如何添加stm32_一个应用软件程序员的单片机STM32零基础入门

    为什么开始考虑搞嵌入式开发? 近5年来,从云计算.大数据到机器学习.AI,各种新潮的技术概念一波--接一波. 作为一名好奇心旺盛的软件程序员,每一个技术概念流行起来都会去凑凑热闹. 但,在我的技术栈里 ...

  6. 程序员祝福圣诞快乐的方式(内涵完整代码)

    2022年圣诞节到来啦,很高兴这次我们又能一起度过~ 这次利用前端的一些简单的代码给不会前端的广大男性朋友知道如何哄对象❤️ 一.前言 圣诞将至,玩计算的大家还在发愁如何实现自己送个心爱的那个女孩什么 ...

  7. 【转载】给程序员的圣诞大礼★★春夏

    计算机寓言之春 真爱与新生 1 两名学生 曾经有一名学生,他在课余时间里穿上古时侯的盔甲,随后他如今那些和他有类似想法的人在一起,模仿古代社会里的贵州和太太们. 另一名学生是计算机科学专业的,他问一名 ...

  8. 8年web前端开发老程序员告诉你如何零基础学习web前端

    随着web前端的飞速发展,学习web前端的人员也是越来越多,在移动 互联网 时代,相信我们每个人的手机上都装有数十个APP,这些APP的开发其实也和当下热门的 Web 前端开发息息相关. 事实上,如今 ...

  9. java学了之后老忘_老程序员的建议,零基础学java,常见的误区和解决方法

    写一篇经验分享的文章,现在很多人学习java 第一,觉得java很难, 第二,觉得java 找工作不好找, 第三,也有人说java饱和了, 现在确实是行业的要求越来越高了, 早在07年的时候把java ...

最新文章

  1. Del.icio.us应用工具杂烩
  2. 为节约而生:从标准Attention到稀疏Attention
  3. linux重启mysqlsystemctl_解决linux(centos7)重新安装mysql systemctl start mysqld.service时报错...
  4. Android内核学习笔记
  5. python入门基础系列_03python—9个基础常识-python小白入门系列
  6. splunk中 如何隐藏input_翻糖制作中,如何避免裂缝,如何隐藏裂缝,如何防粘?...
  7. loadRunner目录分析二
  8. STL_stack/queue
  9. java 流 flush_Java CharArrayWriter flush()方法
  10. 不懂就问,Spring 是如何判定原型循环依赖和构造方法循环依赖的?
  11. vector所存储对象地址在vector操作过程中发生变化
  12. R语言数据可视化---交互式图表recharts包
  13. Linux 进程间通信 无名管道(pipe)
  14. 视频教程-以太坊区块链实战视频教程(全球同步升级)-区块链
  15. 电影《检察风云》投资价值简单分析
  16. 帆软报表 异常汇总及方案.
  17. 每日一练——回文链表
  18. CF85D Sum of Medians
  19. ROS进阶学习的过程
  20. 给网页设计师和前端开发者看的前端性能优化

热门文章

  1. 「 iOS知识小集 」2018 · 第 38 期
  2. OAuth 2.0介绍
  3. Linux系统管理第六周作业【Linux微职位】
  4. 主类main方法里面可以有不带public的子类 但是不能有接口
  5. perform update operations on columns of type JSONB
  6. 多出口冗余网络设计方案
  7. Unity3D 学习教程 14 C# 旋转镜头
  8. 使用print写文件
  9. 实用window2008之七 :路由器配置应用实例
  10. python替换缺失值,处理空值+生成图形+图形标准化