Produkty Novinky Články Návody Kontakty

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.