Przykład minimalnego uruchamiania Newlib
Tutaj podaję wysoce zautomatyzowany i udokumentowany przykład pokazujący newlib w działaniu w QEMU .
Dzięki newlib możesz zaimplementować własne wywołania systemowe dla swojej platformy baremetal.
Na przykład w powyższym przykładzie mamy przykładowy program exit.c
:
#include <stdio.h>
#include <stdlib.h>
void main(void) {
exit(0);
}
a w osobnym pliku C common.c
implementujemy semihostingexit
z ARM :
void _exit(int status) {
__asm__ __volatile__ ("mov r0, #0x18; ldr r1, =#0x20026; svc 0x00123456");
}
Inne typowe wywołania systemowe, które zaimplementujesz, to:
write
wyprowadzać wyniki do hosta. Można to zrobić za pomocą:
- więcej półhostingu
- sprzęt UART
brk
dla malloc
.
Łatwo na boso, ponieważ nie musimy przejmować się stronicowaniem!
TODO Zastanawiam się, czy realistyczne jest osiągnięcie wyprzedzającego wykonania syscalls planowania bez wchodzenia w pełną wersję RTOS, taką jak Zephyr lub FreeRTOS .
Fajną rzeczą w Newlib jest to, że implementuje on wszystkie rzeczy niezwiązane z systemem operacyjnym, takie jak string.h
dla ciebie, i pozwala implementować tylko pośredniczące systemu operacyjnego.
Nie musisz też implementować wszystkich kodów pośredniczących, ale tylko tych, których będziesz potrzebować. Na przykład, jeśli twój program potrzebuje tylko exit
, nie musisz podawać print
.
Drzewo źródeł Newlib ma już pewne implementacje, w tym implementację półhostingu ARM pod newlib/libc/sys/arm
, ale w większości musisz implementować własną. Stanowi jednak solidną podstawę do zadania.
Najprostszym sposobem na skonfigurowanie Newlib jest zbudowanie własnego kompilatora za pomocą crosstool-NG, wystarczy powiedzieć, że chcesz używać Newlib jako biblioteki C. Moja konfiguracja obsługuje to automatycznie za pomocą tego skryptu , który korzysta z konfiguracji newlib obecnych w crosstool_ng_config
.
Myślę, że C ++ również będzie działał, ale TODO to przetestuje.