Strona główna Artykuły ARM bleeding-edge-toolchain - o co chodzi?
bleeding-edge-toolchain - o co chodzi?
Ocena użytkowników: / 30
SłabyŚwietny 
Wpisany przez Freddie Chopin   
Sobota, 09 Luty 2013 14:55

Niektórzy zapewne zauważyli, że w dziale Download pojawiła się nowa kategoria - Programy > bleeding-edge-toolchain - a w niej całkiem spore pliki o nazwach wskazujących na to, iż są to kompilatory typu bare-metal dla układów z rdzeniem ARM... "Na rynku" jest już przecież CodeSourcery (zwane teraz Sourcery CodeBench), linaro, Yagarto, jakby się uprzeć są jeszcze prehistoryczne pakiety GNUARM i WinARM, zapewne jeszcze kilka o których (na razie) nie wiem - po co więc kolejny? Nawet nazwy sensownej mu nadać nie można, bo Yet Another Gnu ARm TOolchain jest już zajęte (;

Może więc na początek odrobinę historii. W zamierzchłych czasach (czyli jakieś 3-4 lata temu [; ), gdy ARMy zaczynały się robić naprawdę popularne (Cortex-M3 i te sprawy), najlepszym wyborem był pakiet CodeSourcery - była dostępna wersja dla Windowsa i Linuxa, pakiet był regularnie uaktualniany, programiści z firmy tworzącej go współpracowali ponoć z firmą ARM, no generalnie wszystko co trzeba. Niezliczone ilości stron w internecie (z tą włącznie) polecają go jako dobry punkt startu.

Gdy wyszły jednak pierwsze układy z rdzeniem Cortex-M4 i zintegrowaną jednostką zmiennoprzecinkową pojawił się pierwszy zgrzyt... Wpisując w konsoli arm-none-eabi-gcc -print-multi-lib otrzymujemy mniej więcej coś takiego:

...\Sourcery_CodeBench_Lite_for_ARM_EABI\bin>arm-none-eabi-gcc -print-multi-lib
.;
thumb;@mthumb
armv6-m;@mthumb@march=armv6-m
thumb2;@mthumb@march=armv7@mfix-cortex-m3-ldrd

...\Sourcery_CodeBench_Lite_for_ARM_EABI\bin>arm-none-eabi-gcc --version
arm-none-eabi-gcc (Sourcery CodeBench Lite 2012.09-63) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Oznacza to w skrócie tyle, że toolchain ten ma zintegrowane biblioteki standardowe (czyli np. bibliotekę libm.a z funkcjami matematycznymi) dla "standardowej" architektury ARM7 (ARMv4, tryb ARM i tryb THUMB) oraz dla Cortex-M0 (ARMv6-M, THUMB) oraz Cortex-M3 (ARMv7-M, THUMB2). Oczywiście przy pomocy tego toolchaina można tworzyć kod dla Cortex-M4, ponieważ architektura ARMv7-ME jest tylko "rozwinięciem" architektury ARMv7-M, ale o użyciu FPU (Floating Point Unit) musimy często zapomnieć. Jeśli ktoś ma fantazję to zawsze można oczywiście pisać w assemblerze lub korzystać z funkcji wchodzących w skład CMSIS, jednak podstawowe rzeczy, np.:

float a = 1.0f;
float b = logf(a);

zamiast skorzystać z dobrodziejstw FPU wykonają się przy użyciu algorytmów w 100% programowych... Dodatkowo w 2010 roku CodeSourcery zostaje przejęte przez firmę Mentor Graphics i support dla darmowej edycji Lite praktycznie zanika. Sugestie o dodanie wsparcia dla FPU w architekturze ARMv7-ME zbywane są informacją, że takie opcje (i nie tylko) dostępne są w płatnej wersji...

Na szczęście w tym samym czasie (2010) powstaje organizacja linaro, składająca się z firmy ARM i kilku jej największych partnerów, której celem jest rozwój i wspieranie otwartych narzędzi dla najnowszych układów z rdzeniem ARM. Choć nie da się ukryć, że głównym "targetem" dla linaro są procesory aplikacyjne z rdzeniem ARM Cortex-A i systemy typu Linux czy Android, to pod koniec 2011 roku pojawia się pierwsze wydanie pakietu o nazwie GNU Tools for ARM Embedded Processors. Od tego czasu nowe wersje pojawiają się 3-4x w roku i zawierają najnowszą wersję kompilatora, pochodzącą z brancha przeznaczonego specjalnie dla mikrokontrolerów (w tamtym czasie - /branches/ARM/embedded-4_6-branch, obecnie - /branches/ARM/embedded-4_7-branch). Dla odmiany względem pakietu CodeSourcery, pakiet ten zawiera bardzo bogatą kolekcję bibliotek:

...\GNU Tools ARM Embedded\4.7 2012q4\bin>arm-none-eabi-gcc -print-multi-lib
.;
thumb;@mthumb
fpu;@mfloat-abi=hard
armv6-m;@mthumb@march=armv6s-m
armv7-m;@mthumb@march=armv7-m
armv7e-m;@mthumb@march=armv7e-m
armv7-r/thumb;@mthumb@march=armv7-r
armv7e-m/softfp;@mthumb@march=armv7e-m@mfloat-abi=softfp@mfpu=fpv4-sp-d16
armv7e-m/fpu;@mthumb@march=armv7e-m@mfloat-abi=hard@mfpu=fpv4-sp-d16
armv7-r/thumb/softfp;@mthumb@march=armv7-r@mfloat-abi=softfp@mfpu=vfpv3-d16
armv7-r/thumb/fpu;@mthumb@march=armv7-r@mfloat-abi=hard@mfpu=vfpv3-d16

...\GNU Tools ARM Embedded\4.7 2012q4\bin>arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.7.3 20121207
(release) [ARM/embedded-4_7-branch revision 194305]
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Jak widać pakiet ten wspiera "klasyczne" ARM7 (ARM, THUMB), Cortex-M (ARMv6-M, ARMv7-M, ARMv7-ME) oraz Cortex-R (ARMv7-R) - wszystkie z możliwością wykorzystania sprzętowego FPU.

W tym momencie niektórzy mogą zapewne przestać czytać pytając na głos "czego chcieć więcej?"... Z pakietami linaro byłoby wszystko w porządku, gdyby nie jeden drobny problem - z niewiadomych przyczyn kompilacja dowolnego projektu trwa w nim 3-4x dłużej niż w pakiecie CodeSourcery...

Jednocześnie - bez związku z powyższym - od czasu do czasu miałem potrzebę stworzyć jakiś kod w C++ i we znaki dawały mi się wyjątki, których wbrew zasadzie "you don't pay for what you don't use" wcale nie da się po prostu wyłączyć. Aby się ich pozbyć (oczywiście ze względów na rozmiar pamięci w mikrokontrolerze) konieczna jest rekompilacja biblioteki standardowej C i C++ wchodzącej w skład kompilatora. (efekty tych kilku kompilacji można zresztą pobrać z działu Download > ARM > Różne - są tam dostępne paczki z samymi bibliotekami kompilatora z wyłączonymi wyjątkami C++)

Ostatnio zaś, przy okazji projektu jakim się zajmowałem, miałem też potrzebę skorzystania z nowej wersji biblioteki newlib, ponieważ (z moją pomocą) znajdowała się tam poprawka drastycznie ograniczająca zużycie pamięci przez funkcję fprintf(). Z racji tego, że projekt ten był dosyć spory, długi czas kompilacji zaczął mnie naprawdę irytować więc postanowiłem sprawdzić, czy wykorzystanie 64-bitowego procesora pozwoli znacząco przyspieszyć proces kompilacji.

Ostatni eksperyment pokazał, że użycie 64-bitowego kompilatora niewiele zmienia względem wersji 32-bitowej (zysk poniżej 10%), ale i tak "wyprodukowane" przezemnie kompilatory są kilkukrotnie szybsze niż oryginalne linaro, osiągając "wydajność" równą pakietom CodeSourcery. No i tak właśnie narodziła się koncepcja bleeding-edge-toolchain.

Podstawowe założenia są więc następujące:

  • oparty o pakiety linaro,
  • skompilowany najnowszym dostępnym kompilatorem, dla Windowsa użyty zostaje nowoczesny kompilator mingw-w64,
  • podstawowe komponenty (kompilator, newlib, gdb i binutils) pochodzą wprost z repozytoriów projektów, wykorzystane są najnowsze rewizje,
  • pozostałe komponenty (biblioteki potrzebne do kompilacji toolchaina) są w najnowszych stabilnych wersjach (chyba że dokumentacja zaleca zastosowanie konkretnej wersji),
  • wyłączona obsługa wyjątków C++ (pracuję nad dostępnością obydwóch wersji bibliotek, wybieranych przez pliki .specs),
  • wszystkie biblioteki kompilatora mają pozostawione informacje konieczne do debuggowania ich (nie są "stripped"),
  • biblioteka newlib z włączoną opcją reent-small i z wyłączonym wsparciem dla 64-bitowych liczb w funkcjach typu printf()/sprintf().

Jaki jest zysk z użycia takiego toolchaina? Przeprowadziłem wyjątkowo nudne porównanie czasu kompilacji dla 6 różnych projektów, porównując 3 pakiety w najnowszych wersjach (bleeding-edge-toolchain-130207 [32-bit], linaro - GCC ARM Embedded 4.7-2012-q4-major, CodeSourcery - Sourcery CodeBench Lite 2012.09-63) zarówno przy kompilacji sekwencyjnej jak i wielowątkowej (2 wątki). Wyniki przedstawia poniższa tabela.

 

rozmiar pliku wynikowego ilość plików źródłowych BET -j1 BET -j2 linaro -j1 linaro -j2 cs -j1 cs -j2
p1 12kB 29 12s 8s 48s 27,5s 12s 8s
p2 17kB 23 19s 12s 51,5s 30,5s 19,5s 12s
p3 30kB 39 17s 11,5s 62s 36,5s 16s 11s
p4 60kB 567 85,5s 40,5s* 96,5s 42s* 91s 40s*
p5 100kB 71 38,5s 24s 104,5s 59,5s -** -**
p6 130kB (30kB)*** 60 26,5s 18s 92s 54,5s 27s 17s

 

* - kompilacja przeprowadzona przy użyciu systemu tup, oryginalne pliki Makefile tego projektu nie nadają się do kompilacji wielowątkowej
** - brak możliwości kompilacji ze względu na niekompatybilność projektu i bibliotek kompilatora (inne opcje dotyczące reentrancy)
*** - około 100kB to rozmiar bitmap i czcionek, projekt zawiera około 30kB kodu

Wyniki są średnią z dwóch kompilacji. Każda kompilacja była poprzedzona pełnym "wyczyszczeniem" projektu (make clean). Liczba plików źródłowych uwzględnia tylko pliki które faktycznie były kompilowane (jest to w zasadzie liczba powstałych plików obiektowych). Pomiarów dokonano przy użyciu skryptu.

W ramach nagrody za te testy pozwolę sobie na drobny komentarz w punktach.

  1. Pakiet CodeSourcery zawiera w teorii inną wersję kompilatora (4.7.2) niż dwa pozostałe (4.7.3 prerelease).
  2. Projekt p4 ze względu na 567 plików źródłowych w zasadzie nie nadaje się do tego porównania - przypuszczalnie większość czasu komputer marnuje na uruchamianie kolejnych procesów kompilatora, więc wyniki dla wszystkich 3 pakietów są porównywalne.
  3. Wykluczając wspomniany powyżej projekt p4 można powiedzieć, że czas kompilacji przy użyciu bleeding-edge-toolchain jest 2.5-4x krótszy niż przy użyciu pakietu linaro.
  4. Wyniki bleeding-edge-toolchain są praktycznie identyczne do wyników CodeSourcery.
  5. Bliższe przyjrzenie się informacjom ze strony pakietu linaro każe przypuszczać, że powodem długiej kompilacji może być użycie wyjątkowo starej wersji systemu (Ubuntu-8.10) i narzędzi do kompilacji tegoż pakietu - zapewne w celu większej kompatybilności ze starszymi systemami operacyjnymi.

Ze względów na to, że kompilację pakietu przeprowadzałem przy użyciu 64-bitowego Linuxa nie udało mi się niestety skompilować pakietu w wersji na 32-bitowy system Linux, jednak zawarte w każdej paczce skrypty przeprowadzające kompilację pozwolą każdemu użytkownikowi takiego systemu na przeprowadzenie kompilacji we własnym zakresie (; Może w przyszłości uda mi się skompilować też i taką wersję - kto wie, na pewno będę próbował (;

Jeśli więc kogoś równie mocno jak mnie denerwują długie czasy kompilacji, to zapraszam do pobierania i używania pakietu bleeding-edge-toolchain (; Komentarze oczywiście jak zwykle mile widziane (;

Zmieniony: Niedziela, 10 Luty 2013 14:38