
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)教程,感謝您的查閱。