uboot移植之init_sequence_f函数数组分析(番外篇)

uboot移植之前期准备篇1

uboot移植之Makefile分析概述篇2

uboot移植之源码流程分析篇3(超详细!)

uboot移植之修改支持SDRAM篇4

uboot移植之修改支持NorFlash篇5

uboot移植之修改支持NandFlash识别篇6(超详细)


目录

内存分布总结:


前程回顾:

剔除掉一些多余的宏开关之后,以及一些多余的函数之后,init_sequence_f数组内容如下:

static init_fnc_t init_sequence_f[] = {
    setup_mon_len,      //设置gd结构体成员mon_len  

                                   //gd->mon_len = (ulong)&__bss_end - CONFIG_SYS_MONITOR_BASE

                                   //CONFIG_SYS_MONITOR_BASE为0, 所以gd->mon_len为u-boot.bin+bss段大小
    board_early_init_f,
    env_init,                //初始化环境变量,其默认的环境变量在include/env_default.h中定义
    init_baud_rate,        //波特率初始化为115200
    serial_init,             //串行通信设置,初始化
    console_init_f,        // 第一阶段平台的初始化
    display_options,     //打印uboot信息
    display_text_info,    //可以通过在 include/common.h 定义DEBUG 开启显示及打印一些debug信息功能,
    print_cpuinfo,        //显示cpu的id以及频率
    announce_dram_init, //调用puts打印一些信息
    /* TODO: unify all these dram functions? */
    dram_init,        //gd->ram_size = PHYS_SDRAM_1_SIZE;  (将sdram的大小64M,存在gd->ram_size中)

    setup_dest_addr,
    reserve_round_4k,
    reserve_mmu,    
    reserve_uboot,
    reserve_malloc,
    reserve_board,
    reserve_global_data,
    reserve_fdt,
    reserve_stacks,
    setup_dram_config,   //bank_size块大小设置
    show_dram_config,   //显示sdram的一些信息
    display_new_sp,       //打印出当前gd->start_addr_sp
    reloc_fdt,           
    setup_reloc,
    NULL,
}

下面分析几个比较重要的函数:

1、board_early_init_f开启MPLL,UPLL。(移植需修改)

PLL在上电复位后开始是不稳定的,所以在上电 复位后12Mhz直接作为Fclk,这时MPLL是不起作用的。如果要想是MPLL起作用,那么要先配置锁定时间寄存器(LOCKTIME),根据公式在寄存器中设置好对应的MPS位

再配置MPLLCON寄存器值,然后等待LOCKTIME时间 后,新的Fclk开始工作,另外,时钟分频系数早在start.s中已经配置好了。(翻译:用户可以通过写入PMS值和PLL的locktime来改变频率,并自动插入锁相环锁定时间。在锁定时间内,时钟不提供给s3c2440a中的内部块。)

2、init_baud_rate,串口波特率初始化为CONFIG_BAUDRATE,即115200

在uboot菜单输入print打印环境变量,发现结果匹配

3、display_options,打印uboot信息

version_string其实就是存放了一些关于uboot字符串的一个缓冲区,再启动的时候打印出uboot的一些版本信息等等。

定义:const char __weak version_string[] = U_BOOT_VERSION_STRING;

uboot启动输出:

4、setup_dest_addr,设置gd->relocaddr,gd->ram_top的指向,指向sdram最顶端0x34000000。

宏CONFIG_SYS_SDRAM_BASE在include\configs\smdk2440.h被定义为0x30000000。在加上从get_effective_memsize函数中返回的gd->ram_size,刚好是0x34000000。gd->ram_size在dram_init函数已经被赋值了。所以,执行完这函数之后:

gd->relocaddr=0x34000000,gd->ram_top=0x34000000。

5、reserve_round_4k,4KB对齐。

4kb对齐,其临界值是0x00001000,所以,gd->relocaddr对齐之后,还是不变,gd->relocaddr=0x34000000。小测试:

6、reserve_mmu, 预留空间存放TLB,以及64kb对齐。

宏PGTABLE_SIZE被定义为4096 * 4,1kb=1024字节,所以保留了16kb的空间给TLB后,gd->relocaddr=0x33ffc000。

64kb对齐后,gd->relocaddr=0x33ff0000。

7、reserve_uboot,预留空间给uboot。

这是我个人的想法,关于uboot的大小不能单纯地看u-boot.bin,因为u-boot.bin并没有包含bss段大小,而u-boot.elf当中又包含了一些多余的调试信息,所以先执行命令:

arm-linux-objdump -h u-boot (u-boot是elf格式)

Idx Name          Size        VMA          LMA           File off        Algn
9    .bss          0004edf8  00078a70  00078a70  00000000   2**8     //size的单位是字节

所以,bss段大小为323064字节,即315kb,uboot大小(含bss段)为836kb。gd->relocaddr=0x33f1f000。

4kb对齐后,gd->relocaddr和gd->start_addr_sp都等于0x33f1f000。

8、reserve_malloc,保留malloc区域。

宏TOTAL_MALLOC_LEN被定义为4 * 1024 * 1024,相减后,gd->start_addr_sp=0x33b1f000。在uboot中,分配释放堆这些操作都要自己去实现,该段空间就是用来实现这个功能,因为c库是在挂接根文件系统之后才能使用的。

9、reserve_board,预留bd_info结构体大小空间,并清零。

bd_t其实就是bd_info结构体,里面存放了许多单板相关的变量成员。关于sizeof(gd_t)的大小,我们可以通过查看反汇编文件得知:

立即数后缺省情况下表示十进制,所以sizeof(gd_t)=80byte,相减后,gd->start_addr_sp=0x33b1efb0。

10、reserve_global_data,预留空间给gd_t结构体。

同上方法,查出sizeof(gd_t)=168byte,相减后,gd->start_addr_sp=0x33b1ef08。在函数数组的最后会调用setup_reloc()将gd结构体复制到这来。

11、reserve_fdt,应该并没有预留空间给设备树驱动。

我的做法:搜索 gd->fdt_blob = 的索引

---- gd->fdt_blob = Matches (9 in 3 files) ----
reloc_fdt in board_f.c (u-boot-2016.07\common) :         gd->fdt_blob = gd->new_fdt;  //排除
do_fdt in fdt.c (u-boot-2016.07\cmd) :             gd->fdt_blob = blob; 
do_fdt in fdt.c (u-boot-2016.07\cmd) :         gd->fdt_blob = blob;     
fdtdec_setup in fdtdec.c (u-boot-2016.07\lib) :     gd->fdt_blob = __dtb_dt_begin;
fdtdec_setup in fdtdec.c (u-boot-2016.07\lib) :         gd->fdt_blob = (ulong *)&_image_binary_end;
fdtdec_setup in fdtdec.c (u-boot-2016.07\lib) :         gd->fdt_blob = (ulong *)&__bss_end;
fdtdec_setup in fdtdec.c (u-boot-2016.07\lib) :     gd->fdt_blob = (ulong *)&_end;
fdtdec_setup in fdtdec.c (u-boot-2016.07\lib) :     gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16,

do_fdt开头的类似函数大多都是在uboot菜单输入命令的时候,调用对应的do_前缀函数来处理输入的命令及参数。或者在程序中显示地调用run_command();函数去调用执行,

其余的来自于fdtdec_setup函数:

其中,由于宏没有定义,所以并没有对gd->fdt_blob的赋值。

12、reserve_stacks,预留空间给栈。空间大小和特定的架构有关。

相减后,gd->start_addr_sp=0x33b1eef8。与操作后,gd->start_addr_sp=0x33b1eef0。调用函数:

16字节对齐后,gd->irq_sp=0x33b1eef0。之后,留出3字节给栈,为了对齐再加上1字节,共4字节。

所以,gd->start_addr_sp=0x33b1eee0。

13、reloc_fdt,什么也没做。

判断决定是否将gd->fdt_blob里面的内容,拷贝到之前划分出来的区域段中。

在void board_init_f( ulong boot_flags ) 函数中gd->flags = boot_flags,而 r0=0 作为参数传入board_init_f函数,所以并没有执行重定位设备树。

14、setup_reloc,重定位gd结构体。

宏CONFIG_SYS_TEXT_BASE被定义为0x0,gd->new_gd指向在reserve_global_data分配出来的新空间,所以该函数主要是通过调用memcpy(gd->new_gd, (char *)gd, sizeof(gd_t)); 将gd结构体中的东西存放在之前分配的空间处。

内存分布总结:

最后,结合上面分析,可以得出内存划分图如下:

注:为了测试方便,板子中采用的uboot版本和分析的源码版本不匹配,后期有时间会修改回来,但是这并不影响我们分析整个流程。

参考资料:

《ARM9嵌入式系统设计与应用开发》 熊茂华 杨震伦 主编

《汇编语言程序设计——基于ARM体系结构》 文全刚 赫志刚 主编

《嵌入式Linux应用开发完全手册》 韦东山著

《S3C2440A_UserManual_Rev13》

 

 

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
uboot是一种常用的开源引导加载程序,用于嵌入式系统的引导启动。其中,board_init_r和board_init_f是uboot中的两个重要函数。 board_init_r函数是在uboot启动过程中执行的第一个函数。它负责执行一系列的初始化工作,例如初始化系统时钟、设置内存映射等。此函数被用于配置和初始化各个硬件模块,包括中断控制器、串口控制器、定时器等,以确保系统正常运行。该函数还读取并解析配置文件,加载设备树等操作,为后续的引导加载准备好必要的条件。 board_init_f函数是在board_init_r函数之后调用的。它用于进一步初始化系统,并执行一些与硬件相关的操作。例如,该函数可能会初始化网络接口、USB接口、存储设备等,并设置系统的默认环境变量。此外,board_init_f函数还负责将uboot的控制权交给操作系统的引导加载程序,从而完成uboot的使命。 通过调用board_init_r和board_init_f函数,uboot能够在系统启动时完成各种硬件的初始化和配置工作。这两个函数是uboot启动过程中的重要环节,确保系统能够顺利地加载操作系统并运行。同时,它们也为开发者提供了扩展uboot的接口,可以在这两个函数中添加自定义的初始化代码,以满足系统特定的需求。 总结来说,board_init_r和board_init_f是uboot中两个重要的函数,用于初始化和配置嵌入式系统的硬件,并为操作系统的加载做好准备。它们是uboot启动过程中不可或缺的一部分,保证系统的正常启动和运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值