Tworzenie projektu od zera – opcja “Start from Board”
W tej części utworzymy projekt w trybie „Start from Board”, czyli z wykorzystaniem predefiniowanej konfiguracji dla konkretnej płytki ewaluacyjnej. Sam proces tworzenia projektu przebiega podobnie jak w przypadku opcji „Start from MCU”, jednak różnice pojawiają się już na etapie wyboru celu w oknie Target Selector.
W poprzednim przykładzie skupiliśmy się na wyborze konkretnego mikrokontrolera. Tym razem zwrócimy uwagę na górną część selektora, w której dostępna jest zakładka umożliwiająca wybór gotowej płytki rozwojowej zamiast pojedynczego układu.

W górnej części okna Target Selector dostępne są dwie podstawowe zakładki: MCU/MPU Selector oraz Board Selector. W poprzednim przykładzie
korzystaliśmy z domyślnej opcji wyboru mikrokontrolera (MCU), co pozwalało rozpocząć projekt bezpośrednio od wybranego układu.
Tym razem przechodzimy do zakładki Board Selector, która umożliwia utworzenie projektu na podstawie gotowej płytki ewaluacyjnej. W polu
wyszukiwania można wpisać numer części (Part Number), na przykład NUCLEO-G474RE, a następnie wybrać odpowiednią pozycję z listy dostępnych
zestawów rozwojowych.


Nazywamy projekt tak jak chcemy i w opcjach pozostawiamy wartości domyślne.

Po wybraniu opcji Finish pojawi się dodatkowe okno konfiguracji, którego nie było w przypadku projektu tworzonego w trybie „Start from MCU”. Dotyczy ono wyboru komponentów Board Support Package (BSP) dla wybranej płytki ewaluacyjnej.
To właśnie w tym miejscu ujawnia się główna różnica pomiędzy obiema metodami tworzenia projektu. W trybie „Start from Board” środowisko proponuje wykorzystanie dodatkowych sterowników dedykowanych konkretnej płytce, obejmujących obsługę dostępnych na niej elementów, takich jak diody LED, przyciski użytkownika czy interfejs komunikacyjny. Wybrane komponenty BSP zostaną automatycznie dodane do struktury projektu wraz z odpowiednimi plikami źródłowymi i konfiguracją.

W tym przykładzie pozostawimy domyślne ustawienia wyboru BSP i przejdziemy dalej bez wprowadzania zmian. Po zatwierdzeniu konfiguracji i
wygenerowaniu kodu projekt zostanie utworzony wraz z dodatkowymi komponentami charakterystycznymi dla pracy „Start from Board”, a w konfiguratorze zobaczymy widok odpowiadający wstępnie przygotowanej konfiguracji dla wybranej płytki.

Jest inaczej, prawda? Co tutaj się stało?
Konfiguracja projektu różni się od tej, którą widzieliśmy w przypadku opcji „Start from MCU”. Zmiana ta wynika z faktu, że projekt został utworzony na
podstawie konkretnej płytki ewaluacyjnej, a nie wyłącznie samego mikrokontrolera.
W trybie „Start from Board” STM32CubeMX automatycznie uwzględnia elementy sprzętowe obecne na wybranej płytce i odpowiednio rezerwuje powiązane z nimi zasoby mikrokontrolera. Obejmuje to m.in. przypisanie określonych pinów, włączenie wybranych interfejsów oraz dodanie warstwy
BSP do projektu. Dzięki temu część konfiguracji jest przygotowana automatycznie, co wpływa zarówno na widok w konfiguratorze, jak i na strukturę wygenerowanego kodu.
Czym jest to tajemnicze BSP?
BSP (Board Support Package) w ekosystemie STM32 to warstwa oprogramowania, która „zna” konkretną płytkę, a nie tylko sam mikrokontroler. Zawiera gotowe sterowniki i konfiguracje dla elementów sprzętowych obecnych na danej płytce rozwojowej, takich jak diody LED, przyciski użytkownika, złącza czy dodatkowe układy na nakładkach X-NUCLEO. Dzięki temu nie musisz za każdym razem sprawdzać schematu, który pin steruje LED-em albo jak podłączony jest przycisk – dostajesz do dyspozycji proste, wysokopoziomowe funkcje.
Typowym przykładem są funkcje BSP_LED_Init , BSP_LED_On czy BSP_PB_Init , które zastępują ręczną konfigurację GPIO i logiki przycisków. Zamiast konfigurować rejestry lub pisać kod z użyciem HAL-a dla konkretnego portu i pinu, wywołujesz kilka funkcji BSP i od razu możesz korzystać z LED-a lub przycisku o nazwie „LED1”, „USER_BUTTON” itp.
W analogiczny sposób działają sterowniki BSP dla czujników i ekspanderów – udostępniają funkcje typu „odczytaj temperaturę” czy „skonfiguruj ekspander”, ukrywając szczegóły magistrali I2C lub SPI.
STMicroelectronics od dłuższego czasu do wszystkich swoich płytek tworzy BSP. Dzięki temu gdy będziesz chciał skorzystać z shieldu MEMS np. X-NUCLEO-IKS4A1, to w projekcie zostaniesz poproszony o wskazanie jedynie BSP do interfejsu I2C.
Można powiedzieć, że BSP to kolejna warstwa abstrakcji pomiędzy HAL, a aplikacją. BSP również dotyczy jednej, konkretnej płytki dla której jest dedykowane. Board Support Package jest dołączane jako kolejny zestaw bibliotek.

W jaki sposób pracuje się z projektem, w którym włączono BSP? Konfiguracja oraz struktura projektu różnią się od tej, którą widzieliśmy w przypadku opcji „Start from MCU”.
Pierwszą zauważalną zmianą jest widok w zakładce konfiguracji mikrokontrolera. Część pinów zostaje automatycznie przypisana do elementów obecnych na płytce ewaluacyjnej i odpowiednio oznaczona w interfejsie graficznym. Wynika to z faktu, że BSP rezerwuje określone zasoby mikrokontrolera, aby zapewnić poprawne działanie komponentów takich jak diody LED, przyciski czy interfejs komunikacyjny dostępny na płytce.

Piny oznaczone kolorem czerwonym to zasoby zarezerwowane przez warstwę BSP. Oznacza to, że są one przypisane do konkretnych elementów sprzętowych obecnych na płytce ewaluacyjnej i nie mogą zostać wykorzystane do innych funkcji bez wyłączenia odpowiedniego komponentu BSP.
Jednocześnie użytkownik ma możliwość decydowania, które elementy BSP mają pozostać aktywne w projekcie. W panelu konfiguracji, po lewej stronie interfejsu STM32CubeMX, pojawia się dodatkowa kategoria BSP, w której można włączać lub wyłączać poszczególne komponenty przypisane do płytki. Zmiany te są natychmiast odzwierciedlane w widoku pinów mikrokontrolera.

Spróbuj coś włączyć lub wyłączyć. Zobaczysz że piny na widoku MCU będą na to odpowiednio reagowały. Włączenie lub wyłączenie wybranego komponentu w sekcji BSP powoduje natychmiastową zmianę w widoku pinów mikrokontrolera. STM32CubeMX automatycznie rezerwuje lub zwalnia odpowiednie zasoby, dzięki czemu użytkownik może w przejrzysty sposób zobaczyć zależności pomiędzy elementami płytki a konfiguracją sprzętową.
Oprócz pinów oznaczonych kolorem czerwonym można zauważyć również piny w kolorze żółtym. Są to zasoby wstępnie przypisane do elementów obecnych na płytce ewaluacyjnej, takich jak zewnętrzne oscylatory HSE i LSE czy interfejs debugowy SWD, za pośrednictwem którego programator ST-LINK komunikuje się z mikrokontrolerem.
W przypadku płytki NUCLEO-G474RE liczba takich elementów nie jest duża, jednak wizualne oznaczenie ich w konfiguratorze stanowi istotną wskazówkę. Dopóki dane peryferium nie zostanie aktywowane w drzewie konfiguracji, przypisane do niego piny nie są w pełni wykorzystywane przez projekt. Oznaczenie to informuje użytkownika o fizycznych połączeniach na płytce i ułatwia planowanie dalszej konfiguracji.
Po zapoznaniu się z widokiem konfiguracji można wygenerować projekt w aktualnym stanie. Pamiętaj o ptaszku z rozdzieleniem plików peryferiów, aby zachować czytelną strukturę projektu.
Po wygenerowaniu kodu w strukturze projektu pojawią się dodatkowe pliki związane z BSP, a w kodzie inicjalizacyjnym będzie widoczna automatycznie dodana konfiguracja komponentów płytki.
Mając BSP możemy zaobserwować, że pojawiła się jego konfiguracja. No dobrze, a jak teraz pomigać diodą tak?

Gdyby w projekcie utworzonym z wykorzystaniem BSP spróbować użyć wcześniejszego kodu opartego bezpośrednio o HAL (np. HAL_GPIO_WritePin dla LD2_GPIO_Port i LD2_Pin ), nie uzyskalibyśmy oczekiwanego efektu. Wynika to z faktu, że w trybie „Start from Board” dioda na płytce jest inicjalizowana i zarządzana przez warstwę BSP, a konfiguracja GPIO może zostać zorganizowana inaczej niż w projekcie tworzonym „Start from MCU”.
W przypadku komponentów objętych BSP zalecanym podejściem jest korzystanie z udostępnionego przez tę warstwę interfejsu API. Sterowanie diodą realizuje się wtedy poprzez funkcje BSP (np. BSP_LED_On i BSP_LED_Off ), a miganie można zaimplementować w następujący sposób:

Różnica w sposobie pracy jest wyraźnie widoczna. W przypadku wykorzystania BSP szczegóły sprzętowe zostają ukryte za dodatkową warstwą
abstrakcji. W kodzie aplikacyjnym nie operujemy już bezpośrednio na konkretnym porcie i pinie mikrokontrolera ani nie musimy uwzględniać, czy dana dioda jest aktywna stanem wysokim czy niskim.
Warstwa BSP przejmuje odpowiedzialność za właściwą konfigurację i interpretację sygnałów, a aplikacja korzysta z uproszczonego interfejsu funkcji,
takich jak BSP_LED_On czy BSP_LED_Off . Z punktu widzenia kodu użytkownika sprowadza się to do wydania polecenia włączenia lub wyłączenia określonego komponentu płytki.
Analogiczne podejście dotyczy pozostałych elementów objętych BSP. Obsługa interfejsu komunikacyjnego (np. LPUART1 skonfigurowanego jako COM port) czy przycisku użytkownika realizowana jest poprzez dedykowane funkcje BSP, które w analogiczny sposób abstrahują od szczegółów konfiguracji sprzętowej mikrokontrolera.
Co przemawia za takim podejściem z użyciem BSP?
- Szybszy start na Nucleo/Discovery – masz od razu skonfigurowane LED-y, przyciski, czasem czujniki i ekspandery; możesz skupić się na logice aplikacji, a nie na przepinowywaniu GPIO z datasheetu.
- Gotowe, spójne API dla elementów na płytkach i nakładkach (X-NUCLEO) – funkcje typu BSP_LED_On , BSP_PB_GetState , API do sensorów itp., mniej klejenia kodu na I2C/SPI od zera.
- Mniejsza szansa na „głupie” błędy sprzętowe na starcie (złe piny, pomylone poziomy aktywne), bo sterowniki są przygotowane i przetestowane przez ST pod konkretny hardware.
- Lepsza produktywność przy prototypowaniu i proof-of-concept, szczególnie gdy ważne jest „żeby coś działało szybko”, a nie jeszcze architektura docelowego firmware’u.
Co przemawia przeciw BSP?
- Silna zależność od konkretnej płytki: przeniesienie kodu na inny hardware często oznacza wymianę wywołań BSP_* na własną warstwę lub goły HAL, co utrudnia portowanie.
- Dodatkowa warstwa abstrakcji zaciemnia obraz – początkujący widzi BSP_LED_On(LED1) i nie uczy się, który to port/pin, jak działa HAL i jak to skonfigurować ręcznie.
- Więcej „magicznego” kodu w projekcie: dodatkowe katalogi, pliki, generowane przykłady – łatwo zgubić rozdział między kodem użytkownika a kodem bibliotecznym i skończyć z chaotyczną architekturą.
- Potencjalne problemy przy aktualizacjach i regeneracji projektu – zmiany w BSP lub w generatorze mogą wprowadzać regresje, a ingerencja w pliki BSP utrudnia bezbolesne wygenerowanie kodu na nowo.
Jakie jest moje zalecenie?
Na co dzień pracuję z osobami, które dopiero wchodzą w świat STM32, dlatego często obserwuję, z jakimi trudnościami mierzą się na początku. Dla osób rozpoczynających naukę zazwyczaj rekomenduję pracę bez BSP – bezpośrednio z wykorzystaniem warstwy HAL.
Na etapie poznawania podstaw ważne jest zrozumienie, jak mikrokontroler konfiguruje piny, jak działa inicjalizacja peryferiów oraz jakie zależności występują pomiędzy zegarami a interfejsami. Warstwa BSP upraszcza wiele aspektów, ale jednocześnie ukrywa szczegóły, które na początku warto zobaczyć i świadomie przeanalizować.
Gdy opanujesz już podstawy pracy z STM32 i jego peryferiami, dodanie kolejnej warstwy abstrakcji staje się naturalnym krokiem. Wtedy BSP może znacząco przyspieszyć pracę – szczególnie w projektach wykorzystujących płytki ewaluacyjne i nakładki typu X-NUCLEO.
Pozostał nam ostatni sposób, który wykonamy na wersji STM32CubeIDE v.2.0.0. Zapraszam zatem do kolejnej części.
Mateusz Salamon
