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.cimplementujemy 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:
writewyprowadzać wyniki do hosta. Można to zrobić za pomocą:
- więcej półhostingu
- sprzęt UART
brkdla 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.