fbpx

Jeśli myślimy o debugowaniu to, co nam przychodzi do głowy? Breakpointy, praca krokowa, ale przede wszystkim printowanie. Mając do czynienia z mikrokontrolerami najczęściej komunikaty wysyłamy do terminala konsoli szeregowej na PC. Wykorzystujemy do tego jeden z interfejsów UART. Co jeśli tego UARTa nie mamy? Jest taki jeden sprytny mechanizm. Nazywa się Semiosting.

Czym jest Semihosting na STM32?

Jest to jedna z dostępnych metod debugowania programów na mikrokontrolerze. Mechanizmy, które się do tego wykorzystuje są wbudowane w rdzenie ARM. Semihosting dostępny jest więc nie tylko na STM32.

Chodzi o to, aby w mikrokontrolerze zastąpić standardowe wejście i wyjście. Nie mamy w naszych układach ani ekranu z konsolą, ani klawiatury. Jednak to nie oznacza, że nie możemy z nich skorzystać.

Semihosting pozwala na użycie zasobów naszego komputera jako standardowe wejście i wyjście dla mikrokontrolera. Jakie to zasoby? Ano konsola i klawiatura.

Wszystko dzieje się za sprawą specjalnych instrukcji w mikrokontrolerze, które wywołują wyjątki systemowe (np. instrukcja SVC – SuperVisor Call). Wyjątek taki przechwytywany jest przez odpowiednie funkcje i sprzętowy debugger. Ten potrafi teraz przekierować dane z mikrokontrolera wprost do naszego komputera i odwrotnie.

Po stronie PC odbiera to oprogramowanie, które uruchomiło debugowanie kodu na mikrokontrolerze. Udostępnia ono konsolę i klawiaturę do użycia właśnie przez ten “tunel”.

Potrzebne piny mikrokontrolera

Teraz najlepsze. Jakie piny mikrokontrolera są wykorzystywane do takiej komunikacji?

Dokładnie te same, co w przypadku “klasycznego” debugowania. Są to SWCLK i SWDIO. Nic więcej!

Nie musimy zmieniać konfiguracji sprzętowej. Ba! Nie musimy “marnować” interfejsu UART na to, aby printować coś na konsoli w celach debugowych.

Jest to ogromna zaleta Semihostingu. UART zjada 2 piny, a SWV jeden – SWO. Jeśli będziesz miał restrykcyjny projekt, w którym nie masz wolnych pinów, to masz już “interfejs” do printowania logów z działania programu.

Przejdźmy zatem do konfiguracji tego Semihostingu.

Platforma do testów

Jako płytki testowej użyłem zestawu Discovery B-U585I-IOT02A. Jest to płytka z najnowszym dzieckiem STMicroelectronics, czyli STM32U5. Niedawno pisałem na temat ich możliwości.

Aktualnie używam tej platformy na Live Streamach, które prowadzę regularnie we wtorki o 18:00 na moim YouTube.

Najważniejsze info! Ta metoda jest identyczna dla wszystkich mikrokontrolerów STM32 (i nie tylko). Jeśli masz inny układ to wszystko będzie wyglądało identycznie.

Konfiguracja Semihostingu na STM32

Przejdźmy do konkretów. Jak ustawić Semihosting na STM32? Jest kilka kroków.

1. Odpowiedni debuger programowy

Musisz wybrać odpowiedni debugger po stronie komputera. Będzie to OpenOCD.

Niestety domyślnie ustawiany ST-Link GDB nie obsługuje Semihostingu.

Konfigurację debugowania ustawiasz podczas pierwszego uruchomienia debugowania. Jeśli już to robiłeś, to pod robaczkiem masz Debug Configurations.

Teraz jako Debug Probe ustaw ST-Link (OpenOCD).

2. Załączenie zewnętrznej biblioteki przez Linker

Aby program wiedział jak posługiwać się, chociażby wyjątkami systemowymi w celu korzystania z Semihostingu, należy dołączyć zewnętrzną bibliotekę. Jest to biblioteka prekompilowana, więc robi się to dopiero na etapie linkera.

Jeśli wprowadzasz parametry ręcznie to do opcji linkera dodaj

-l rdimon --specs=rdimon.specs

Jeśli tak jak ja korzystasz z STM32CubeIDE to dodaj w odpowiednich opcjach linkera:

Project > Properties > C/C++ Build > Settings > MCU GCC Linker

W Libraries dopisujesz rdimon.

W Miscellaneous z kolei wpisz:

-specs=rdimon.specs

3. Wyłączenie syscall.c z kompilacji

STM32CubeMX generuje domyślny plik syscalls.c. Znajdują się w nim puste funkcje wywołań systemowych. Są one do naszej dyspozycji, gdybyśmy chcieli samemu napisać sobie taki np. semihosting lub coś podobnego.

Raczej nie będziemy robić tego samemu. Dodatkowo te same funkcje dołączane są z zewnątrz przez to, co podłączyliśmy do linkera.

Będzie zgrzyt. To znaczy kompilator może nam powiedzieć, że mamy jakieś podwójne definicje. Trzeba ten plik wyłączyć z kompilacji.

Można by go usunąć, ale… on wróci po ponownym wygenerowaniu plików przez CubeMX. Trzeba go wyłączyć całkowicie.

Prawy klik na ten plik > Properties > zaznaczamy ptaszek “Exclude resource from build”

4. Inicjalizacja w programie na mikrokontrolerze

Mamy już skonfigurowane wszystko po stronie mikrokontrolera. Teraz zostało w naszym programie wywołać funkcję inicjującą Semihosting. Podobnie jak inicjujemy każdy interfejs, zanim go użyjemy.

Służy do tego funkcja:

initialise_monitor_handles();

Wystarczy dodać ją w funkcji main przed pętlą główną. Możemy to zrobić jeszcze przed inicjalizacją HALa. Wtedy będziemy mogli już coś wysyłać na konsolę jeszcze zanim wstanie cały HAL.

Aby kompilator nie krzyczał, że jej nie zna musisz dorzucić jej prototyp z zaznaczeniem, że jest extern (w bibliotece rdimon) gdzieś u góry pliku.

extern void initialise_monitor_handles(void);

5. Włączenie semihostingu przy starcie debugowania

Po stronie mikrokontrolera mamy wszystko. Dokończmy stronę PCta.

Tutaj podobnie jak na STM32 trzeba zainicjować Semihosting. Robi się to w momencie startu debugowania, czyli podczas uruchamiania sesji OpenOCD. Trzeba mu podać komendę, aby wiedział, że semihostujemy.

Musisz ponownie wejść do ustawień sesji debugowania Twojego projektu. Tym razem to, co nas interesuje jest w zakładce Startup. Jest tak pole “Initialization Commands”. Te komendy wywołają się podczas stawiania sesji debugowej.

Wpisz tutaj:

monitor arm semihosting enable

Masz już wszystko, co jest potrzebne do użycia Semihostingu!

Jak używać Semihostingu?

Mamy za sobą konfigurację, więc jak skorzystać z tego mechanizmu?

Jeśli nie masz, to musisz dołączyć do projektu plik <stdio.h>.

Jeśli zrobiłeś wszystko tak, jak podałem to teraz po prostu używasz funkcji printf

Jest tylko jedna ważna zasada. Każdy komunikat wysyłany przez Semihosting musi się kończyć znakiem ‘\n’.

Tak jakbyś np. na PC printował na konsolę, tak samo teraz printujesz z mikrokontrolera. Gdzie trafią te napisy? Na konsolę, z której uruchomiony był OpenOCD. Jeśli robiłeś to w STM32CubeIDE to jest ta konsola na dole.

Przykład:

int main(void)
{
  /* USER CODE BEGIN 1 */
	initialise_monitor_handles();

	printf("Semihosting test\n");
  /* USER CODE END 1 */

Jak widzisz wrzuciłem kod od Semihostingu od razu po wejściu do funkcji main i od razu chcę coś wyprintować. Jaki będzie efekt?

Działa. Mój testowy napis pojawił się na konsoli.

Zwróć uwagę na to, że wśród czerwonych komunikatów z OpenOCD dostaliśmy “semihosting is enabled”. Oznacza to, że wszystko gra.

Mówiłem też, że możemy skorzystać z naszej klawiatury w PC, prawda?

Funkcja scanf(…) czyta standardowe wejście, czyli to, co wpiszemy na konsolę. Jest to funkcja blokująca i czeka na Enter podany z klawiatury.

Dopisując do programu takie linijki:

int main(void)
{
  /* USER CODE BEGIN 1 */
	int32_t Value;

	initialise_monitor_handles();

	printf("Semihosting test\n");

	printf("Type a integer: \n");
	scanf("%ld", &Value);
	printf("You typed %ld\n", Value);

  /* USER CODE END 1 */

Otrzymujemy flow programu wymagający interakcji od użytkownika. Program stoi i oczekuje aż podasz mu na konsoli liczbę całkowitą. Nie zapominaj o Enterze! Wprowadzany przez nas tekst z klawiatury ma kolor zielonkawo turksowy.

Operacje na plikach

Tą drogą możemy nie tylko korzystać z konsoli, ale również z plików na naszym komputerze!

Służą do tego funkcje:

  • fopen() – otwiera plik
  • fprintf() – wpisuje do pliku
  • fscanf() – czyta z pliku
  • fclose() – zamyka plik

Tych funkcji w pliku stdio.h jest więcej, ale te są najważniejsze.

Ścieżkę do pliku możesz podać względnie – wtedy dotyczy to miejsca, gdzie program jest uruchomiony.

Możesz też podać bezwzględnie. Posługujesz się ścieżkami z Twojego komputera. Tylko nie podawaj dysku C, bo odbijesz się od uprawnień administratora i MCU wskoczy w Hard Fault 🙂

Przykład:

int main(void)
{
  /* USER CODE BEGIN 1 */
	FILE *FilePtr;

	initialise_monitor_handles();

	FilePtr = fopen("d:\\semi\\test.txt", "w");

	fprintf(FilePtr, "Test semihosting");

	fclose(FilePtr);
  /* USER CODE END 1 */

Program ma za zadanie otworzyć plik (stworzyć go jeśli nie ma), wpisać tekst i zamknąć. Zawsze pamiętaj o zamykaniu plików po ich użyciu!

Puszczając taki program w ścieżce, którą podałem dostałem nowy plik 🙂

W środku oczywiście było to, co wpisałem w programie na mikrokontrolerze.

Widzę tutaj potencjał w “drugą stronę”, czyli z pliku na PC do mikrokontrolera.

Można napisać jakiś algorytm na mikrokontrolerze, a dane do testowania wstrzykiwać z pliku na komputerze! To może mieć ogromne zastosowanie.

Podsumowanie

Semihosting jest bardzo ciekawą alternatywą dla debugowania przez printowanie. Pozwala nam zastąpić  UART. Dużo łatwiej pozwala na implementację np. podłączenia klawiatury czy zasysania danych z pliku na komputerze.

Nie wspomniałem nic o wadach, a myślę, że ma jedną istotną. To rozwiązanie jest bardzo wolne. Spróbuj uruchomić printowanie w kółko bez żadnego delaya to zobaczysz, że nie ma takiego szturmu znaków jak np. przy UART.

Z tego względu Semihosting nie nada się tam, gdzie wymagana jest spora prędkość przesyłanych logów. Jednak to są będzie specyficzne zastosowania. Nie ma też co demonizować tej prędkości. Do nauki, czy prostego projektu może okazać się, że taka prędkość jest wystarczająca.

Możesz również wprowadzić poziom logowania i np. wysyłać tylko ważniejsze komunikaty lub tylko te, które aktualnie potrzebujesz.

Z zalet wymieniłbym na pewno minimalną liczbę pinów potrzebnych do pracy. Można powiedzieć, że zero, bo i tak debugger zawsze masz podłączony.

Kurs STM32 dla Początkujących

Już 16 lutego wraca najlepszy kurs programowania STM32 dla Początkujących! To już czwarta edycja!

Jest to kompletny program od A do Z, w którym nauczysz się programowania mikrokontrolerów STM32. Poznasz jego interfejsy i będziesz umieć z nich skorzystać w sposób prawidłowy i nieblokujący.

Nie przegap szansy! Następna edycja będzie prawdopodobnie dopiero w drugiej połowie 2022 roku.

Dotychczas w kursie wzięło udział ponad 470 osób!

Zapisz się na listę oczekujących na https://kursstm32.pl/

5/5 - (3 votes)

Podobne artykuły

.

0 komentarzy

Dodaj komentarz

Avatar placeholder

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