Mengimplementasikan `printf` tanpa OS - Memanfaatkan pustaka standar C di lingkungan Bare Metal
(popovicu.com)- Memperkenalkan cara menggunakan fungsi standar C termasuk
printftanpa sistem operasi dengan memanfaatkan pustaka Newlib - Di lingkungan Bare Metal berbasis arsitektur RISC-V, driver UART dan fungsi alokasi memori diimplementasikan langsung lalu dihubungkan ke Newlib
- Dengan mengimplementasikan fungsi system call minimum seperti
_write,_sbrk,_close, fitur tingkat tinggi sepertiprintfpun dapat digunakan - Menjelaskan cara membuat toolchain berbasis Newlib bersama toolchain RISC-V GCC, termasuk build otomatis dan penulisan linker script
- Hasilnya, berhasil membangun lingkungan
printfyang juga mendukung output UART, inputscanf, hingga alokasi memori dinamis
Abstraksi perangkat lunak dan pustaka standar C
- Pada OS umum, saat
printfdipanggil, berbagai lapisan abstraksi seperti system call kernel, lapisan terminal, dan font rendering ikut bekerja - Di lingkungan Bare Metal, kontrol I/O harus dilakukan langsung tanpa sistem operasi, sehingga implementasi driver secara manual diperlukan
- Newlib menyediakan susunan yang dapat diperluas dengan hanya mengimplementasikan fungsi minimum, alih-alih seluruh pustaka standar C
Konsep Newlib
printfsecara internal diimplementasikan berdasarkan fungsi primitif sederhana seperti_write- Pada awalnya, Newlib mendefinisikan semua fungsi dalam bentuk dummy, sehingga cukup mengimplementasikan bagian yang diperlukan dan sisanya dapat memakai nilai bawaan
- Jika pengembang hanya mengimplementasikan fungsi yang dibutuhkan, fitur pustaka C dapat digunakan secara fleksibel
Toolchain cross-compilation
- Untuk cross-compile dari x86_64/Linux → RISC-V, perlu build langsung dari source GCC
- Dengan membangun toolchain yang menggunakan Newlib sebagai pustaka C bawaan, sistem dapat dikonfigurasi agar mampu membangun biner untuk RISC-V
Detail toolchain
- Saat membangun toolchain, digunakan opsi
--prefix,--enable-multilib,--disable-gdb,--with-cmodel=medany medanyadalah pengaturan di RISC-V yang memungkinkan akses ke area memori beralamat tinggi- Setelah build selesai, cross-compiler dan pustaka Newlib dapat digunakan dari path
/opt/riscv-newlib
Mengimplementasikan blok penyusun memori dan UART
- Implementasi kirim-terima karakter dilakukan dengan mengakses langsung alamat hardware 16550A UART di lingkungan QEMU
- Newlib dihubungkan melalui implementasi fungsi pengganti system call seperti
_write,_sbrk,_close _sbrkbekerja dengan cara memperluas memori heap dari titik_endhingga_stack_bottom
Contoh aplikasi: input dan output
- Di fungsi
main,printfdanscanfdapat digunakan, dan nilai input juga diproses dengan benar - Echo tidak didukung, tetapi input string dapat diterima dan ditampilkan melalui
scanf - Runtime terpisah diimplementasikan untuk menginisialisasi stack dan melakukan zero-fill pada section BSS sebelum memanggil
main
Linker script
- Alamat awal eksekusi adalah
0x80000000, dan kode runtime ditempatkan di lokasi tersebut - Memori disusun dalam urutan
.text,.rodata,.data,.bss, dan heap ditetapkan dari_endhingga sebelum stack - Stack memiliki ukuran tetap 64KB, dan alamat paling atasnya adalah
0x80000000 + 64MB - Tabrakan antara heap dan stack dicegah melalui pernyataan
ASSERT
Momen “gotcha”
- Saat mengatur toolchain,
--with-cmodel=medanyharus digunakan agar instruksi machine code yang mampu menangani alamat di atas0x80000000dapat dihasilkan - Jika model alamat pada pustaka C dan kode aplikasi berbeda, akan terjadi link error
Menjalankan aplikasi
- Melalui Makefile, cross-compile dan eksekusi QEMU dapat diotomatisasi
- Opsi
-specs=nosys.specs,-nostartfiles,-T link.lddigunakan untuk konfigurasi minimum Newlib dan runtime kustom - Saat menjalankan
make debug, input dan output melalui UART berfungsi normal di konsol QEMU - Jejak instruksi aktual dapat diperiksa melalui
qemu_debug.log
Kesimpulan
- Struktur yang memungkinkan penggunaan
printf,scanf,malloc, dan lainnya tanpa sistem operasi berhasil diimplementasikan dengan Newlib - Dengan memanfaatkan struktur berbasis building block milik Newlib, strategi kuncinya adalah hanya mengimplementasikan fungsi minimum yang dibutuhkan
- Ke depannya, fungsi tambahan seperti file system dan manajemen memori juga bisa diimplementasikan, dan tetap dapat digunakan ulang di Bare Metal sambil mempertahankan kompatibilitas pustaka
- Hasil keseluruhan proyek berukuran sekitar 220KB, sehingga relatif kecil dan efisien
Source GitHub: popovicu/bare-metal-cstdlib
Belum ada komentar.