Środowisko Krzysztof Świentek Systemy wbudowane Spis treści 1 2
Źródła 1 http://infocenter.arm.com 2 http://www.keil.com/arm/mdk.asp 3 http://pl.wikipedia.org Spis treści 1 2
Co to jest toolchain? Zbiór narzędzi programistycznych potrzebnych do wygenerowania działajacego programu Typowy toolchain składa się z: kompilatora, asemblera, linkera, biblioteki standardowej W skład toolchain a wchodzi też często debugger Toolchain buduje się dla konkretnej architektury tzn. robimy kompilator, linker, bibliotekę standardowa i inne narzędzia Biblioteki C implementujace POSIX API: glibc uniwersalna, ale duża Embedded glibc (eglibc) zoptymalizowana dla systemów wbudowanych, odchudzone glibc, zarzucone uclib powstała jako wsparcie dla µclinux, Linux a bez MMU musl stosunkowo nowy, szybka, prosta Biblioteka standardowa musi zostać wybrana na etapie tworzenia kompilatora! Budowanie toolchain a Tworzymy jednocześnie wszystkie narzędzia potrzebne do zbudowania działajacej aplikacji. Czyli co? Rozróżniamy trzy, w ogólności różne, maszyny build machine tam gdzie toolchain powstaje host machine tam gdzie toolchain będzie odpalony target machine dla której toolchain generuje kod Sposoby budowy toolchain ów natywny toolchain zwykłe narzędzia np. w dystrybucji Linux a cross-kompilowany toolchain najczęściej wykorzystywany, zbudowany na platformie x86 dla x86, a tworzacy kod np. dla ARM a cross-natywny toolchain zbudowany na np. x86, dla ARM a, aby go tam odpalać canadian build budujemy na maszynie A, aby odpalać na B i generować kod dla C; zazwyczaj niepotrzebny Typowy efekt budowy toolchain to cross-kompilator
Binarny interfejs aplikacji ABI binarny interfejs aplikacji (ang. Application Binary Interface) ABI to interfejs pomiędzy np. bibliotekami i systemem operacyjnym na poziomie kodu maszynowego ABI jest podobne do API, ale nie na poziomie kodu źródłowego, ale skompilowanego ABI obejmuje zbiór rozkazów rozmiar,layout i aligment typów danych sposób wywoływania funkcji tzw. calling convention: sposób przekazywania parametrów do funkcji i zwracania rezultatu EABI (Embedded ABI) zazwyczaj znacznie prostsze (brak dll i) formaty plików wykorzystanie rejestrów procesora organizacja stosu itp.... Nas obejmuje ARM EABI dba o to kompilator Spis treści 1 2
MDK Microcontroller Development Kit (MDK) Zamiast MDK może być też DS-5, jedno i drugie jest wspierane przez ARM Holdings Środowisko: µvision IDE Nasz toolchain Kompilator armcc wersja 5.05 Asembler armasm wersja 5.05 Linker armlink wersja 5.05 Budowanie statycznych bibliotek armar wersja 5.05 Konwersja wyniku fromelf wersja 5.05 Biblioteka: ARM C microlib prawie 3 razy mniejsza niż standardowa Biblioteka: Rogue Wave C++ Biblioteka: C++ Standard Template Library (STL) µvision debugger (i symulator) Alternatywnie może być toolchain oparty o narzędzia GNU Niestandardowe funkcje kompilatora I modyfikator weak można stosować do funkcji i zmiennych funkcja o takiej samej nazwie bez modyfikatora zostanie zlinkowana w miejsce funkcji słabej sporo funkcji jest tak zdefiniowanych np. wszystkie przerwania #pragma import(symbol_name) importuje referencję do symbol_name można właczyć/wł aczyć pewne funkcje biblioteki standardowej np.: wyłaczyć implementację sterty use_no_heap zmienić implementację use_realtime_heap tzw. szybkiego dzielenia use_realtime_division ANCI C stdio use_full_stdio wolniejsze memcpy use_smaller_memcpy... itp.
Niestandardowe funkcje kompilatora II wsparcie dla pól bitowych typedef struct { int i : 1; int j : 2; } BB attribute ((bitband)); BB value; // Unplaced object void update_value(void) { value.i = 1; value.j = 0; } dodatkowy typ danych Semihosting Co zrobić z printf jeżeli system nie ma odpowiedniego wyjścia? Komunikacja z debuggerem przez link debugujacy Debugger (sprzętowo) musi obsługiwać tracing Implementowane poprzez SVC (formalnie SWI)
Wyłaczanie czyli retargeting Wyłaczenie semihosting u: #pragma import( use_no_semihosting_swi) Zawsze implementujemy strukturę FILE Dla printf trzeba zaimplementować fputc, stdout oraz (opcja) ferror Dla scanf trzeba zaimplementować fgetc, stdin oraz backspace Gdzie możemy wysłać (skad wczytać) strumień znaków? Te same zasady dotycza putchar i puts oraz getchar i gets Może zajść konieczność zdefiniowania także _sys_exit ta funkcja nie może wrócić, musi zawierać pętlę nieskończona! Mechanizm Sub/Super Jak nadpisać funkcję której nie można zmodyfikować? Mamy dwie deklaracje nadrzędna i podrzędna z odpowiednim prefiksem $Sub$$ lub $Super$$ int $Super$$fputc(int c, FILE *fp); int $Sub$$fputc(int c, FILE *fp) { if (fp == (FILE *)MAGIC_NUM) { write_to_uart(c); return c; } else { return $Super$$fputc(c, fp); } } Można wykorzystać do podmiany fputc bez wyłaczania semihosting u Obsługiwane na poziomie linkera armlink, działa tylko przy linkowaniu statycznym Można tak też opakować np. funkcję main