Das U-Boot není ponorka
Obvyklý pohled na roli univerzálního bootloaderu U-Boot se omezuje na natažení binárního obrazu linuxového jádra z externího úložiště (NAND Flash, SD karta atd.) do operační paměti a jeho spuštění. Ale během vývoje je U-Boot neocenitelným pomocníkem. Umožňuje natáhnout velké binárky ze sítě a zkrátit tak dobu mezi rebooty, které jsou ve fázi ladění velmi časté. Odpadnou zdlouhavé zápisy do Flash paměti nebo na SD kartu.
U-Boot umí natahovat z LAN binární obrazy programů pomocí síťových protokolů BOOTP, DHCP a TFTP. Pro naše potřeby zprovozníme TFTP server, který poběží na linuxovém PC. Nejdříve si připravíme ethernetové rozhraní modulu SAMA5.
Na Baseboardu vypneme spínač napájení.
Připojíme ethernetové rozhraní modulu, které je vyvedeno na konektoru J4, na RJ45 konektor P6 na Baseboardu. Rozhraní RJ45 konektoru je na Baseboardu vyvedeno na pinhead J49. Použijeme barevné propojovací káblíky a spojíme tyto vývody
- pin 34 na J4 (ETHTD+) s pinem 1 na J49 (TD+)
- pin 35 na J4 (ETHTD-) s pinem 3 na J49 (TD-)
- pin 36 na J4 (ETHRD+) s pinem 4 na J49 (RD+)
- pin 37 na J4 (ETHRD-) s pinem 6 na J49 (RD-)
- pin 38 na J4 (ETHTCT) s pinem 2 na J49 (TCT)
- pin 39 na J4 (ETHRCT) s pinem 5 na J49 (TD+)
LEDky, které indikují stav ethernetového rozhraní, jsou dostupné na Baseboardu na pinheadu J32. Připojíme
- pin 41 na J4 (ETHLEDS100) na pin 1 na J32
- pin 42 na J4 (ETHLEDLINK) na pin 2 na J32
Zasuneme ethernetový patch kabel do konektoru P6 na Baseboardu a do ethernetového hubu.
Připojíme Reset vývod modulu, který je na pinu 32 konektoru J2, na jeden z pinů na pinheadu J27 na Baseboardu. To nám umožní používat tlačítko SW2 k resetování modulu.
Spustíme emulátor terminálu (třeba Putty), připojíme se na sériový port DBGU a zapneme spínač napájení na Baseboardu. Jakmile se spustí U-Boot, zastavíme odpočítávání stiskem kterékoli klávesy, abych se dostali na prompt U-Bootu.
Dokumentaci k U-Bootu najdete na webových stránkách autora.
Nastavíme MAC adresu ethernetového rozhraní modulu SAMA5. Možná vlastníte blok MAC adres, a tak použijete jednu z nich. Nebo při vývoji použijete takovou MAC adresu, která nebude kolidovat s některým zařízením ve vaší LAN. Stručné vysvětlení, jak zvolit MAC adresu, najdete v jednom z našich starších článků.
My pro naše exprimenty použijeme lokálně spravovanou MAC adresu, která se dá jednoduše zapamatovat:
U-Boot> setenv ethaddr 02:10:20:30:40:50
Nastavíme IP adresu modulu a síťovou masku. Hodnoty musíme zvolit tak, aby odpovídaly prostředí naší LAN.
U-Boot> setenv ipaddr 192.168.168.30 U-Boot> setenv netmask 255.255.255.0
Smažeme proměnné bootcmd, bootargs a findfdt. Nyní je nepotřebujeme a jejich nový obsah nastavíme, až bude třeba.
U-Boot> setenv bootcmd U-Boot> setenv bootargs U-Boot> setenv findfdt
Do proměnné bootdelay nastavíme hodnotu -1. Tím zakážeme odpočítávání a automatické bootování a U-Boot po spuštění zobrazí svůj prompt.
U-Boot> setenv bootdelay -1
Příkazem printenv zobrazíme aktuální stav proměnných a příkazem saveenv je uložíme do SPI Flash paměti.
U-Boot> printenv baudrate=115200 bootdelay=-1 ek_name=sama5d31ek ethact=macb0 ethaddr=02:10:20:30:40:50 ipaddr=192.168.168.30 mb_rev=a netmask=255.255.255.0 Environment size: 157/12284 bytes U-Boot> saveenv Saving Environment to SPI Flash... Erasing SPI flash...Writing to SPI flash...done U-Boot>
Resetujeme modul.
U-Boot> reset
Otestujeme funkčnost ethernetového rozhraní a připojení do LAN příkazem ping.
U-Boot> ping 192.168.168.29 macb0: PHY present at 0 macb0:0 is connected to macb0. Reconnecting to macb0 macb0: Starting autonegotiation... macb0: Autonegotiation complete macb0: link up, 100Mbps full-duplex (lpa: 0x45e1) Using macb0 device host 192.168.168.29 is alive U-Boot>
Vynikající výsledek - LAN je dostupná.
Pokud na vašem PC ještě neběží TFTP server, tak ho nainstalujte. Na Debianu je to jednoduché. Jako uživatel root proveďte příkaz
# apt-get install tftpd
který nainstaluje službu TFTP. Požadavky jsou spravovány super-serverem inetd, který spouští TFTP démona. Podívejte se do souboru /etc/inetd.conf a najděte řádek s definicí služby TFTP.
tftp dgram udp wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd /srv/tftp
Poslední řetězec na řádku specifikuje adresář, do kterého budeme kopírovat soubory, ke kterým mají mít TFTP klienti přístup. V našem případě to je adresář /srv/tftp. Pokud tento adresář dosud neexistuje, vytvořte ho a nastavte jeho přístupová práva.
# cd /srv # mkdir tftp # chmod 777 tftp
Na linuxovém PC nainstalujeme sadu utilit pro U-Boot. Hlavně potřebujeme program mkimage, kterým se vytváří soubory, které umí U-Boot natáhnout do paměti. V Debianu je mkimage obsažen v balíčku u-boot-tools.
# apt-get install u-boot-tools
Otestujeme TFTP server. Zkusíme natáhnout z TFTP serveru nějakou binárku do SDRAM paměti modulu SAMA5 a spustit ji. Linuxové jádro zatím nemáme, jediné, co máme, je binárka U-Bootu. Zkusíme ji natáhnout a spustit, uvidíme, co to udělá. Nakopírujeme soubor u-boot.bin do adresáře /srv/tftp na linuxovém PC (t.j. do kořenového adresáře našeho TFTP serveru) a v terminálovém okně na příkazovém řádku U-Bootu použijeme příkaz tftpboot.
Nejdříve si necháme vypsat nápovědu příkazem help tftpboot, abychom viděli, jak se příkaz tftpboot používá.
U-Boot> help tftpboot tftpboot - boot image via network using TFTP protocol Usage: tftpboot [loadAddress] [[hostIPaddr:]bootfilename] U-Boot>
- loadAddress - adresa v paměti, kam se má binárka natáhnout; v našem případě 0x20000000, což je začátek SDRAM paměti
- hostIPaddr - IP adresa TFTP serveru; naše je 192.168.168.29, ale vaše bude asi jiná
- bootfilename - jméno souboru binárky, takže u-boot.bin
U-Boot> tftpboot 20000000 192.168.168.29:u-boot.bin macb0: PHY present at 0 macb0: Starting autonegotiation... macb0: Autonegotiation complete macb0: link up, 100Mbps full-duplex (lpa: 0x45e1) Using macb0 device TFTP from server 192.168.168.29; our IP address is 192.168.168.30 Filename 'u-boot.bin'. Load address: 0x20000000 Loading: ################################################################# ######### 3 MiB/s done Bytes transferred = 375336 (5ba28 hex) U-Boot>
Výborně, komunikace s TFTP serverem funguje. Teď zkusíme spustit kód, který jsme do paměti natáhli. Vstupní bod U-Bootu (adresa první instrukce) je shodný s adresou, kam jsme binárku natáhli, takže 0x20000000. A vida, U-Boot se spustil ...
U-Boot> go 20000000 ## Starting application at 0x20000000 ... U-Boot 2014.07-00031-gd6cc7cc (Oct 22 2014 - 14:22:56) CPU: SAMA5D31 Crystal frequency: 12 MHz CPU clock : 528 MHz Master clock : 132 MHz DRAM: 256 MiB NAND: 256 MiB MMC: mci: 0 SF: Detected AT25DF041 with page size 256 Bytes, erase size 4 KiB, total 512 KiB In: serial Out: serial Err: serial Net: macb0, usb_ether U-Boot>
Opakovat stále dokola stejné hodnoty na příkazovém řádku je pěkně otravné. Proto si nastavíme proměnné prostředí, které příkaz tftpboot použije jako defaultní, pokud jsou tyto hodnoty na příkazovém řádku vynechány
- loadaddr - adresa, na kterou bude binárka natažena
- serverip - IP adresa TFTP serveru
- bootfile - jméno souboru binárky
Nastavíme obsah proměnných a uložíme je do SPI Flash
U-Boot> setenv loadaddr 20000000 U-Boot> setenv serverip 192.168.168.29 U-Boot> setenv bootfile u-boot.bin U-Boot> saveenv
Teď zkusíme spustit příkaz tftpboot bez parametrů. Měl by použít hodnoty, které jsme zadali do proměnných.
U-Boot> tftpboot macb0: PHY present at 0 macb0: Starting autonegotiation... macb0: Autonegotiation complete macb0: link up, 100Mbps full-duplex (lpa: 0x45e1) Using macb0 device TFTP from server 192.168.168.29; our IP address is 192.168.168.30 Filename 'u-boot.bin'. Load address: 0x20000000 Loading: ################################################################# ######### 3 MiB/s done Bytes transferred = 375336 (5ba28 hex) U-Boot>
Pokud opakovaně píšeme dlouhé sekvence příkazů, můžeme si práci zjednodušit vytvořením skriptu. Na linuxovém PC zapíšeme sadu příkazů do textového souboru example1.txt.
echo Ethernet interface echo ------------------ printenv ethaddr printenv ipaddr printenv netmask echo echo TFTP server echo ----------- printenv serverip echo echo Load image u-boot.bin at 0x22000000 echo ----------------------------------- echo tftpboot 22000000 u-boot.bin echo echo Run it from 0x22000000 echo ---------------------- go 22000000
Příkazem mkimage zkonvertujeme vytvořený textový soubor na skript U-Bootu. Výsledný soubor example1.scr nakopírujeme do kořenového adresáře TFTP serveru /srv/tftp.
$ mkimage -A arm -O linux -T script -C none -a 0 -e 0 \ -n "Example 1" -d example1.txt example1.scr Image Name: Example 1 Created: Thu Nov 20 15:53:29 2014 Image Type: ARM Linux Script (uncompressed) Data Size: 352 Bytes = 0.34 kB = 0.00 MB Load Address: 00000000 Entry Point: 00000000 Contents: Image 0: 344 Bytes = 0.34 kB = 0.00 MB $ cp example1.scr /srv/tftp
Na modulu SAMA5 natáhneme skript example1.scr z TFTP serveru příkazem tftpboot. Můžeme vynechat IP adresu TFTP serveru a loadovací adresu, protože příkaz tftpboot použije předdefinované proměnné
U-Boot> tftpboot example1.scr macb0: PHY present at 0 macb0:0 is connected to macb0. Reconnecting to macb0 macb0: Starting autonegotiation... macb0: Autonegotiation complete macb0: link up, 100Mbps full-duplex (lpa: 0x45e1) Using macb0 device TFTP from server 192.168.168.29; our IP address is 192.168.168.30 Filename 'example1.scr'. Load address: 0x20000000 Loading: # 81.1 KiB/s done Bytes transferred = 416 (1a0 hex) U-Boot>
Příkaz iminfo vypíše informace z hlavičky nataženého souboru
U-Boot> iminfo ## Checking Image at 20000000 ... Legacy image found Image Name: Example 1 Image Type: ARM Linux Script (uncompressed) Data Size: 352 Bytes = 352 Bytes Load Address: 00000000 Entry Point: 00000000 Contents: Image 0: 344 Bytes = 344 Bytes Verifying Checksum ... OK U-Boot>
Skript spustíme příkazem source
U-Boot> source 20000000 ## Executing script at 20000000 Ethernet interface ------------------ ethaddr=02:10:20:30:40:50 ipaddr=192.168.168.30 netmask=255.255.255.0 TFTP server ----------- serverip=192.168.168.29 Load image u-boot.bin at 0x22000000 ----------------------------------- macb0: PHY present at 0 macb0:0 is connected to macb0. Reconnecting to macb0 macb0: Starting autonegotiation... macb0: Autonegotiation complete macb0: link up, 100Mbps full-duplex (lpa: 0x45e1) Using macb0 device TFTP from server 192.168.168.29; our IP address is 192.168.168.30 Filename 'u-boot.bin'. Load address: 0x22000000 Loading: ################################################################# ######### 3 MiB/s done Bytes transferred = 375336 (5ba28 hex) Run it from 0x22000000 ---------------------- ## Starting application at 0x22000000 ... U-Boot 2014.07-00031-gd6cc7cc (Oct 22 2014 - 14:22:56) CPU: SAMA5D31 Crystal frequency: 12 MHz CPU clock : 528 MHz Master clock : 132 MHz DRAM: 256 MiB NAND: 256 MiB MMC: mci: 0 SF: Detected AT25DF041 with page size 256 Bytes, erase size 4 KiB, total 512 KiB In: serial Out: serial Err: serial Net: macb0, usb_ether U-Boot>
Tohle je jednoduchý skript, který vlastně nedělá nic důležitého. Skriptovatelnost U-Bootu je ale mocný nástroj, který nám ušetří opakované psaní příkazů, když při vývojové fázi používáme různé bootovací scénáře.