• Newlib library का उपयोग करके operating system के बिना भी printf सहित C standard functions का उपयोग संभव बनाने की implementation method का परिचय
  • RISC-V architecture आधारित Bare Metal environment में UART driver और memory allocation functions को सीधे implement करके Newlib से जोड़ा गया
  • _write, _sbrk, _close जैसी न्यूनतम system call functions की implementation मात्र से printf जैसे advanced features का उपयोग संभव
  • Newlib-आधारित toolchain बनाने के लिए RISC-V GCC toolchain के साथ automatic build और linker script लिखने का तरीका बताया गया
  • परिणामस्वरूप UART output, scanf input और dynamic memory allocation तक काम करने वाला printf environment सफलतापूर्वक बनाया गया

Software abstractions and C standard library

  • सामान्य OS में printf call करने पर kernel system call, terminal layer, font rendering जैसी कई abstraction layers काम करती हैं
  • Bare Metal environment में operating system के बिना सीधे input/output control की ज़रूरत होती है, और इसके लिए driver को सीधे implement करना पड़ता है
  • Newlib पूरी C standard library के बजाय केवल न्यूनतम features implement करके extendable configuration प्रदान करता है

Newlib concept

  • printf अंदरूनी रूप से _write जैसे सरल primitive functions के आधार पर implement होता है
  • Newlib में शुरुआत में सभी functions dummy form में defined होते हैं, और ज़रूरी हिस्से implement करने पर बाकी में default behavior इस्तेमाल किया जा सकता है
  • developer केवल आवश्यक functions implement करके लचीले तरीके से C library features का उपयोग कर सकता है

Cross-compilation toolchain

  • x86_64/Linux → RISC-V cross-compilation के लिए GCC source से सीधे build की आवश्यकता होती है
  • Newlib को default C library के रूप में सेट किए गए toolchain को बनाकर RISC-V binaries build करने योग्य configuration तैयार की जाती है

Toolchain details

  • toolchain build करते समय --prefix, --enable-multilib, --disable-gdb, --with-cmodel=medany options का उपयोग किया गया
  • medany RISC-V में high-address memory region तक access संभव बनाने वाली setting है
  • build पूरा होने के बाद /opt/riscv-newlib path पर cross-compiler और Newlib library उपलब्ध हो जाते हैं

Implementing the memory and UART building blocks

  • QEMU environment के 16550A UART hardware address को सीधे access करके character send/receive implement किया गया
  • _write, _sbrk, _close जैसी system call replacement functions implement करके Newlib से जोड़ा गया
  • _sbrk heap memory को _end point से _stack_bottom तक extend करने के तरीके से काम करता है

Application example: input and output

  • main function में printf, scanf का उपयोग संभव है, और input values भी सही तरह process होती हैं
  • echo support नहीं है, लेकिन scanf के जरिए string input लेकर output किया जा सकता है
  • अलग runtime implement करके stack initialization और BSS section zero-fill के बाद main को call किया जाता है

Linker script

  • execution start address 0x80000000 है, और runtime code को उसी location पर रखा गया है
  • memory layout .text, .rodata, .data, .bss क्रम में रखा जाता है, और heap को _end से stack से ठीक पहले तक सेट किया गया है
  • stack 64KB fixed size का है, और सबसे ऊपरी address 0x80000000 + 64MB है
  • ASSERT statement के माध्यम से heap और stack के टकराव को रोका गया है

The ‘gotcha’ moment

  • toolchain configure करते समय --with-cmodel=medany का उपयोग करना ज़रूरी है ताकि 0x80000000 से ऊपर के addresses को संभाल सकने वाले machine instructions generate किए जा सकें
  • यदि C library और application code का address model अलग हो, तो link error होता है

Running the app

  • Makefile के जरिए cross-compile और QEMU execution को automate किया जा सकता है
  • -specs=nosys.specs, -nostartfiles, -T link.ld options से Newlib की minimal configuration और custom runtime का उपयोग किया गया
  • make debug चलाने पर QEMU console में UART के जरिए input और output सही तरह काम करते हैं
  • qemu_debug.log के जरिए वास्तविक instruction trace देखा जा सकता है

Conclusion

  • operating system के बिना भी printf, scanf, malloc आदि का उपयोग संभव बनाने वाली संरचना Newlib से implement की गई
  • Newlib की building-block आधारित संरचना का उपयोग करते हुए, ज़रूरी features को ही न्यूनतम रूप में implement करना मुख्य रणनीति है
  • आगे file system, memory management जैसी अतिरिक्त features भी implement की जा सकती हैं, और library compatibility बनाए रखते हुए Bare Metal में भी reuse संभव है
  • पूरे project का output लगभग 220KB है, जो अपेक्षाकृत छोटा और efficient स्तर है

GitHub source: popovicu/bare-metal-cstdlib

अभी कोई टिप्पणी नहीं है.

अभी कोई टिप्पणी नहीं है.