TT#4 Fault Analyzer

Każdy programista mikrokontrolerów ARM prędzej czy później napotka w swoim kodzie błąd, który powoduje zatrzymanie się programu w obsłudze przerwania od HardFault. Jak znaleźć i zdiagnozować przyczynę? O tym w dzisiejszym wpisie.

Materiał jest częścią Tips and Tricks – serii artykułów dotyczących ciekawostek o STM32

czyli przydatnych, choć rzadko opisywanych elementów z ekosystemu STM32.

Fault Analyzer to narzędzie wbudowane w środowisko STM32CubeIDE, które pomaga zinterpretować informacje pozyskane z zagnieżdżonego kontrolera przerwań NVIC w celu zidentyfikowania przyczyn, które spowodowały błąd działania rdzenia. Informacje te są wizualizowane w widoku analizatora błędów i pomagają identyfikować i rozwiązywać trudne do znalezienia błędy systemowe, które występują, gdy procesor jest wprowadzany w stan błędu przez oprogramowanie aplikacji.

Jakie mogą być przyczyny błędów systemowych? Oto kilka najczęściej spotykanych:

  • Próba uzyskania dostępu do nieprawidłowych lokalizacji w pamięci
  • Wykonywanie niezdefiniowanej instrukcji
  • Dzielenie przez zero

Błędy zostały podzielone na kilka kategorii:

  • Hard Fault oraz Bus Fault – występują, gdy podjęta zostanie próba nieprawidłowego dostępu przez magistralę, rejestru układu peryferyjnego, albo pamięci
  • Usage Fault – powstają w wyniku niedozwolonych instrukcji lub innych błędów programu
  • Memory Managment Fault – obejmują próby dostępu do nielegalnej lokalizacji lub naruszenia zasad utrzymywanych przez jednostkę ochrony pamięci (MPU)

Pełną listę błędów możemy zobaczyć po uruchomieniu trybu debugowania w oknie Fault Analyzera. Jeżeli okno nie uruchomi nam się automatycznie, możemy je otworzyć poprzez Window->Show View->Fault Analyzer.

Poza tym, aby dodatkowo ułatwić szukanie błędów, analizator wyświetla zawartość rejestrów MCU w momencie awarii. Pozwala to na odtworzenie stanu MCU w momencie wykonania błędnej instrukcji.

Jak wygląda taka analiza błędu? Spróbujmy wywołać sobie prosty do powtórzenia błąd np. dzielenie przez zero. Po uruchomieniu projektu w trybie debugowania i wystartowaniu programu, zatrzyma się ono w pliku z obsługą przerwań (w moim przypadku „stm32l4xx_it.c”), a konkretnie w funkcji HardFault_Handler(). Wówczas okno analizatora wygląda jak poniżej.

Widzimy zaznaczone pola „Bus, memory management or usage fault„, które mówi nam o ogólnym typie błędu, oraz w zakładce Usage Fault Details pole „Attempt to perform a division by zero„, które określa błąd bardziej szczegółowo. Dodatkowo możemy podejrzeć zawartość rejestrów wewnętrznych procesora.

Znajdziemy tam takie rejestry, jak:

  • SP (Stack Pointer) – wskaźnik stosu. Przechowuje on adres ostatnio zapisanej instrukcji na stos. W nawiasie podane jest, który wskaźnik stosu jest używany: MSP (Main Stack Pointer) lub PSP (Process Stack Pointer)
  • r0 do r12 – rejestry ogólnego przeznaczenia
  • LR (Link Register) – przechowuje adres powrotu do aktualnie wykonywanego podprogramu
  • PC (Program Counter) – licznik programu, który wskazuje adres instrukcji następną po ostatnio pobranej do wykonania
  • xPSR (Special-Purpose Program Status Register) – zawiera flagi statusów np. negative, zero, carry, overflow

Wiemy już jaki rodzaj błędu się pojawił. Jednak nasz program zatrzymał się w HardFault_Handler() i nie możemy zidentyfikować linii kodu, która wywołała błąd. W takim wypadku wystarczy, że klikniemy w ikonę w górnej części okna po prawej stronie.

Poszczególne ikony odpowiadają za:

  • Open editor on fault location – otwiera edytor kodu w miejscu wystąpienia błędu
  • Open dissasembly on fault location – wskazuje linię w edytorze deasemblacji w miejscu wystąpienia błędu
  • PC lub LR – wybór rejestru, z którego chcemy pobrać adres do podświetlenia w edytorze kodu lub deasemblacji

W ten sposób możemy dość łatwo odnaleźć źródło błędu. Moglibyśmy to odczytać bezpośrednio w rejestrów wewnętrznych (zresztą Fault Analyzer właśnie z nich korzysta), jednak mając gotowe narzędzie, które dodatkowo wizualizuje nam informację, szukanie błędów jest znacznie łatwiejsze.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *