XiaomiRouter自学之路(08-U-boot启动数值具体说明)

在上一章节的[U-boot启动过程]中,我们分析到U-boot倒计时后的参数选择,这一章节我们将对各参数选择后执行的具体功能代码进行分析,让我们更深入的理解代码在内存、Flash之间的搬运过程。

再来查看下各数值代表的含义

0: System Load Linux then write to Flash via Serial.
1: Load system code to SDRAM via TFTP.
2:Load system code then write to Flash via TFTP.
3: Boot system code via Flash (default).
4: Entr boot command line interface.
7: Load Boot Loader code then write to Flash via Serial. 
8: System Load UBoot to SDRAM via TFTP. 
9: Load Boot Loader code then write to Flash via TFTP.

将其分类下,其实就很明了:

  • 两种文件需要更新:U-boot、System

  • 两种更新方式:Serial、tftp

  • 更新到两个位置:SDRAM、Flash

  • 数值3:从Flash启动系统

  • 数值4:进入U-boot命令行模式

1.进入U-boot命令行模式

case '4':
    printf("   \n%d: System Enter Boot Command Line Interface.\n", SEL_ENTER_CLI);
    printf ("\n%s\n", version_string);
    /* main_loop() can return to retry autoboot, if so just run it again. */
    for (;;) {
        main_loop ();
    }
break;

case 4就是循环执行main_loop()函数,该函数位于common/main.c中

main_loop函数就是一直检测用户所输入的命令,然后进行解析执行对于的代码,那哪些命令才可以被解析正确呢,如果用户想自己加入一个命令呢?

这边使用的是U_BOOT_CMD宏定义,如ping命令的定义如下:

U_BOOT_CMD(
    ping,   2,  1,  do_ping,
    "ping\t- send ICMP ECHO_REQUEST to network host\n",
    "pingAddress\n"
);

U_BOOT_CMD的定义如下,第一个参数name即要输入的命令,maxargs为最大长度,rep表示可重复性,cmd为输入命令后索要执行的函数如这边的do_ping()函数,usage/help都是提示信息。

define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

知道U_BOOT_CMD的定义后,我们就知道如何添加自己的命令,以及输入每个命令的具体代码在哪里寻找。

2.两种

上面总结了以下两种:

  • 两种文件需要更新:U-boot、System

  • 两种更新方式:Serial、tftp

  • 更新到两个位置:SDRAM、Flash

解释下就是通过Serial/tftp的方式将U-boot/System烧录到SDRAM/Flash,所以也很直观。

我们先来看下两种方式即Serial和tftp,当选择不同的方式时,就会选择不同的接口函数。

观察代码我们可以发现:

  • 当选择tftp模式时,先通过tftp_config()函数设置网络环境,然后再通过do_tftpb()函数进行数据的上传。

  • 当选择serial模式时,则通过do_load_serial_bin(()函数进行数据的上传。

这边先普及一个知识,我们数据的转移过程是先通过tftp/serial从本地上传到运行内存SDRAM中,然后在从SDRAM写入介质Flash中,所以上面的这两个接口函数都是将文件上传到运行内存SDRAM中。

两种方式知道了,那接着看两个位置SDRAM和Flash。

  • SDRAM上面已经说明了,通过do_tftpb()do_load_serial_bin(()函数即可。

  • 由于使用的是spi flash,所以写入Flash则使用接口函数raspi_erase_write()来实现。

既然更新方式和更新位置知道了,那剩下的更新文件U-boot和System是如何区分的,细心的你可能会发现在调用do_tftpb()do_load_serial_bin(()raspi_erase_write()时都是有带不同的参数的,这些参数就是用来区分我们U-boot/System所要存放的具体地址。

在include/configs/rt2880.h中有如下定义:

#define CFG_BOOTLOADER_SIZE 0x20000
#define CFG_CONFIG_SIZE     0x10000
#define CFG_FACTORY_SIZE    0x10000

#define CFG_ENV_ADDR        (CFG_FLASH_BASE + CFG_BOOTLOADER_SIZE)
#define CFG_FACTORY_ADDR    (CFG_FLASH_BASE + CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE)
#define CFG_KERN_ADDR       (CFG_FLASH_BASE + (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE))
#ifdef DUAL_IMAGE_SUPPORT
#define CFG_KERN2_ADDR      (CFG_FLASH2_BASE + (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE))

可以很直观的看出各信息在Flash中的存放位置,Uboot-config-factory-kernel。

3.从Flash启动系统

    if(BootType == '3') {
        char *argv[2];
        sprintf(addr_str, "0x%X", CFG_KERN_ADDR);
        argv[1] = &addr_str[0];
        printf("   \n3: System Boot system code via Flash.\n");
        do_bootm(cmdtp, 0, 2, argv);
    }

启动系统也是比较直观的,调用do_bootm()函数,该函数位于common/cmd_bootm.c中,do_bootm()函数将地址参数传输进去,里面通过raspi_read()函数进行读取特定的位置到内存,然后执行,即所说的启动系统,当然在启动的过程会有一系列的验证等动作。

U-boot启动数值具体说明的分析就到这边,有感悟时会持续会更新。


本文章由作者:佐须之男 整理编辑,原文地址: XiaomiRouter自学之路(08-U-boot启动数值具体说明)
本站的文章和资源来自互联网或者站长的原创,按照 CC BY -NC -SA 3.0 CN协议发布和共享,转载或引用本站文章应遵循相同协议。如果有侵犯版权的资 源请尽快联系站长,我们会在24h内删除有争议的资源。欢迎大家多多交流,期待共同学习进步。

相关推荐