OS olmadan `printf` uygulamak - Bare Metal ortamında C standart kütüphanesini kullanma
(popovicu.com)- Newlib kütüphanesi kullanılarak işletim sistemi olmadan da
printfdahil C standart fonksiyonlarının kullanılmasını sağlayan yöntemin tanıtımı - RISC-V mimarisi tabanlı Bare Metal ortamında UART sürücüsü ve bellek ayırma fonksiyonlarının doğrudan uygulanıp Newlib’e bağlanması
_write,_sbrk,_closegibi asgari sistem çağrısı fonksiyonlarının uygulanmasıyla bileprintfgibi gelişmiş özelliklerin kullanılabilmesi- Newlib tabanlı bir toolchain oluşturmak için RISC-V GCC toolchain’i ile birlikte otomatik derleme ve linker script yazımının anlatılması
- Sonuç olarak UART çıkışı,
scanfgirişi ve dinamik bellek ayırmaya kadar çalışan birprintfortamının kurulmasının başarılması
Software abstractions and C standard library
- Normal bir OS ortamında
printfçağrıldığında çekirdek sistem çağrıları, terminal katmanı, font render etme gibi çeşitli soyutlama katmanları çalışır - Bare Metal ortamında ise işletim sistemi olmadan doğrudan G/Ç denetimi gerekir ve bunun için sürücülerin doğrudan uygulanması gerekir
- Newlib, tam C standart kütüphanesi yerine yalnızca asgari işlevleri uygulayarak genişletilebilir bir yapı sunar
Newlib concept
printf, dahili olarak_writegibi basit primitive fonksiyonlar üzerine kurulu biçimde uygulanır- Newlib’de başlangıçta tüm fonksiyonlar dummy biçimde tanımlanmıştır; yalnızca gereken parçalar uygulanırsa geri kalanı varsayılan olarak kullanılabilir
- Geliştirici yalnızca ihtiyaç duyduğu fonksiyonları uygularsa C kütüphanesi özelliklerini esnek biçimde kullanabilir
Cross-compilation toolchain
- x86_64/Linux → RISC-V çapraz derlemesi için GCC kaynak kodundan doğrudan derleme gerekir
- Varsayılan C kütüphanesi olarak Newlib ayarlanmış bir toolchain kurularak RISC-V için binary derlenebilecek şekilde yapılandırılır
Toolchain details
- Toolchain derlenirken
--prefix,--enable-multilib,--disable-gdb,--with-cmodel=medanyseçenekleri kullanılır medany, RISC-V’de yüksek adresli bellek alanlarına erişimi mümkün kılan bir ayardır- Derleme tamamlandıktan sonra
/opt/riscv-newlibyolunda cross-compiler ve Newlib kütüphaneleri kullanılabilir
Implementing the memory and UART building blocks
- QEMU ortamındaki 16550A UART donanım adresine doğrudan erişilerek karakter gönderme/alma uygulanır
_write,_sbrk,_closegibi sistem çağrısı yerine geçen fonksiyonlar uygulanarak Newlib’e bağlanır_sbrk, heap belleğini_endnoktasından_stack_bottomkonumuna kadar genişletecek şekilde çalışır
Application example: input and output
mainfonksiyonundaprintf,scanfkullanılabilir ve giriş değerleri de düzgün işlenir- Echo desteklenmese de
scanfile metin girişi alınıp çıktılanabilir - Ayrı bir runtime uygulanarak stack başlatılır, BSS bölümü sıfırlanır ve ardından
mainçağrılır
Linker script
- Çalıştırma başlangıç adresi
0x80000000olup runtime kodu bu konuma yerleştirilir - Bellek
.text,.rodata,.data,.bsssırasıyla yerleştirilir ve heap,_endnoktasından stack’e kadar ayarlanır - Stack sabit 64KB boyutunda olup en üst adres
0x80000000 + 64MBşeklindedir - Heap ile stack çakışmasını önlemek için
ASSERTifadesi kullanılır
The ‘gotcha’ moment
- Toolchain yapılandırılırken
--with-cmodel=medanykullanılmalıdır; böylece0x80000000üzerindeki adresleri işleyebilen makine komutları üretilebilir - C kütüphanesi ile uygulama kodunun adres modeli farklıysa linker hatası oluşur
Running the app
- Makefile üzerinden cross-compile ve QEMU çalıştırma işlemleri otomatikleştirilebilir
-specs=nosys.specs,-nostartfiles,-T link.ldseçenekleriyle Newlib’in asgari ayarları ve kullanıcı tanımlı runtime kullanılırmake debugçalıştırıldığında QEMU konsolunda UART üzerinden giriş ve çıkışın düzgün çalıştığı görülürqemu_debug.logüzerinden gerçek komut izleri incelenebilir
Conclusion
- Newlib ile işletim sistemi olmadan da
printf,scanf,mallocgibi işlevlerin kullanılabildiği bir yapı uygulanmıştır - Newlib’in building block tabanlı yapısından yararlanarak, yalnızca gerekli işlevleri asgari düzeyde uygulamak temel stratejidir
- İleride dosya sistemi, bellek yönetimi gibi ek işlevler de uygulanabilir ve kütüphane uyumluluğu korunarak Bare Metal ortamında yeniden kullanılabilir
- Tüm proje çıktısı yaklaşık 220KB olup görece küçük ve verimli bir düzeydedir
GitHub kaynağı: popovicu/bare-metal-cstdlib
Henüz yorum yok.