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

    xiaoxiao2021-03-25  100

    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命令行模式** ``` c 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; <div class="se-preview-section-delimiter"></div>

    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" ); <div class="se-preview-section-delimiter"></div>

    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} <div class="se-preview-section-delimiter"></div>

    知道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中有如下定义:

    <div class="se-preview-section-delimiter"></div> #define CFG_BOOTLOADER_SIZE 0x20000 <div class="se-preview-section-delimiter"></div> #define CFG_CONFIG_SIZE 0x10000 <div class="se-preview-section-delimiter"></div> #define CFG_FACTORY_SIZE 0x10000 <div class="se-preview-section-delimiter"></div> #define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_BOOTLOADER_SIZE) <div class="se-preview-section-delimiter"></div> #define CFG_FACTORY_ADDR (CFG_FLASH_BASE + CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE) <div class="se-preview-section-delimiter"></div> #define CFG_KERN_ADDR (CFG_FLASH_BASE + (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE)) <div class="se-preview-section-delimiter"></div> #ifdef DUAL_IMAGE_SUPPORT <div class="se-preview-section-delimiter"></div> #define CFG_KERN2_ADDR (CFG_FLASH2_BASE + (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE)) <div class="se-preview-section-delimiter"></div>

    可以很直观的看出各信息在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相关教程,感谢您的查阅。

    转载请注明原文地址: https://ju.6miu.com/read-17844.html

    最新回复(0)