Raspberry Pi 3
Bu başlık altında 64 bitlik işlemciye sahip Raspberry Pi 3 Model B için, 64 bit hedefli, u-boot ve Linux çekirdeğini nasıl derleyebileceğimize bakacağız.
Raspberry Pi 3 ve Raspberry Pi 2 için geliştirme süreçleri oldukça benzerdir. Sadece u-boot, kernel default ayarları ve seri portun kullanımına ilişkin bir takım farklılıklar bulunmaktadır. Yeri geldiğinde bu farklılıklara değineceğiz. Raspberry Pi 3 ile Raspberry Pi 2 fiziksel seri konsol bağlantıları aynıdır.
Raspberry Pi 3 Teknik Özellikleri
Cihazın temel teknik özelliklerini aşağıdaki gibi listeleyebiliriz.
Özellik | Açıklama |
---|---|
SoC | Broadcom BCM2837 |
CPU | 64-bit quad-core ARM Cortex-A53, 1.2GHz |
GPU | Broadcom Dual Core VideoCore IV |
RAM | 1GB LPDDR2 (900 MHz) (GPU ve CPU paylaşımlı) |
Video çıkışı | HDMI and RCA, plus 1 CSI camera connector |
Hafıza | MicroSD |
Giriş/Çıkış | 17 GPIO plus specific functions |
Network | 10/100 Ethernet, 802.11n WiFi and Bluetooth 4.1 |
Raspberry Pi 2 ve 3 arasındaki temel özelliklere ilişkin karşılaştırma ise aşağıdaki gibidir:
Raspberry Pi 2 | Raspberry Pi 3 |
---|---|
Processor: 32-bit quad-core ARM Cortex-A7 | Processor: 64-bit quad-core ARM Cortex-A53 |
Clock frequency: 1000 MHz | Clock frequency: 1200 MHz |
RAM: 1024 MB | RAM: 1024 MB |
Wi-Fi : Yok | Wi-Fi : Var |
Bluetooth : Yok | Bluetooth : Var, 4.1 |
Power supply : 5v 2A | Power supply : 5v 2.5A |
Storage: MicroSD card | Storage: MicroSD card |
Network adapter: Ethernet network card | Network adapter: Ethernet network card |
USB ports: 4 | USB ports: 4 |
2.5A USB: No | 2.5A USB: Yes |
Geliştirme Araçlarının Elde Edilmesi
Gerekli araç ve üretilen dosyaları uygun bir dizin yapısı altında tutmak geliştirme sürecinde faydalı olacaktır. Örnek olarak kendi sistemimizde aşağıdaki dizin yapısını oluşturduk. Daha sonra linux ve u-boot dizinlerini yine bu dizin yapısı altına ekleyeceğiz.
/opt/rpi3
└── toolchain
Geliştirme ana dizinini DEVELOPMENT_DIR isimli bir çevre değişkeninde saklayabiliriz.
$ export DEVELOPMENT_DIR=/opt/rpi3
DEVELOPMENT_DIR çevre değişkeni ile belirlediğiniz başka bir dizini göstererek geliştirmelerinizi o şekilde yapabilirsiniz.
İlk olarak çapraz derleyiciyi nasıl edinebileceğimize bakalım. 64 bit hedefli Linaro çapraz derleme araçlarını aşağıdaki gibi sisteminize indirip toolchain dizini altına açabilirsiniz.
$ cd $DEVELOPMENT_DIR/toolchain
$ wget -c https://releases.linaro.org/components/toolchain/binaries/latest-7/\
aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz
$ tar xvf gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz --strip-components=1
Artık toolchain dizini altında ihtiyaç duyduğumuz çapraz derleme araçları bulunmaktadır. PATH çevre değişkenine çapraz derleyicinin konumunu aşağıdaki gibi ekleyebiliriz.
$ export PATH=$DEVELOPMENT_DIR/toolchain/bin:$PATH
Bu aşamadan sonra bulunduğumuz terminal üzerinde çapraz derleyiciyi kullanabiliriz, aşağıdaki gibi test edebilirsiniz.
$ aarch64-linux-gnu-gcc -v
Kernel Derleme Süreci
Raspberry Pi için kernel kaynak kodunu aşağıdaki gibi indirebiliriz.
$ cd $DEVELOPMENT_DIR
$ git clone --depth=1 https://github.com/raspberrypi/linux
Çapraz derleyicinin PATH değişkeninde tanımlı olduğundan emin olduktan sonra derleme işlemine geçilebilir.
$ export PATH=$DEVELOPMENT_DIR/toolchain/bin:$PATH
Raspberry Pi 3 için öntanımlı konfig dosyası bcmrpi3_defconfig olarak isimlendirilmiştir. Kernel konfigürasyonu ve derleme işlemleri aşağıdaki gibidir:
$ cd linux/
$ make ARCH=arm64 bcmrpi3_defconfig
$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j4
Bu işlem sonucunda arch/arm64 dizini altında, uygun alt dizinler içerisinde, kernel imajı ve gerekli dtb dosyası oluşacaktır. Kernel imajı ve dtb dosyasının konumları aşağıdaki gibi olacaktır.
arch/arm64/boot/Image
arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b.dtb
dtb dosyası olarak bcm2837-rpi-3-b.dtb dosyasını kullanacağız. Raspberry Pi 3 üzerinde Broadcom BCM2837 SoC kulllanıldığını hatırlayınız.
Derleme işlemi sonunda oluşan kernel imajının uncompressed olduğuna dikkat ediniz. u-boot üzerinden kernel'ı yüklerken sıkıştırılmamış bu imajı kullanacağız.
U-boot Derleme Süreci
U-boot kaynak kodunu aşağıdaki gibi indirebiliriz.
$ cd $DEVELOPMENT_DIR
$ git clone git://git.denx.de/u-boot.git
Bu aşamadan sonra u-boot kodunu rp3 için konfigure edip derleyebiliriz.
$ cd u-boot/
$ make rpi_3_defconfig
$ make CROSS_COMPILE=aarch64-linux-gnu- -j2
Derleme sonunda ana dizinde u-boot.bin dosyası oluşacaktır.
Bu aşamadan sonra daha önceki bölümlerde anlatıldığı gibi gerekli boot dosyaları ve dosya sistemini içeren bir SD kart hazırlanmalıdır.
SD Kart Boot Bölümlendirmesi
Raspberrp Pi 2'de olduğu gibi yine gerekli araçlar https://github.com/raspberrypi/firmware/tree/master/boot adresinden indirilebilir. Bu adresten bootcode.bin, fixup.dat ve start.elf dosyalarını indirebilirsiniz. Raspberry Pi 2 ve 3 arasında bu dosyalarla ilgili bir farklılık bulunmamaktadır. Bu dosyalarla birlikte, derlediğimiz kernel imajını, dtb ve u-boot dosyalarını boot bölümlendirmesine kopyalamalıyız. Derlenen dosyalar Image, bcm2837-rpi-3-b.dtb ve u-boot.bin şeklinde isimlendirilmiş olacaktır.
Cihaz direkt kernel üzerinden açılabildiği gibi öncesinde u-boot önyükleyicisini çalıştırmak da mümkündür. Burada u-boot üzerinden cihazı nasıl açabileceğimizi inceleyeceğiz. u-boot.bin dosyasını SD karta kernel8.img olarak kopyalayacağız. Bu isim değişikliğinin nedenine aşağıda değindik.
Tüm kopyalama işlemleri sonunda SD kartın boot bölümlendirmesinin içeriği aşağıdaki gibi olmalıdır.
├── bcm2837-rpi-3-b.dtb
├── bootcode.bin
├── config.txt
├── fixup.dat
├── Image
├── kernel8.img (u-boot.bin dosyası)
└── start.elf
Bu noktada cihazın nasıl açıldığını hatırlamak faydalı olacaktır. Cihaza enerji verildiğinde ilk olarak ROM bellekteki alt seviye önyükleyici, GPU içindeki, bir RISC işlemci tarafından çalıştırılır. Bu önyükleyici tarafından SD kartın FAT bölümlendirmesi mount edildikten sonra bootcode.bin çalıştırılır. bootcode.bin yükleyicisi de yine bir önyükleyici olan start.elf isimli GPU firmware'ini çalıştırır. Bu aşamaya kadar süreç dışarıdan bir müdahale olmaksızın gerçekleşmektedir. start.elf çalıştıktan sonra config.txt içeriğini okumaktadır. Bu sayede config.txt dosyası üzerinde değişiklik yapılarak start.elf yükleyicisinin çalışmasına müdahale edilebilmektedir.
Çalıştırılacak olan kernel imajı config.txt içerisinde kernel=Image şeklinde gösterilebilir. Raspberry Pi 2 için, bir önceki bölümde incelediğimiz gibi config.txt dosyasına, kernel=u-boot.bin şeklinde bir giriş eklenirse ilk olarak kernel yerine u-boot çalıştırılacaktır. Raspberry Pi 3 için ise bu yöntem işe yaramamaktadır. Raspberry Pi 2 ve 3 için default kernel imaj adı kernel7.img'dir. Raspberry Pi 3 önyükleyicisi, start.elf, kernel8.img isimli bir dosya görmesi durumunda öncelikli olarak bu dosyayı 64 bitlik modda yüklemektedir.
Seri Konsol
Raspberry Pi 3, PL011 ve mini olmak üzere iki adet UART'a sahiptir. Bu sebeple daha önce incelediğimiz Raspberry Pi 2 modeline göre config.txt ve kernel komut satır argümanlarında bazı farklılıklar bulunmaktadır.
Pi 3 modelinde PL011 default durumda Bluetooth modülü için kullanılmaktadır. Bu sebeple seri konsol için mini UART'ı kullanacağız. Linux tarafından bu aygıt ttyS0 olarak tanınmaktadır.
Not: Pi 2 modeli için seri konsol olarak PL011 kullanılmakta ve bu aygıt Linux tarafından ttyAMA0 olarak isimlendirilmektedir. Pi 2 için seri konsol olarak ttyAMA0 kullandığımızı hatırlayınız.
Cihaz açılırken default durumda mini UART aktif değildir. Bu sebeple config.txt dosyasına aşağıdaki satır eklenmelidir.
enable_uart=1
Bu aşamadan sonra cihaza enerji verdiğimizde ilk olarak u-boot çalışacaktır. Bu sırada klavyeden bir tuşa basarak u-boot komut satırına geçebilirsiniz.
U-boot Komut Satırı
u-boot komut satırında ilk olarak kernel imaj ve dtb dosyasını SD karttan belleğin güvenli alanlarına çekelim.
U-Boot> fatload mmc 0 ${kernel_addr_r} Image
U-Boot> fatload mmc 0 ${fdt_addr_r} bcm2837-rpi-3-b.dtb
kernel_addr_r ve fdt_addr_r değişkenlerine uygun adresler atanmış durumdadır. Daha sonra kernel komut satırı argümanlarını bootargs değişkeninde tutabiliriz.
U-Boot> setenv bootargs 8250.nr_uarts=1 root=/dev/mmcblk0p2 rootwait\
console=tty1 console=ttyS0,115200
Seri konsol için ttyS0'ı kullanıyoruz ayrıca kernel'a 8250.nr_uarts=1 ile kullanılacak UART sayısını geçiriyoruz.
Bu aşamadan sonra uncompressed kernel imajını booti komutu ile aşağıdaki gibi çalıştırabiliriz.
U-Boot> booti ${kernel_addr_r} - ${fdt_addr_r}
initrd imajı kullanmadığımız için booti komutuna 2. argüman olarak - değerini geçirdik. Sonrasında komut satırndan boot diyerek Linux çekirdeğini çalıştırabilirsiniz.
U-Boot> boot
Bu işlemleri sürekli tekrarlamamak için, cihazın açılması bölümünde anlatıldığı gibi, bir uboot.env dosyası hazırlanabilir veya bu ayarları saveenv komutu ile SD kart üzerinde saklayabiliriz. Burada ikinci yöntemi kullanacağız. Yukarıdaki işlemler aşağıdaki gibi kalıcı hale getirilebilir.
U-Boot> setenv bootargs "8250.nr_uarts=1 root=/dev/mmcblk0p2 rootwait console=tty1\
console=ttyS0,115200"
U-Boot> setenv bootcmd "fatload mmc 0 ${kernel_addr_r} Image;\
fatload mmc 0 ${fdt_addr_r} bcm2837-rpi-3-b.dtb;\
booti ${kernel_addr_r} - ${fdt_addr_r}"
U-Boot> saveenv
Cihaz sonraki açılışlarda u-boot önyükleyicisi bootcmd değişkeni ile gösterilen işlemleri otomatik olarak yapacaktır.