u-boot:官網下載的u-boot-2014.4(ftp://ftp.denx.de/pub/u-boot/)
單板:樹莓派b
1、 添加自己的單板
首先解壓uboot源碼,進入根目錄,在幫助文檔README中有如何添加單板的說明:
If the system board that you have is not listed, then you will need
to port U-Boot to your hardware platform. To do this, follow these
steps:
- Add a new configuration option for your board to the toplevel
“boards.cfg” file, using the existing entries as examples.
Follow the instructions there to keep the boards in order.- Create a new directory to hold your board specific code. Add any
files you need. In your board directory, you will need at least
the “Makefile”, a “.c”, “flash.c” and “u-boot.lds”.- Create a new configuration file “include/configs/.h” for
your board- If you’re porting U-Boot to a new CPU, then also create a new
directory to hold your CPU specific code. Add any files you need.- Run “make _config” with your new name.
- Type “make”, and you should get a working “u-boot.srec” file
to be installed on your target system.- Debug and solve any problems that might arise.
[Of course, this last step is much harder than it sounds.]
1)首先在頂層目錄下的boards.cfg文件中添加樹莓派單板的配置信息,我這裏仿造rpi_b:
Status,Arch,CPU:SPLCPU,SoC,Vendor,Board name,Target,Options, Maintainers
Active arm arm1176 bcm2835 raspberrypi rpi_zy rpi_zy - zhangyi
這裏從左到右分別表示:
Status : 配置使能狀態
Arch:體系架構
CPU:SPLCPU:CPU名稱
SoC:SOC芯片名稱
Vendor:廠商
Board name:單板名稱
Target:配置目標
Options:選項
Maintainers:維護者
2)在頂層board創建一個用於存儲單板相關代碼文件的目錄,這裏我直接拷貝board/raspberrypi/rpi_b 目錄然後修改裏面的文件名和Makefile文件:
$ cp -r /board/raspberrypi/rpi_b /board/raspberrypi/rpi_b
$ mv /board/raspberrypi/rpi_b/rpi_b.c
/board/raspberrypi/rpi_b/rpi_zy.c
然後修改Makefile文件:
- - - obj-y := rpi_b.o
+++ obj-y := rpi_zy.o
3)爲自己的單板創建配置文件include/configs/xxxx.h, 我這裏也是直接拷貝rpi_b的配置文件:
cp include/configs/rpi_b.h include/configs/rpi_zy.h
4)精簡使用不到的uboot源碼結構:
(1)在arch目錄下只保留arm目錄:
[apple@apple u-boot-2014.04]$ cd arch/
[apple@apple arch]$ ls
arm
(2)在arch/arm/目錄下只保留如下內容:
[apple@apple arch]$ cd arm/
[apple@apple arm]$ ls
config.mk cpu dts imx-common include lib
(3)在arch/arm/cpu目錄下只保留如下內容:
[apple@apple arm]$ cd cpu/
[apple@apple cpu]$ ls
arm1176 built-in.o Makefile u-boot.lds u-boot-spl.lds
(4)在arch/arm/include/asm目錄下以arch開頭的只保留arch-bcm2835
(5)u-boot-2014.04/board 目錄下只保留raspberrypi:
[apple@apple u-boot-2014.04]$ cd board
[apple@apple board]$ ls
raspberrypi
(6)u-boot-2014.04/board/raspberrypi目錄下只保留rpi_zy:
[apple@apple board]$ cd raspberrypi/
[apple@apple raspberrypi]$ ls
rpi_zy
(7)u-boot-2014.04/include/configs 目錄下只保留rpi_zy.h
[apple@apple u-boot-2014.04]$ cd include/configs/
[apple@apple configs]$ ls
rpi_zy.h
5)修改頂層Makefile文件,添加交叉編譯器支持:
318 # Make variables (CC, etc...)
319 CROSS_COMPILE = arm-linux-gnueabihf-
320 AS = $(CROSS_COMPILE)as
321 # Always use GNU ld
6) 在頂層目錄下編寫簡單的編譯腳本文件,執行編譯工作:
#!/bin/sh
make distclean
make rpi_zy_config
make all
運行該腳本文件即可在uboot根目錄下生成u-boot.bin二進制文件。
7) 安裝與運行
將編譯出來的u-boot.bin拷貝到SD卡的FAT分區下,然後修改config.txt文件,添加(或修改)以下配置項:
kernel=u-boot.bin
同時需要保證SD卡FAT分區中包含以下文件:bootcode.bin、config.txt、start.elf和u-boot.bin(這些文件的作用見《樹莓派的啓動引導方式》)。
上電啓動,uboot正常啓動並能夠在終端打印信息。
但是此時的uboot尚不能正常讀寫SD卡、USB和Ethernet(樹莓派的Ethernet網絡芯片是基於USB的)。
2、 修改並支持SD卡讀寫
參見http://people.freebsd.org/~gonzo/arm/patches/u-boot-pi-sdhci-hs-workaround.diff
修改drivers/mmc/bcm2835_sdhci.c的182行:
添加SDHCI_QUIRK_NO_HISPD_BIT
181 host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT;
修改完成後,該uboot即可正常讀寫樹莓派的SD卡。
例如:讀取存放在SD卡FAT分區中的uImage文件到ram中的loadaddr位置處。
3、 移植USB-HOST和USB-Ethernet驅動
源文件:https://github.com/gonzoua/u-boot-pi/tree/rpi
這裏GitHub上的uboot是國外開發者基於2013.01-rc1版本修改的,並且支持usb和Ethernet。
uboot中usb-host和usb-ethernet的驅動在u-boot-pi-rpi/drivers/usb/eth和u-boot-pi-rpi/drivers/usb/host目錄下,樹莓派相關的是dwc_otg-hcd.c、dwc_otg.c、dwc_otg_regs.h、dwc_otg_core_if.h和dwc_otg.h這幾個host驅動文件以及smsc95xx.c的Ethernet驅動文件。
其中smsc95xx.c在2014.4版的uboot中已經存在了,並且和u-boot-pi-rpi中的並無太大不同,所以主要的工作就在移植usb-host驅動和配置uboot添加usb和ethernet相關的commond。
1)首先將dwc_otg-hcd.c、dwc_otg.c、dwc_otg_regs.h、dwc_otg_core_if.h和dwc_otg.h這幾個文件拷貝到u-boot-2014.04/drivers/usb/host目錄下,同時修改Makefile:
[apple@apple host]$ cp dwc* ~/raspberry/build/u-boot-2014.04/drivers/usb/host
[apple@apple host]$ vim ~/raspberry/build/u-boot-2014.04/drivers/usb/host/Makefile
+++ obj-$(CONFIG_USB_DWC_OTG) += dwc_otg.o dwc_otg-hcd.o
2)修改u-boot-2014.04/include/configs/rpi_zy.h,修改如下:
+++ /* USB Networking options */
+++ #define CONFIG_USB_HOST_ETHER
+++ #define CONFIG_USB_ETHER_SMSC95XX
+++ #define CONFIG_USB_DWC_OTG
+++ #define CONFIG_USB_STORAGE
+++ #define CONFIG_CMD_USB
+++ #define CONFIG_CMD_NET
+++ #define CONFIG_CMD_PING
+++ #define CONFIG_CMD_DHCP
--- #undef CONFIG_CMD_NET
--- #undef CONFIG_CMD_DHCP
--- #undef CONFIG_CMD_NET
--- #undef CONFIG_CMD_PING
3)修改完成後,重新編譯並運行
這裏有遇到一個問題,在執行usb start時,當uboot檢測到ethernet時會出現failed to set MAC address的WARNING,當然後續也無法使用了。
通過比較2分smsc95xx.c文件,發現在獲取Mac地址的smsc95xx_init_mac_address函數中,會嘗試調用smsc95xx_read_eeprom函數從eeprom中獲取MAC地址。
287 static int smsc95xx_read_eeprom(struct ueth_data *dev, u32 offset, u32 length,
288 u8 *data)
289 {
290 u32 val;
291 int i, ret;
292
293 ret = smsc95xx_eeprom_confirm_not_busy(dev);
294 if (ret)
295 return ret;
296
297 for (i = 0; i < length; i++) {
298 val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_);
299 smsc95xx_write_reg(dev, E2P_CMD, val);
300
301 ret = smsc95xx_wait_eeprom(dev);
302 if (ret < 0)
303 return ret;
304
305 smsc95xx_read_reg(dev, E2P_DATA, &val);
306 data[i] = val & 0xFF;
307 offset++;
308 }
309 return 0;
400 }
其中在smsc95xx_eeprom_confirm_not_busy函數中增加了如下代碼片段:
257 do {
258 smsc95xx_read_reg(dev, E2P_CMD, &val);
259 +++ if (!(val & E2P_CMD_LOADED_)) {
260 +++ debug("No EEPROM present\n");
261 +++ return -1;
262 +++ }
如果smsc95xx_read_reg發現不存在EEPROM,則直接返回失敗,同時爲了安全起見不會隨機生成MAC地址。
將以上代碼移植到2014.04的代碼段中,同時打開uboot的debug模式,就會打印出No EEPROM present,顯然uboot無法從EEPROM中獲取到Mac地址,因爲在樹莓派的9512芯片上並沒有接EEPROM。
解決方式是手動添加環境變量usbethaddr,同時在uboot的preboot命令爲:
#define CONFIG_PREBOOT \
"if load mmc 0:1 ${loadaddr} /uEnv.txt; then " \
"env import -t ${loadaddr} ${filesize}; " \
"fi"
在uboot啓動main loop前會執行這條命令從uEnv.txt文件中倒入環境變量,所以在SD卡的FAT分區中添加uEnv.txt文件,同時向裏面寫入:
usbethaddr=b8:27:eb:b7:b5:2e
ipaddr=192.168.1.25
serverip=192.168.1.17
問題解決,重新運行後打印輸出如下:
參考文獻:
1、《嵌入式Linux學習筆記(基於S5PV210、TQ210).pdf》
2、http://blog.sina.com.cn/s/blog_7cedb56d0102uzye.html
3、http://my.oschina.net/funnky/blog/141982?p=1