Hawkboard
Hawkboard, TI (Texas Instruments) firmasının geliştirdiği, OMAP ARM9 (OMAP-L138) işlemcisini kullanan açık bir donanımdır.
Temel olarak aşağıdaki bileşenlere sahiptir.
İşlemci | ARMV5/ARM926 |
---|---|
DSP | C674x Floating Point |
RAM | 128 MB DDR |
NAND | 128 MB |
MMC/SD | Var |
Ethernet | Var |
VGA | Var |
Konsol | Var |
Not: Hawkboard projesi, kartın bazı donanım problemleri nedeniyle sonlandırılmış durumdadır. Fakat kartın NAND, Ethernet ve VGA gibi bileşenlere sahip olması, bu tür sistemleri tanıma sürecinde bizim için kullanışlı bir çalışma ortamı oluşturacaktır.
Bu bölümde, cihaz için önyükleyici ve işletim sistemi çekirdeğinin nasıl derlendiğinden, sonrasında cihazı kendi bilgisayarımız üzerinden (Host) nasıl açabileceğimize (Recovery) ve temel bazı kullanım senaryolarına bakacağız.
İlk olarak, önyükleyici ve çekirdeği nasıl edinip derleyebileceğimize bakalım.
Not: Derleme sürecinde CodeSourcery geliştirme araçlarını kullanacağız. Bu aşamada çapraz derleyicinizin yol ifadesinin PATH çevre değişkeninde tanımlı olduğundan emin olunuz.
Ayrıca başka bir derleyici kullanıyorsanız, önyükleyici ve çekirdek derleme aşamalarında, derleyicinize ait öneki (prefix) kullanmalısınız. CodeSourcery için derleyici öneki arm-none-linux-gnueabi- şeklindedir.
Önyükleyici (Bootloader)
Hawkboard, U-Boot önyükleyicisini kullanmaktadır.
wget -c http://hawkboard.googlecode.com/files/u-boot-omapl1_v1.tar.bz2
tar xf u-boot-omapl1_v1.tar.bz2
cd u-boot-omapl1
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- distclean
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- omapl_hawkboard_config
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
Bu aşamada ana dizinde u-boot dosyası oluşmuş olmalıdır.
Çekirdek (Kernel)
wget -c http://hawkboard.googlecode.com/files/linux-omapl1_ver1.tar.bz2
tar xf linux-omapl1_ver1.tar.bz2
cd linux-omapl1
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- distclean
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- omapl138_hawkboard_defconfig
make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- uImage
Bu aşamada ana dizinden itibaren arch/arm/boot dizininde, U-Boot tarafından yüklenebilecek, çekirdek imajı uImage oluşmuş olmalıdır.
Şimdi kartı sıfırdan nasıl açabileceğimize bakalım.
Kartın Kurtarılması (Board Recovery)
Kart üzerinde, açılış sürecine ilişkin alt seviye bir yazılım olmaması, bu yazılımın bozulmuş olması durumununda veya bu süreç bypass edilmek istendiğinde, kartın dışarıdan açılması tek veya alternatif bir seçenek olarak karşımıza çıkmaktadır.
Kart kurtarma senaryolarında genel olarak cihaza SD kart, USB veya seri port üzerinden ilk olarak önyükleyicinin atılarak çalıştırılması hedeflenmektedir. Cihaz üzerinde önyükleyici çalıştırıldıktan sonra seri terminal üzerinden cihazla alt seviye bir iletişim kurulabilir ve sonraki adımlara buradan devam edilebilir.
Hawkboard seri port üzerinden (UART Recovery) açılabilmektedir. Öncesinde, daha önce derlediğimiz önyükleyici dosyasını (u-boot) seri port için uygun şekilde imzalamalıyız. Bu imzalama ve önyükleyiciyi cihaza atma işlemleri için TI tarafından hazırlanan AIS Generator / UART Host Tool araçlarını kullanacağız. Gerekli araçları sisteminize kurmak için ilk olarak aşağıdaki zip dosyasını indirebilirsiniz.
Not: TI tarafından sağlanan bu araçlar, maalesef Linux karşılıkları olmayan, .NET Framework bağımlılığı olan pencereli uygulamalardır. Linux altında bu programları kullanabilmek için sisteminizde mono, mono-vbnc ve wine paketleri bulunmalıdır.
wget -c http://www-s.ti.com/sc/techlit/sprab41.zip
zip dosyasından AISgen_d800k008_Install_v1.13.exe kurulum dosyası çıkacaktır. Kurulum sonrasında, sırasıyla imzalama ve cihaza önyükleyici atmak için AISgen_d800k008.exe ve UartHost.exe uygulamalarını kullanacağız.
İlk olarak, imzalama işlemini nasıl yaptığımıza bakalım.
Not: İşlemci yongasındaki ROM önyükleyici dışarıdan okuyacağı bir sonraki önyükleyiciyi, TI tarafından geliştirilen, Application Image Script (AIS) formatında beklemektedir. Formatın detaylarına TI dokümanlarında mevcuttur.
Seri Port Hedefli İmzalama
AISgen imzalama uygulamasında General ve DDR sekmelerine aşağıdaki değerleri vermeliyiz. DDR sekmesinin görünür olması için General sekmesinde, Configure DDR seçeneği işaretlenmelidir.
General:
Özellik | Değer |
---|---|
Device Type | d800k002 - ARM |
Boot Mode | UART2 |
DDR:
Özellik | Değer |
---|---|
Memory Type | DDR2 |
DRPYC1R | 0x43 |
SDCR | 0x00134632 |
SDCR2 | - |
SDTIMR1 | 0x26492a09 |
SDTIMR2 | 0x7d13c722 |
SDRCR | 0x249 |
Not: Bu aşamada yukarıdaki bu değerlerin ne anlama geldiğini bilmek zorunda değiliz.
Linux altında aldığımız örnek ekran görüntüleri aşağıdaki gibidir.
Sonrasında, ARM Application File bölümüne daha önce derlediğiniz u-boot dosyasını, AIS Output File bölümünü de oluşturulacak olan dosya ismini vererek imzalama işlemini gerçekleştirebilirsiniz. Biz imzalı dosyamıza u-boot_uart.bin ismini verdik.
Şimdi imzalanmış önyükleyici dosyasını Hawkboard'a nasıl atacağımıza bakalım.
Seri Port Üzerinden Önyükleyicinin Atılması
Bu amaçla UartHost.exe uygulamasını kullanacağız. Fakat öncesinde cihaz üzerindeki açılış sürecini kontrol eden anahtarları (Boot Switches) uygun şekilde ayarlamalıyız. Üretim aşamasında işlemci içindeki dahili bir hafızaya kodlanan önyükleyici (ROM Bootloader) bu anahtarların durumuna göre sonraki önyükleyiciyi NAND veya seri port üzerinden okumaya çalışmaktadır. Cihazı seri port üzerinden açabilmek için boot anahtarları aşağıdaki gibi ayarlanmalıdır.
Not: Boot anahtarları, kart üzerinde DIP switch şeklinde bulunmaktadır. Reset butonunun yakınında bulunan bu anahtarlar SW1 olarak isimlendirilmiştir.
1 | 2 | 3 | 4 |
---|---|---|---|
OFF | ON | OFF | ON |
Bu durumda, cihaza enerji verildiğinde veya resetlendiğinde, seri terminale BOOTME mesajını gönderecektir. Cihaza önyükleyiciyi atmadan önce bu mesajın geldiğinden emin olunuz ve seri terminal bağlantınızı sonlandırınız.
Şimdi UartHost.exe uygulamasını kullanabiliriz. Uygulamaya daha önce imzaladığımız u-boot dosyasını ve seri portu göstermeliyiz, ayrıca Wait for BOOTME seçeneğinin seçili olduğundan emin olunuz. Bu durumda uygulamada Start butonuna bastığımızda Linux altında aldığımız örnek ekran görüntüsü aşağıdaki gibidir.
Bu aşamada uygulama cihaza enerji vermemizi veya resetlememizi beklemektedir. Cihaz yeniden başlatıldığında, imzalanmış u-boot cihaza atılacaktır. Örnek ekran görüntüsü aşağıdaki gibidir.
Sonrasında seri terminal üzerinden cihaza bağlanıp enter tuşuna bastığınızda u-boot komut satırını görmelisiniz. printenv ile önyükleyicinin kullandığı çevre değişkenlerini görebilirsiniz.
hawkboard.org > printenv
bootargs=mem=128M console=ttyS2,115200n8 root=/dev/ram0 rw initrd=0xc1180000,4M ip=dhcp
bootcmd=
bootdelay=3
baudrate=115200
bootfile="uImage"
stdin=serial
stdout=serial
stderr=serial
ethaddr=0a:c1:a8:12:fa:c0
ver=U-Boot 2009.01 (Oca 21 2015 - 14:11:03)
Environment size: 254/131068 bytes
Bu aşamadan sonra sistemi açmak için bir çok seçeneğe sahibiz. Sırayla bunlardan bazılarını kısaca inceleyim.
Cihazın TFTP ve NFS Üzerinden Açılması
Bu yöntemi kullanarak, ağ üzerindeki başka bir sistemden veya geliştirme yaptığınız bilgisayardan, çekirdeği cihaza çekmek ve uzaktaki bir dosya sistemini mount etmek mümkündür. Öncesinde geliştirme yaptığınız bilgisayarınızda TFTP ve NFS sunucuları kurulu olmalıdır.
Uzaktaki bir makinadan çekirdeği cihaz üzerine aşağıdaki gibi çekebilirsiniz.
setenv autoload no
dhcp
setenv serverip <TFTP sunucu adresi>
tftp c0700000 uImage
Açılış sırasında root dosya sistemi olarak NFS'i kullanmak için ise bootargs değişkenine aşağıdaki formda değerler geçirilmelidir.
setenv nfsroot ${serverip}:<Uzak makinadaki NFS dizini>
setenv bootargs "root=/dev/nfs nfsroot=${nfsroot} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0"
dhcp özelliğinin olmaması durumunda, cihaz IP, gateway ve netmask değerlerini aşağıdaki gibi verebilirsiniz.
setenv ipaddr <Cihaz IP adresi>
setenv gatewayip <Gateway adresi>
setenv netmask <Netmask>
Sonrasında daha önce çekirdeği çektiğiniz adresteki kodu çalıştırarak cihazı açabilirsiniz.
bootm <Çekirdeğin belleğe çekildiği adres>
Kendi sistemimiz için örnek bir kullanım aşağıdaki gibidir.
setenv autoload no
dhcp
setenv serverip 172.16.2.136
tftp c0700000 uImage
setenv nfsroot ${serverip}:/nfsroot
setenv bootargs "console=ttyS2,115200 init=/bin/sh root=/dev/nfs nfsroot=${nfsroot} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0"
bootm c0700000
Şimdi, bir diğer alternatif olarak, cihazı NAND üzerinden nasıl açabileceğimize bakalım.
Cihazın NAND Üzerinden Açılması
Cihazı NAND üzerinden açabilmek için ilk olarak gerekli dosyaları bir şekilde NAND üzerine yazmalıyız. Bu işlemi, dosya sistemini NFS üzerinden mount edip, Linux üzerinden yapabildiğimiz gibi, U-Boot üzerinden de yapabiliriz. Fakat öncesinde, daha önce seri port için yaptığımıza benzer şekilde, NAND üzerine yazacağımız u-boot dosyasını imzalamalıyız.
Şimdi sırasıyla, imzalama işlemine ve gerekli dosyaları NAND üzerine nasıl yazabileceğimize bakalım.
NAND Hedefli İmzalama
İmzalama işlemi için yine AISgen_d800k008.exe uygulamasını kullanacağız, seri port için imzalama yaparken kullandığımız aynı değerleri kullanacağız yalnız Boot Mode tipini NAND Flash olarak seçmeliyiz.
General:
Özellik | Değer |
---|---|
Device Type | d800k002 - ARM |
Boot Mode | NAND Flash |
NAND Bölümlendirmesi
Çekirdek, NAND üzerinde sanki bir bölümlendirme (Partition) yapısı varmış gibi işlem yapabilir. Bu bölümlendirme, Linux kaynak kodu içerisinden sabit olarak ayarlanabileceği gibi çekirdeğe önyükleyici tarafından geçirilen argümanlar vasıtasıyla dinamik olarak da yapılabilir.
Sabit bölümlendirme bilgileri arch/arm/mach-davinci/board-omapl138-hawk.c dosyasında mtd_partition türündeki omapl138_hawk_nandflash_partition isimli bir dizi ile temsil edilmektedir.
Dinamik bölümlendirme için ise çekirdek kodu command line partition table parsing seçeneği seçilerek derlenmeli ve çekirdeğe mtdparts komut satırı seçeneği geçirilmelidir. Örnek olarak aşağıdaki gibi bir bölümlendirme oluşturalım.
Bölüm | Uzunluk |
---|---|
U-Boot_Env | 128K |
U-Boot | 512K |
Kernel | 4M |
Recovery | 40M |
FileSystem | Kalan Boş Alan |
Bu bölümlendirmeyi oluşturabilmek için çekirdeğe, diğer komut satırı parametreleriyle beraber, aşağıdaki mtdparts değerini geçirmeliyiz.
mtdparts=davinci_nand.1:128K(U-Boot_Env),512K(U-Boot),4M(Kernel),40M(Recovery),-(FileSystem)
Not: Yukarıdaki ifadede davinci_nand, mtd id değerini, noktadan sonra eklenen 1 değeri ise aygıt numarasını göstermektedir. mtd id değerine, Linux üzerinden, aşağıdaki gibi ulaşabilirsiniz.
ls /sys/bus/platform/drivers | grep nand
Linux üzerinden NAND bölümlendirmesini cat /proc/mtd şeklinde görebilirsiniz. Örneğimiz için çıktı aşağıdaki gibidir.
# cat /proc/mtd
dev: size erasesize name
mtd0: 00020000 00020000 "U-Boot_Env"
mtd1: 00080000 00020000 "U-Boot"
mtd2: 00400000 00020000 "Kernel"
mtd3: 02800000 00020000 "Recovery"
mtd4: 05360000 00020000 "FileSystem"
Her bir bölüm üzerinde, bir blok aygıt (block device) olarak işlem yapılabilir. İlgili dosya düğümlerini aşağıdaki gibi listeleyebilirsiniz.
# ls /dev/mtdblock*
/dev/mtdblock0 /dev/mtdblock1 /dev/mtdblock2 /dev/mtdblock3 /dev/mtdblock4
Şimdi sırasıyla önyükleyici, çekirdek imajı ve dosya sistemini nasıl yazabileceğimize bakalım. Ayrıca, FileSystem olarak isimlendirdiğimiz son bölümden önce Recover isimli başka bir bölüm daha oluşturduğumuza dikkat ediniz. Bu bölüm üzerinde, güvenlik amaçlı, yalnız okunabilen bir dosya sistemi oluşturacağız.
Gerekli Dosyaların Linux Üzerinden Yazılması
İlk olarak, NAND üzerine yazacağımız önyükleyici, çekirdek ve dosya sistemi imajlarını NFS üzerinden açtığımız cihazımızın dosya sistemine kopyalamalıyız. Gerekli dosyaları /opt altına attığımızı kabul edelim.
/opt # ls
rootfs.jffs2 uImage
rootfs.sqsh u-boot_nand.bin
Dosya | Türü |
---|---|
u-boot_nand.bin | NAND için imzalanmış önyükleyici |
uImage | Çekirdek imajı |
rootfs.sqsh | squashfs dosya sistemi imajı |
rootfs.jffs2 | jffs2 dosya sistemi imajı |
Gerekli dosyaları dd aracı ile aşağıdaki gibi sırasıyla NAND üzerine yazabiliriz.
Uyarı: Bu işlemler öncesinde, U-Boot komut satırından nand erase ile tüm NAND'i silmeyi unutmayınız. Diğer bir alternatif mtd-utils araçlarını cihaz hedefli derleyerek aynı işlemi Linux üzerinden yapmak olabilir.
dd if=u-boot_nand.bin of=/dev/mtdblock0 bs=128k
dd if=uImage of=/dev/mtdblock2 bs=128k
dd if=rootfs.sqsh of=/dev/mtdblock3 bs=128k
dd if=rootfs.jffs2 of=/dev/mtdblock4 bs=128k
Şimdi aynı işlemi u-boot üzerinden nasıl yapabileceğimize bakalım.
Gerekli Dosyaların U-Boot Üzerinden Yazılması
nand erase 0x20000 0x80000
tftpboot 0xc0700000 u-boot_nand.bin
nand write.e 0xc0700000 0x20000 0x80000
nand erase 0xA0000 0x400000
tftpboot 0xc0700000 uImage
nand write.e 0xc0700000 0xA0000 0x400000
nand erase 0x2CA0000 0x1000000
tftpboot 0xc0700000 rootfs.sqsh
nand write.e 0xc0700000 0x2CA0000 0x1000000
nand erase 0x4A0000 0x1000000
tftpboot 0xc0700000 rootfs.jffs2
nand write.e 0xc0700000 0x4A0000 0x1000000
nand write.e komutunun genel şekli aşağıdaki gibidir.
nand write.e <memory address> <offset> <size>
Çekirdeğe geçireceğininiz NAND bölümlendirmesini değiştirmeniz durumunda, kullandığımız ofset değerleri de değişecektir. Ayrıca yukarıdaki örnek kullanımda dosya sistemlerinin 16M sınırında olduğu kabul edilmiştir, boyut olarak 0x1000000 değerinin kullanıldığına dikkat ediniz.
Root dosya sisteminin uygun parametlerle jffs2 imajının oluşturuluması ve sonrasında, U-Boot veya Linux üzerinden, NAND üzerine yazıldıktan sonra tekrar okunmasında bazı problemler ortaya çıkabilmektedir. Bu yüzden önyükleyici ve çekirdeği u-boot üzeriden yazmanızı, dosya sistemini ise Linux üzerinden ilgili bölümü mount edip dosya sistemini kopyalamanızı öneririz.
Önerilen Yöntem
U-Boot:
nand erase
tftpboot 0xc0700000 u-boot_nand.bin
nand write.e 0xc0700000 0x20000 0x80000
tftpboot 0xc0700000 uImage
nand write.e 0xc0700000 0xA0000 0x400000
setenv nfsroot ${serverip}:/nfsroot
setenv bootargs "console=ttyS2,115200 init=/bin/sh root=/dev/nfs nfsroot=${nfsroot} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0"
bootm c0700000
Linux:
mount -t jffs2 /dev/mtdblock4 nand/
tar xf rootfs.tgz -C nand/
umount nand
Bu aşamada ROM yükleyicinin, bir sonraki açılışta, u-boot yükleyicisini NAND üzerinden araması için boot anahtarları aşağıdaki gibi ayarlanmalıyız.
1 | 2 | 3 | 4 |
---|---|---|---|
ON | OFF | OFF | OFF |
Gerekli dosyaları NAND üzerine yazdıktan sonra cihazın kendiliğinden NAND üzerinden açılabilmesi için önyükleyici üzerinde bazı değişiklikler yapmalıyız. Cihazı resetleyerek tekrar u-boot komut satırına düşelim.
Çekirdeğe, root dosya sisteminin yerini ve tipini geçirmeliyiz. Aşağıdaki kullanımda root=/dev/mtdblock4 dosya sisteminin aranacağı NAND bölümünü, rootfstype=jffs2 ise dosya sisteminin tipini göstermektedir. Sonrasında NAND üzerindeki çekirdek kodu, güvenli bir adrese çekilip başlatılmalıdır. nand read ve bootm komutları bu işleri yapmaktadır. bootcmd ile gösterilen komutlar, açılışta önyükleyici tarafından otomatik olarak çalıştırılarak, bu komutların icra edilmesi sağlanır.
setenv bootargs "console=ttyS2,115200 init=/bin/sh root=/dev/mtdblock4 rootwait rootfstype=jffs2 mtdparts=davinci_nand.1:128K(U-Boot_Env),512K(U-Boot),4M(Kernel),40M(Recovery),-(FileSystem)"
setenv bootcmd 'nand read c0700000 A0000 200000; bootm c0700000'
saveenv
Bu aşamadan sonra cihaz resetlendiğinde, dışarıdan herhangi bir müdahale olmaksızın, dahili NAND hafızası üzerinden açılacaktır.