六,移植uboot-設置默認環境變量,完善u-boot


文檔時間:2018-08-14

交叉編譯器:arm-linux-gcc-4.3.2

Ubuntu版本:16.04

uboot版本:2013.10

 

1,修改 uboot 默認環境變量

前面章節得到的 uboot 串口打印信息如下:

可以看出,讀出的是壞的CRC,使用默認的環境變量,搜索 "using default environment" ,找到位於 common/env_common.c 文件 set_default_env 函數中,定位此處:

從上面的代碼可以猜到,默認的環境變量都保存在 default_environment 中,進入到 default_environment :

這里面的內容比較多,我們以其中的 bootargs 為例,搜索 bootargs 字樣,可以在其它單板中看到如下語句:

bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0

 //root 指定文件系統位置

//init 指定內核啟動后執行的第一個應用程序

//console 指定使用哪個終端,這里的 ttySAC0 指的就是串口0

其它宏也是這樣,比如我們熟悉的有:

"bootcmd=",用來啟動內核的命令

"bootdelay=",uboot啟動倒計時,默認值為5s,只有設置了bootcmd,它才有用

"baudrate=",波特率,默認為115200

"ipaddr=",IP 地址

"serverip=",服務器IP地址

"netmask=",子網掩碼

"gatewayip=",網關

"mtdparts=",mtd分區表

仿照其它單板在 include/configs/jz2440.h中添加相應的宏來設置默認環境變量,代碼如下(紅色為添加代碼):

#define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0" //bootargs
#define CONFIG_BOOTCOMMAND "nand read 0x30000000 0x60000 0x200000; bootm 0x30000000" //bootcmd
#define CONFIG_ETHADDR 00:0c:29:3b:22:2a //MAC地址

/* autoboot */
#define CONFIG_BOOTDELAY 5
#define CONFIG_BOOT_RETRY_TIME -1
#define CONFIG_RESET_TO_RETRY
#define CONFIG_ZERO_BOOTDELAY_CHECK

#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.2.90
#define CONFIG_SERVERIP 192.168.2.101

2,設置 mtdparts 分區

1),設置環境變量保存位置

 在之前的打印信息中雖然會出現,"bad CRC,using default environment",后面我們通過手動設置環境變量,也是可以執行我們想要的操作,但是我們並沒有使用過 save 命令將其保存到 flash 中,

這是因為在 flash 中,我們沒有對 uboot,params,kernel,rootfs 進行分區,save 命令不能保存到我們想要保存的位置,因此,為了不破壞flash原有的內容,此前未使用 save 命令

所以,首先我們先找到 save 在代碼中的位置,在 uboot 上,輸入 save -help 命令,打印如下:

搜索關鍵字 saveenv

 

發現很多文件中都有對 saveenv 函數的定義,由於我們只需要把環境變量保存到 flash 中,所以只需要關注與 flash 有關的文件,如上圖所示:

common/env_nand.c 文件,和common/env_flash.c 文件,前者是將環境變量保存到 nand 中,后者保存到 nor 中,打開 common 目錄下的 Makefile 文件,查看編譯這兩個文件所依賴的宏:

可以看出,編譯 env_flash.c 文件需要 CONFIG_ENV_IS_IN_FLASH 宏,編譯 env_nand.c 文件需要 CONFIG_ENV_IS_IN_NAND 宏,在 jz2440.h 文件中查找這兩個宏有無定義:

發現只有與nor 相關宏的定義,沒有與 NAND 相關宏的定義,而在本例程中,nand 啟動不支持 nor flash 操作,所以我們將環境變量保存在 nand flash 中,

參照其它單板對 nand 宏的定義,修改代碼:

//#define CONFIG_ENV_ADDR            (CONFIG_SYS_FLASH_BASE + 0x070000)
//#define CONFIG_ENV_IS_IN_FLASH
//#define CONFIG_ENV_SIZE            0x10000

#define CONFIG_ENV_IS_IN_NAND        /* U-Boot env in NAND Flash  */
#define CONFIG_ENV_SIZE            0x20000        //128kb
#define CONFIG_ENV_OFFSET        0x80000    //給uboot預留512kb

其中還有一個 CONFIG_ENV_RANGE 宏,這個宏可以不定義,如果不定義的話,在env_nand.c 中,會把它設置為 CONFIG_ENV_SIZE

重新編譯,燒寫uboot,就可以使用 save 命令保存環境變量了。

 2),設置分區,支持mtdparts命令

如果想要查看 uboot,kernel等的分區,在uboot中輸入 mtdparts 打印如下:

發現不支持該命令,修改代碼使 uboot 支持 mtdparts 命令,搜索 mtdparts,在 commong/cmd_mtdparts.c 中頻繁出現,猜測跟此文件有關,

打開 common 目錄下的 Makefile ,發現要想編譯 cmd_mtdparts.c 文件,需定義 CONFIG_CMD_MTDPARTS 宏,如下圖所示:

 

搜索 CONFIG_CMD_MTDPARTS ,參照別的單板對這個宏的設置,在 jz2440.h里 設置相關宏使其支持 mtdparts,修改代碼如下(紅色部分為增加代碼):

/* mtdparts command line support */
#define CONFIG_MTD_DEVICE        /* needed for mtdparts commands */
#define CONFIG_FLASH_CFI_MTD
#define MTDIDS_DEFAULT        "nand0=JZ2440-0"
/* default mtd partition table */
#define MTDPARTS_DEFAULT    "mtdparts=JZ2440-0:512k(u-boot)," \
                            "128k(params)," \
                            "4m(kernel)," \
                            "-(rootfs);" \

然后修改之前設置的 bootcmd (位於 jz2440.h 中),紅色部分為修改代碼:

#define CONFIG_BOOTCOMMAND "nand read 0x30000000 kernel; bootm 0x30000000" //bootcmd  

修改好之后,我們還要修改 board_init_r 函數(位於 arch/arm/lib/board.c 文件中),代碼修改如下(紅色部分為增加代碼):

    run_command("mtdparts default", 0);       //added by zhyy

    /* main_loop() can return to retry autoboot, if so just run it again. */
    for (;;) {
        main_loop();
    }

這樣,uboot每次啟動時都會執行一次mtdparts default 命令,使它根據默認參數來自動分區,這樣 mtdparts 就設置好了

編譯,燒寫,測試,在uboot中輸入 mtd/mtdparts,打印如下:

可以看出,uboot已經支持mtdparts 命令,打印信息與我們設置相符,接下來利用文件名來燒寫文件,輸入命令:

 燒寫 uboot 命令:

tftp 30000000 u-boot.bin
nand erase.part u-boot
nand write 30000000 uboot
reset        //重啟 uboot

燒寫內核命令:

tftp 30000000 uImage
nand erase.part kernel
nand write 30000000 kernel
bootm 30000000        //啟動內核

燒寫jffs2文件系統(目前還不支持yaffs文件系統的燒寫):

tftp 30000000 xxx.jffs2        //xxx表示文件系統名稱
nand erase.part rootfs
nand write.jffs2 30000000 4a0000 $filesize
reset

 

3,裁剪 uboot

經過上述步驟編譯出來的 uboot 大概有 378kb,這實在是太大了(因為 uboot的功能主要是啟動內核,給內核傳遞參數),所以接下來我們需要對 uboot 進行裁剪,uboot 很多文件都是基於 Makefile 里的宏來進行編譯的,而這些宏的定義基本上都在 include/configs/jz2440.h 中,所以我們需要修改 jz2440.h 文件,去掉不需要的宏:

1),去掉USB相關的宏

/************************************************************
 * USB support (currently only works with D-cache off)
 ************************************************************/
//#define CONFIG_USB_OHCI
//#define CONFIG_USB_OHCI_S3C24XX
//#define CONFIG_USB_KEYBOARD
//#define CONFIG_USB_STORAGE
//#define CONFIG_DOS_PARTITION

2),去掉 RTC 支持

/************************************************************
 * RTC
 ************************************************************/
//#define CONFIG_RTC_S3C24X0

3),去掉 BOOTP 選項

/*
 * BOOTP options
 */
//#define CONFIG_BOOTP_BOOTFILESIZE
//#define CONFIG_BOOTP_BOOTPATH
//#define CONFIG_BOOTP_GATEWAY
//#define CONFIG_BOOTP_HOSTNAME

4),去掉部分文件系統的支持

/*
 * File system
 */
//#define CONFIG_CMD_FAT
//#define CONFIG_CMD_EXT2
//#define CONFIG_CMD_UBI
//#define CONFIG_CMD_UBIFS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
//#define CONFIG_YAFFS2
//#define CONFIG_RBTREE

編譯,打印如下錯誤:

打開 include/usb.h,定位到169行,屏蔽以下代碼:

//#error USB Lowlevel not defined

編譯, 打印如下錯誤:

打開 common 目錄下的 Makefile,定位到 cmd_date 關鍵字,如下:

可以看出編譯 cmd_date.c 需要CONFIG_CMD_DATE 的支持,在 jz2440.h 中找到該宏,將其屏蔽:

//#define CONFIG_CMD_DATE

 編譯,打印如下錯誤:

打開 common 目錄下的 Makefile,定位到 usb 關鍵字,如下:

 

可以看出編譯 usb.c 需要宏 CONFIG_CMD_USB 的支持,在 jz2440.h 中找到該宏,將其屏蔽:

//#define CONFIG_CMD_USB

編譯,成功,看一下uboot的大小,只有221kb,裁剪的差不多了

 

4,支持 yaffs 文件系統

在我們的uboot中輸入 nand write.yaffs 30000000 0 0 打印如下:

可以看出,我們的uboot目前不支持 yaffs 文件系統的燒寫,接下來,修改代碼,使其支持 yaffs文件系統的燒寫。

我們在使用 nand 命令時,會進入到 do_nand 函數(位於 common/cmd_nand.c 文件中),打開 cmd_nand.c 文件,定位到 do_nand 函數,代碼如下:

可見,要想支持yaffs,需要添加 宏 CONFIG_CMD_NAND_YAFFS,在 jz2440.h 中添加該宏:

#define CONFIG_CMD_NAND_YAFFS

 然后進入 nand_write_skip_bad 函數(位於 drivers/mtd/nand/nand_util.c 文件中):

int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
        size_t *actual, loff_t lim, u_char *buffer, int flags)
{

  ............  

if (!need_skip && !(flags & WITH_DROP_FFS)) {    //需要修改 rval = nand_write(nand, offset, length, buffer);    //正常拷貝,不考慮OOB問題 if (rval == 0) return 0;        //拷貝完,return *length = 0; printf("NAND write to offset %llx failed %d\n", offset, rval); return rval; } while (left_to_write > 0) { size_t block_offset = offset & (nand->erasesize - 1); size_t write_size, truncated_write_size; WATCHDOG_RESET(); if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) { printf("Skip bad block 0x%08llx\n", offset & ~(nand->erasesize - 1)); offset += nand->erasesize - block_offset; continue; } if (left_to_write < (blocksize - block_offset)) write_size = left_to_write; else write_size = blocksize - block_offset; #ifdef CONFIG_CMD_NAND_YAFFS if (flags & WITH_YAFFS_OOB) { int page, pages; size_t pagesize = nand->writesize; size_t pagesize_oob = pagesize + nand->oobsize; struct mtd_oob_ops ops; ops.len = pagesize; ops.ooblen = nand->oobsize; ops.mode = MTD_OPS_AUTO_OOB;    //需要修改 ops.ooboffs = 0; pages = write_size / pagesize_oob; for (page = 0; page < pages; page++) {    //循環燒寫每一頁 WATCHDOG_RESET(); ops.datbuf = p_buffer; ops.oobbuf = ops.datbuf + pagesize; rval = mtd_write_oob(nand, offset, &ops);    //燒寫 OOB if (rval != 0)       break;          //燒寫失敗,退出for循環     ............... }

將上面的 if (!need_skip && !(flags & WITH_DROP_FFS)) 改為 if (!need_skip && !(flags & WITH_DROP_FFS) &&!(flags&WITH_YAFFS_OOB))

因為避免輸入 nand write.yaffs 直接進入該判斷,然后不執行下面的 while (left_to_write > 0)語句

將上面的MTD_OPS_AUTO_OOB 修改為 MTD_OOB_RAW(我也不知道為啥,參考別人的)

(PS:此段參考別人)

編譯,燒寫,測試,輸入以下命令:

tftp 30000000 xxx.yaffs2        //xxx代表文件系統名稱
nand erase.part rootfs
nand write.yaffs 30000000 4a0000 $filesize

打印如下信息:

表示下載成功,說明uboot已經支持 yaffs 文件系統了。

到此為止,uboot 的移植已經基本完成了。

 

5,打補丁

 打補丁之前,使用以下命令清除make編譯的文件

make distclean
rm u-boot.dis

 然后輸入以下命令進行打補丁:

cd ..
mv u-boot-2013.10 u-boot-2013.10_zhyy
tar -xjf u-boot-2013.10.tar.bz2            //解壓創建源文件
diff -urN u-boot-2013.10 u-boot-2013.10_zhyy > u-boot-2013.10_zhyy.patch            //注意,源文件在前,新文件在后

 使用包命令,進入到 u-boot-2013.10 ,輸入一下命令:

patch -p1 < u-boot-2013.10_zhyy.patch

 

 uboot 移植到此結束。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM