Ostatnio na live omawiałem IDE i debugery sprzętowe w embedded. Nagranie jest dostępne tutaj:

Pod nagraniem są też timestampy i linki. Wyszło tego bardzo dużo więc lepiej to będzie zebrać we wpisie. Od razu zapraszam również na kolejny live w czwartek 28 maja o 20:00, gdzie tematem będą języki programowania w embedded.

Rodzaje IDE

Możemy wyróżnić trzy podstawowe grupy IDE. Poniżej każda grupa i linki do kilku reprezentantów.

IDE od producentów procesorów:

IDE do własnej konfiguracji działające z wieloma rodzinami procesorów:

Drogie IDE, najczęściej w pakiecie z kompilatorami czy innymi narzędziami:

Zarówno producenci procesorów, jak i drogich IDE często dodają również wtyczki do Eclipse. Jednak bardzo często nie działają one poprawnie z nowszymi wersjami i nie są tak często aktualizowane.

Jak skonfigurować Eclipse

Jakiś czas temu umieszczałem tutoriale konfiguracji pod Eclipse:

Jednak narzędzia zmieniają się z nowymi wersjami i stare wtyczki przestają działać. Dlatego niestety jeżeli chcemy mieć aktualną wersję, musimy śledzić zmiany i wprowadzać je na bieżąco.

Jak skonfigurować VS Code

Aby móc kompilować za pomocą komend z VS Code, musimy stworzyć plik tasks.json z odpowiednimi komendami kompilacji. Ja korzystałem z tego tutoriala.

Z kolei debug na hardware umożliwiają pluginy takie jak Cortex-debug. Oczywiście do mniej popularnych procesorów pewnie nie będzie plugina. Konfigurację debugu przechowujemy w pliku launch.json w folderze .vscode naszego projektu. Umieściłem na GitHubie swój szablon konfiguracji. Ja korzystam z OpenOCD, natomiast wspierane jest również kilka innych opcji jak np. Segger J-Link.

Plugin korzysta z plików SVD (System View Description). To format tekstowy zapisywania konfiguracji procesora wymyślony przez ARM. Wszyscy producenci ARMów udostępniają pliki konfiguracyjne dla swoich procesorów. Na GitHubie jest repo z plikami SVD dla różnych procesorów. Jednak jest ono dosyć stare, dlatego części procesorów może brakować, mogą być też stare wersje. Alternatywnie można skorzystać z pluginów do VS-Code zawierających pliki SVD dla poszczególnych rodzin procesorów. Jak na przykład ten plugin dla STM32F4.

Debugery sprzętowe

Tutaj mamy do wyboru tanie debugery od producentów chipów jak np. ST-Link. Działają one tylko z tym konkretnym rodzajem procesorów. Alternatywą są droższe debugery wspierające wiele rodzin od różnych producentów. Przykładami mogą być:

Takie debugery to już wydatek rzędu 2000 zł (a w przypadku Lauterbacha nawet kilka razy więcej). Poza wsparciem wielu procesorów mają one dodatkowe opcje takie jak np. trace, szybka konsola debugowa, czy wsparcie dla RTOSów.

Wsparcie debugu RTOSów możemy też osiągnąć przy pomocy zewnętrznych rozwiązań takich jak Percepio Tracealyzer.

Istnieje też opcja zrobienia sobie debugera na podstawie projektu PCB i gotowego wsadu. Projekt to JTAG-lock-pick i został stworzony przez Freddiego Chopina.

Emulatory procesorów

Emulacja pozwala nam na debug bez posiadania prawdziwego sprzętu. Czasami emulatory są udostępniane przez producentów jako część ich IDE. Można również skorzystać z otwartego rozwiązania jak QEMU pozwalającego emulować ARMy.

Emulatory pozwalają również zdefiować działanie hardware’u podłączonego do naszego procesora np. eventy w odpowiedzi na ustawienie konkretnych stanów pinów. Konfiguracja bywa dosyć żmudna, ale czasami może to być opłacalne.

Kompilacja a debugowanie

Jeżeli chcecie korzystać z debugera, nie zapomnijcie skompilować projektu z flagami debugowymi. Dzięki temu zostaną dodane odpowiednie symbole, które umożliwią wam podglądanie zmiennych itp. W gcc najprościej włączyć debug za pomocą flagi -g. Mamy również do dyspozycji bardziej zaawansowane opcję, ale tutaj odsyłam do dokumentacji kompilatora.

Drugą ważną sprawą są flagi optymalizacji. Im więcej optymalizacji włączymy, tym bardziej instrukcje będą się różnić od kodu źródłowego. W efekcie podczas stepowania będziemy skakali w różne dziwne miejsca w kodzie. W gcc istnieje flaga -Og włączająca optymalizacje nie utrudniające debugu.

Niestety czasem nie mamy wyboru i musimy debugować zoptymalizowany kod. Niektóre problemy ujawniają się dopiero, kiedy jakieś flagi debugowe są włączone. Bardzo często uznajemy za winowajcę kompilator i twierdzimy, że flagi optymalizacji potrafią zepsuć poprawny kod. Jednak zwykle prawda jest taka, że bazujemy na nieprawdziwych założeniach i nasz kod zawiera undefined behavior, które objawiają się przy większej optymalizacji. Przykład takiego problemu jest opisany tutaj.

I na koniec przypominam jeszcze o kolejnym live w czwartek o 20:00. Tematem będą języki programowania w embedded.