Narzędzia do rozwiązywania problemów w systemach z mikrokontrolerami z rdzeniem Cortex-M3/M4

Przysłowie mówi, że „jeden obraz zastępuje tysiąc słów”. Idąc tym tropem, tematem niniejszego artykułu uczyniono wykorzystanie możliwości graficznego przedstawienia informacji w zastosowaniu do trudnego zwykle procesu debugowania oprogramowania systemów wbudowanych. Nowoczesne, zintegrowane środowiska projektowe, takie jak Atollic TrueSTUDIO dają inżynierom wiele możliwości wizualizacji przebiegu pracy aplikacji, nawet w najbardziej wyrafinowanych implementacjach. W niniejszym tekście przestawiono dwa narzędzia śledzenia pracy aplikacji z graficzną wizualizacją informacji: debugowanie metodą kernel-aware (KA) oraz interfejs Serial Wire Viewer (SWV). Oba mechanizmy zostaną tu omówione na przykładzie mikrokontorlerów z rdzeniem Cortex-M3 i M4.

Ogólnie o debugowaniu

Szukanie błędów w oprogramowaniu jest często trudne i pracochłonne. Mimo, że istnieje wiele podręczników dotyczących technik rozwoju oprogramowania, stosunkowo nieliczne omawiają właśnie tę kwestię. Najlepsze techniki znaleźć można oczywiście nie w literaturze, a u doświadczonych inżynierów, a rozprzestrzenianie tej wiedzy postępuje powoli poprzez ukazujące się okazjonalnie artykuły, tutoriale oraz w prywatnych rozmowach i podczas szkoleń. Wiele nauki wynieść można także z walki z własnym kodem metodą prób i błędów. We wczesnych stadiach projektu, gdy pisane są pojedyncze funkcje i bloki kodu, trudności w debugowaniu są zwykle nieznaczne. Sprawy komplikują się o rzędy wielkości z upływem czasu, podczas integracji całości kodu i testów. Co więcej, jest to zwykle moment, w którym nie zbywa nam czasu – po miesiącach rozwoju specyfikacji i wymagań, wyboru narzędzi i sprzętu, pisania kodu i wstępnych testów wiele projektów jest już opóźnionych. Najcięższa i najbardziej frustrująca część projektu jest więc dodatkowo utrudniana przez ogromną presję na to, aby produkt trafił do sprzedaży.

 

Rys. 1. Narzędzia do inspekcji kodu w Atollic TrueSTUDIO

Rys. 1. Narzędzia do inspekcji kodu w Atollic TrueSTUDIO

 

Oczywiście najlepszą metodą skracania i upraszczania całego procesu debugowania jest zapobieganie powstawaniu błędów. Da się na tym polu osiągnąć znaczne postępy wykorzystując dobre praktyki programowania, opisywane w wielu książkach, np. w świetnej „Test Driven Development for Embedded C” Jamesa W. Grenninga. Inne ważne metodologie w tym zakresie obejmują: ścisłe przestrzeganie standardów pisania kodu oraz wykorzystanie tzw. inspekcji kodu (ang. code review) przez osobę, która go nie pisała. Narzędzia wspomagające inspekcję kodu są wbudowane w środowisko Atollic TrueSTUDIO. Rysunek 1 przedstawia widok ekranu w trakcie trwania takiej inspekcji, w czasie której jeden z oceniających napotyka w kodzie tzw. „magiczną liczbę” (ang. magic number), czyli stałą umieszczoną bez opisu. Nie musi to oczywiście być błąd, ale jest duża szansa, że taki fragment kodu spowoduje problemy przy próbach modyfikacji czy przenoszenia oprogramowania na inny układ docelowy.

Kilka uwag historycznych dotyczących debugowania przez JTAG

Doświadczeni inżynierowie pamiętają pewnie, że był taki czas, kiedy „złotym standardem” w debugowaniu był tzw. in-circuit emulator (ICE). Technika ta podzieliła jednak los dinozaurów, głównie z powodu kosztów i problemów z zawodnością pojawiających się ze wzrostem częstotliwości taktowania zegara. Pustkę po ICE wypełniło wiele starych i nowszych technik, od rozwiązań w stylu migających diod LED i użycia funkcji printf(), przez monitory stanu pamięci ROM i jej emulatorów, aż do różnych implementacji debugowania w tle (ang. Background Debug Mode, BDM). JTAG, w zamyśle stworzony do tzw. boundary scanningu układów scalonych, zaczął zaznaczać swoją obecność w świecie systemów wbudowanych jako praktyczna technika debugowania pod sam koniec XX wieku i od tamtej pory wciąż nabiera znaczenia.

Debugowanie przy pomocy JTAG’a odbywa się przy użyciu trzech zasadniczych elementów. Są to:

  1. dodatkowe bloki w układzie scalonym umożliwiające transmisję informacji i sterowania do zewnętrznego systemu debugującego na komputerze hostującym,
  2. sprzęt włączony między komputer i system wbudowany, tłumaczący informacje z systemu debugującego w układzie scalonym na postać użyteczną dla interfejsu komunikacyjnego (np. UART, USB czy LAN), w Polsce nazywany często po prostu JTAG’iem,
  3. aplikacja na komputerze hostującym wysyłająca i odbierająca informacje i sterująca badanym systemem wbudowanym oraz wyświetlająca potrzebne dane w formie graficznej.

Tradycyjnie narzędzia do debugowania z wykorzystaniem JTAG’a pozwalają uruchomić cały program, uruchomić program do określonego miejsca, przechodzić kod w trybie krokowym oraz zakładać pułapki (ang. breakpoint). Dostępny jest też zwykle podgląd i możliwość zmiany zawartości pamięci. Rozszerzenie wbudowanych w układ scalony bloków do debugowania nazwane embedded trace macrocell (ETM) pozwala dodatkowo na śledzenie wykonywania instrukcji oraz używanyh danych. ETM spotykane było jednak zwykle tylko w drogich, najbardziej skomplikowanych układach.

W połowie pierwszej dekady XXI wieku firma ARM z Cambridge zaprezentowała specyfikację rozszerzenia architektury mikrokontrolerów z rdzeniem ARM Cortex nazwanego CoreSight, która znacznie poszerzyła możliwości tradycyjnego debugowania przez JTAG. Jak było już wspomniane, w niniejszym artykule uwaga została skupiona na mikrokontrolerach z rdzeniami Cortex-M3 i M4. W architekturach tych CoreSight nie został zaimplementowany w całości, co było podyktowane chęcią zachowania bez zmian podstawowego, taniego szkieletu architektury Cortex-M. Niemniej jednak, zysk w tej sytuacji jest po stronie inżyniera wykorzystującego mikrokontrolery z rdzeniem Cortex, jako że możliwości debugowania zostały i tak znacznie powiększone, a cena pozostała niewygórowana. Technika debugowania wprowadzona wraz z CoreSight nosi nazwę Serial Wire Viewer (SWV).

O autorze