XiaomiRouter自學(xué)之路(08-U-boot啟動(dòng)數(shù)值具體說(shuō)明)

題圖:gratisography

XiaomiRouter自學(xué)之路(08-U-boot啟動(dòng)數(shù)值具體說(shuō)明)

在上一章節(jié)的[U-boot啟動(dòng)過(guò)程]中,我們分析到U-boot倒計(jì)時(shí)后的參數(shù)選擇,這一章節(jié)我們將對(duì)各參數(shù)選擇后執(zhí)行的具體功能代碼進(jìn)行分析,讓我們更深入的理解代碼在內(nèi)存、Flash之間的搬運(yùn)過(guò)程。

再來(lái)查看下各數(shù)值代表的含義

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. 

將其分類下,其實(shí)就很明了:

  • 兩種文件需要更新:U-boot、System
  • 兩種更新方式:Serial、tftp
  • 更新到兩個(gè)位置:SDRAM、Flash
  • 數(shù)值3:從Flash啟動(dòng)系統(tǒng)
  • 數(shù)值4:進(jìn)入U(xiǎn)-boot命令行模式

1.進(jìn)入U(xiǎn)-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就是循環(huán)執(zhí)行main_loop()函數(shù),該函數(shù)位于common/main.c中

main_loop函數(shù)就是一直檢測(cè)用戶所輸入的命令,然后進(jìn)行解析執(zhí)行對(duì)于的代碼,那哪些命令才可以被解析正確呢,如果用戶想自己加入一個(gè)命令呢?

這邊使用的是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的定義如下,第一個(gè)參數(shù)name即要輸入的命令,maxargs為最大長(zhǎng)度,rep表示可重復(fù)性,cmd為輸入命令后索要執(zhí)行的函數(shù)如這邊的do_ping()函數(shù),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的定義后,我們就知道如何添加自己的命令,以及輸入每個(gè)命令的具體代碼在哪里尋找。

2.兩種

上面總結(jié)了以下兩種:

  • 兩種文件需要更新:U-boot、System
  • 兩種更新方式:Serial、tftp
  • 更新到兩個(gè)位置:SDRAM、Flash

解釋下就是通過(guò)Serial/tftp的方式將U-boot/System燒錄到SDRAM/Flash,所以也很直觀。

我們先來(lái)看下兩種方式即Serial和tftp,當(dāng)選擇不同的方式時(shí),就會(huì)選擇不同的接口函數(shù)。

觀察代碼我們可以發(fā)現(xiàn):

  • 當(dāng)選擇tftp模式時(shí),先通過(guò)tftp_config()函數(shù)設(shè)置網(wǎng)絡(luò)環(huán)境,然后再通過(guò)do_tftpb()函數(shù)進(jìn)行數(shù)據(jù)的上傳。
  • 當(dāng)選擇serial模式時(shí),則通過(guò)do_load_serial_bin(()函數(shù)進(jìn)行數(shù)據(jù)的上傳。

這邊先普及一個(gè)知識(shí),我們數(shù)據(jù)的轉(zhuǎn)移過(guò)程是先通過(guò)tftp/serial從本地上傳到運(yùn)行內(nèi)存SDRAM中,然后在從SDRAM寫(xiě)入介質(zhì)Flash中,所以上面的這兩個(gè)接口函數(shù)都是將文件上傳到運(yùn)行內(nèi)存SDRAM中。

兩種方式知道了,那接著看兩個(gè)位置SDRAM和Flash。

  • SDRAM上面已經(jīng)說(shuō)明了,通過(guò)do_tftpb()do_load_serial_bin(()函數(shù)即可。
  • 由于使用的是spi flash,所以寫(xiě)入Flash則使用接口函數(shù)raspi_erase_write()來(lái)實(shí)現(xiàn)。

既然更新方式和更新位置知道了,那剩下的更新文件U-boot和System是如何區(qū)分的,細(xì)心的你可能會(huì)發(fā)現(xiàn)在調(diào)用do_tftpb()、do_load_serial_bin(()、raspi_erase_write()時(shí)都是有帶不同的參數(shù)的,這些參數(shù)就是用來(lái)區(qū)分我們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啟動(dòng)系統(tǒng)

    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);
    }

啟動(dòng)系統(tǒng)也是比較直觀的,調(diào)用do_bootm()函數(shù),該函數(shù)位于common/cmd_bootm.c中,do_bootm()函數(shù)將地址參數(shù)傳輸進(jìn)去,里面通過(guò)raspi_read()函數(shù)進(jìn)行讀取特定的位置到內(nèi)存,然后執(zhí)行,即所說(shuō)的啟動(dòng)系統(tǒng),當(dāng)然在啟動(dòng)的過(guò)程會(huì)有一系列的驗(yàn)證等動(dòng)作。

U-boot啟動(dòng)數(shù)值具體說(shuō)明的分析就到這邊,有感悟時(shí)會(huì)持續(xù)會(huì)更新。

注:以上內(nèi)容都是本人在學(xué)習(xí)過(guò)程積累的一些心得,難免會(huì)有參考到其他文章的一些知識(shí),如有侵權(quán),請(qǐng)及時(shí)通知我,我將及時(shí)刪除或標(biāo)注內(nèi)容出處,如有錯(cuò)誤之處也請(qǐng)指出,進(jìn)行探討學(xué)習(xí)。文章只是起一個(gè)引導(dǎo)作用,詳細(xì)的數(shù)據(jù)解析內(nèi)容還請(qǐng)查看XiaomiRouter相關(guān)教程,感謝您的查閱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容