14 puan yazan GN⁺ 2025-05-06 | Henüz yorum yok. | WhatsApp'ta paylaş
  • Newlib kütüphanesi kullanılarak işletim sistemi olmadan da printf dahil 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, _close gibi asgari sistem çağrısı fonksiyonlarının uygulanmasıyla bile printf gibi 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ışı, scanf girişi ve dinamik bellek ayırmaya kadar çalışan bir printf ortamı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 _write gibi 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=medany seç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-newlib yolunda 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, _close gibi sistem çağrısı yerine geçen fonksiyonlar uygulanarak Newlib’e bağlanır
  • _sbrk, heap belleğini _end noktasından _stack_bottom konumuna kadar genişletecek şekilde çalışır

Application example: input and output

  • main fonksiyonunda printf, scanf kullanılabilir ve giriş değerleri de düzgün işlenir
  • Echo desteklenmese de scanf ile 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 0x80000000 olup runtime kodu bu konuma yerleştirilir
  • Bellek .text, .rodata, .data, .bss sırasıyla yerleştirilir ve heap, _end noktası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 ASSERT ifadesi kullanılır

The ‘gotcha’ moment

  • Toolchain yapılandırılırken --with-cmodel=medany kullanılmalıdır; böylece 0x80000000 ü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.ld seçenekleriyle Newlib’in asgari ayarları ve kullanıcı tanımlı runtime kullanılır
  • make debug çalıştırıldığında QEMU konsolunda UART üzerinden giriş ve çıkışın düzgün çalıştığı görülür
  • qemu_debug.log üzerinden gerçek komut izleri incelenebilir

Conclusion

  • Newlib ile işletim sistemi olmadan da printf, scanf, malloc gibi 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.

Henüz yorum yok.