Przydatne biblioteki C++ STM32

C++ w systemach embedded otwiera całą gamę nowych możliwości. Poprawne użycie nowoczesnych konstrukcji języka i biblioteki standardowej pozwala ułatwić i przyspieszyć naszą pracę. Niestety większość popularnych bibliotek C++ nie jest tworzona z myślą o systemach embedded. Czasami taka biblioteka mimo wszystko u nas zadziała, jednak nie zawsze mamy tyle szczęścia. Nawet wykorzystanie dużej części STL może być problematyczne ze względu na dynamiczną alokację pamięci. Istnieją jednak biblioteki stworzone właśnie z myślą o mikrokontrolerach. W tym wpisie przybliżę kilka z nich, szczególnie pod kątem użycia w STM32.

Dlaczego warto pisać w C++

Zanim przejdę do opisu konkretnych bibliotek, odpowiem na pytanie po co w ogóle przesiadać się z czystego C. C++, a szczególnie jego nowe standardy, ma kilka istotnych zalet:

  • Redukcja duplikacji dzięki klasom i templatom.
  • Możliwość uniknięcia typowych błędów ze wskaźnikami dzięki referencjom i smart pointerom.
  • RAII ułatwia kontrolę czasu życia zasobów.
  • Dokładniejsze sprawdzanie typów i niejawnych rzutowań.
  • Rozbudowana biblioteka standardowa zawierająca implementacje struktur danych i algorytmów.

Dzięki tym funkcjom można po prostu tworzyć lepszy kod. Co więcej nie musi się to wcale wiązać ze spadkiem wydajności końcowej aplikacji.

Jak pokazują badania – C od wielu lat niepodzielnie króluje jako główny język systemów embedded. Jednak będzie się to powoli zmieniać. Mikrokontrolery mają coraz więcej RAM i FLASH. Programy muszą realizować coraz bardziej skomplikowane zadania. Dlatego bardziej zaawansowane języki jak C++ to przyszłość branży. Społeczności związane z C++, ale i innymi językami jak np. Rust, czy Go wykonują niesamowitą pracę w celu ich popularyzacji w systemach embedded.

Ograniczenia C++ w embedded

Decydując się na użycie C++ w embedded, musimy zdawać sobie sprawę, czego nie powinniśmy robić. Głównym ograniczeniem jest wykorzystanie heapa – a więc operatory new/delete, ewentualnie malloc/free. W embedded najlepiej, jakbyśmy w ogóle go nie używali. Korzystanie z dynamicznej alokacji pamięci jest niedeterministyczne, powoduje fragmentację i do efektywnego działania wymaga wykorzystania dużo większego obszaru pamięci niż jest rzeczywiście potrzebny. Więcej o problemach z heapem można przeczytać w tym artykule. Inne problemy niespotykane w tradycyjnych aplikacjach to brak wsparcia systemu operacyjnego, czy brak obsługi wyjątków.

To tyle tytułem wstępu, pora przejść do właściwej części, czyli bibliotek C++ na STM32.

Biblioteki do obsługi peryferiów

Headery pisane w C zawierające definicje wszystkich rejestrów procesora oraz ich pól bitowych są nieodłącznym elementem każdej biblioteki dla mikrokontrolerów. Jej użycie skutkuje powstaniem charakterystycznego kodu pełnego dziwnych symboli nie mających sensu jeżeli na bieżąco nie sprawdzamy wszystkiego z datasheetem. C++ oferuje tutaj obiecującą alternatywę. Można użyć biblioteki, która wychwyci podczas kompilacji wpisanie wartości na nieodpowiednim bicie, czy użycie stałej związanej z innym rejestrem. Jest kilka dostępnych bibliotek tego typu.

Kvasir

Ta biblioteka najbardziej przypadła mi do gustu. Wygląda na dosyć prostą w użyciu i mamy od razu wszystko, czego potrzebujemy łącznie z gotowymi headerami dla wielu modeli procesorów różnych rodzin i producentów. Biblioteka oparta jest na templatach, a poszczególne headery mogą być generowane z plików konfiguracyjnych. Jest napisana w standardzie C++11. Autorem Kvasir jest Odin Holmes, którego można było zobaczyć na Codedive i 4Developers. Jeżeli wystartuję z jakimś nowym projektem to będzie prawdopodobnie mój wybór nr 1.

Modm

Poczytałem sobie trochę o tej bibliotece i niesamowicie mi się spodobała. Podobnie jak poprzednio mamy templaty opakowujące rejestry i dodające static asserty. Biblioteki są generowane na podstawie plików konfiguracyjnych ściąganych ze stron producentów. Na przykład STM32 ściąga bibliotekę Cube MX i z javowych binarek wyciąga informacje o poszczególnych pinach i peryferiach. Dzięki temu ma nawet takie informacje jak możliwe alternatywne funkcje każdego pinu, czy do których kanałów DMA można podłączyć dane peryferia. Niestety kiedy ją ściągnąłem i się pobawiłem, okazało się, że nie jest tak różowo. Mamy skrypty do automatycznej generacji, ale działają tylko na Linuxie i MacOs. Brak wsparcia dla Windowsa. Próbowałem nawet trochę się pobawić i uruchomić ten proces. Nawet sporą część konfiguracji udało mi się przejść, ale ostatecznie poległem. Biblioteka wykorzystuje C++17, co może być minusem jeśli w swoich projektach używamy starszego standardu.

Xpcc

Starszy brat Modm. Działa z C++14 i wykorzystuje w dużej części te same toole do generacji. Wygenerowanie biblioteki na Windowsie prawdopodobnie także będzie dużym wyzwaniem. Nie ma też nigdzie dostępnego outputu z wygenerowanymi headerami.

libstm32pp

Ta biblioteka jest dużo mniej rozbudowana niż poprzednie. Została napisana pod C++11. Poza mechanizmem do wpisywania wartości do rejestrów posiada gotowe funkcje typu GPIOpin::setMode. W przeciwieństwie do poprzednich, biblioteka nie jest generowana na podstawie żadnej konfiguracji. Wszystko prawdopodobnie było dodane przez autora ręcznie. Na githubie można znaleźć kilka podobnych projektów np. stm32plus, czy stm32tpl.

Inne biblioteki

ETLCPP

Jest to biblioteka zastępująca STL i posiadająca implementacje popularnych struktur i algorytmów z biblioteki standardowej, które nie wykorzystują heapa. Została ona stworzona specjalnie z myślą o Embedded. Mamy więc vector, array,  set, iteratory itp. Dokumentacja jest dostępna na stronie projektu. Biblioteka wykorzystuje standard C++03. Jeżeli ruszę z nowym projektem, na pewno będę chciał ją wypróbować.

type_safe

Biblioteka wyłapująca niejawne konwersje między podstawowymi typami np. między intami signed i unsigned. Dodatkowo umożliwia tworzenie własnych typów, dla których można definiować dozwolone operacje. Dokładniejszy opis jest dostępny na stronie autora. Biblioteka na pewno jest przydatna do systemów safety-critical, gdzie staramy się unikać wszelkich niejawnych konwersji.

NamedType

Podobna biblioteka do poprzedniej – też umożliwia wykrywanie podczas kompilacji błędów konwersji między typami. Jednak jej głównym zadaniem jest tworzenie jawnych typów takich jak np. wysokość, czy długość. Dzięki temu możemy uniknąć błedów choćby przy przekazywaniu parametrów do funkcji – zamiast wielu argumentów typu int możemy je nazwać na przykład width, height.

debug_assert

Biblioteka do obsługi assertów lepsza niż standardowe assert.h. Mamy tu kilka dodatkowych opcji takich jak poziomy asercji, czy moduły. Dzięki temu możemy włączać/wyłączać asserty dla interesujących nas części kodu.

Systemy operacyjne

Distortos

RTOS napisany w C++11, który wygląda bardzo ciekawie. Został napisany głównie z myślą o STM32 i zawiera wszystkie potrzebne funkcjonalności takie jak priorytety tasków, mutexy, semafory czy kolejki. Autorem jest FreddieChopin, który na swojej stronie ma dużo innych ciekawych narzędzi takich jak skompilowane pod windowsa wersje debuggera OpenOCD, czy bleeding-edge-toolchain. Distortos również ląduje na mojej liście do użycia w kolejnym projekcie.

QP State Machines

Na koniec taka ciekawostka – framework na systemy embedded oparty o maszyny stanu. Umożliwia on pisanie softu korzystając z reactive programming. Workflow wygląda tak, że najpierw opisujemy nasz system za pomocą diagramów UML z maszynami stanu, a następnie generujemy z tego kod.

 

Podobne wpisy

  • Ile kosztuje system safety-critical?

    Systemy safety-critical – wszystkie wpisy Ile kosztuje system safety-critical? SOUP – Wykorzystanie zewnętrznego softu w safety-critical Analiza ryzyka w systemach safety-critical Języki programowania w safety-critical Techniki zalecane przy tworzeniu systemów safety-critical Poziomy bezpieczeństwa w systemach safety-critical V-model – proces wytwarzania systemów safety-critical Ariane 5 – int overflow, który wysadził w powietrze rakietę Therac-25, czyli błąd…

  • Zabawy z folią aluminiową

    Po zlutowaniu nowego PCB, zgodnie z planem opisanym poprzednio, przystąpiłem do strojenia regulatorów silników. O ile z ruchem postępowym poszło szybko – w końcu robiłem to już któryś raz – tak z ruchem obrotowym natrafiłem na kolejne problemy. Jako sprzężenie zwrotne dla regulatora używam żyroskopu i okazało się, że odczyty są mocno zaszumione. Zakłócenia są…

  • Pomodoro Technique

    Zarówno w pracy, jak i w życiu codziennym zarządzanie czasem jest bardzo ważne. Szczególnie siedząc przed komputerem jesteśmy wystawieni na działanie wielu rozpraszaczy. Z drugiej strony człowiek może utrzymać maksymalną koncentrację tylko przez krótki czas. W ciągu dnia pracy możemy się zmusić do utrzymania koncentracji nawet przez kilka godzin, ale umysł nie pracuje wtedy tak…

  • Projekt jak wyścig kolarski

    W dobie Agile projekty informatyczne są często traktowane jako wiele następujących zaraz po sobie sprintów. Można się spotkać z głosami, że taki projekt to raczej maraton, gdzie powinniśmy się skupiać na celu w dłuższej perspektywie. Jednak indywidualny bieg nie oddaje dobrze wielu niuansów związanych z współpracą w zespole, dużo lepszym porównaniem jest wyścig kolarski.

  • Zmiany na blogu

    W ostatnim czasie blog przechodzi zmiany. Duża część z nich nie rzuca się w oczy. Między innymi poprawiłem bezpieczeństwo, przyspieszyłem wczytywanie strony, zainstalowałem nowe pluginy, zacząłem ułatwiać dostęp do najważniejszych wpisów, a nawet zwiększyłem aktywność na fejsie. We wpisie pada trochę nazw pluginów do WordPressa, więc jeżeli też prowadzisz własnego bloga, mogą Ci się również…

5 komentarzy

  1. Dzięki za wzmiankę o distortos, choć trochę szkoda, że dopiero na przedostatnim miejscu <:

    Jeśli użyjesz go w jakimś projekcie, to koniecznie daj znać. W projekcie obecnie bardzo sporo się zmienia, miejmy nadzieję że na lepsze, choć chwilowo są to głównie zmiany dotyczące magicznych generatorów kodu. Na udoskonalanie samych mechanizmów RTOSa (a lista potrzebnych zmian którą sobie zapisałem jest naprawdę długa) wciąż brak czasu…

  2. Cześć, mam prośbę. Czy byłbyś wstanie pokazać przykładowy kod, dajmy na to blinka z wykorzystaniem Kvasir? Kompletnie nie widzę nawet namiastki dokumentacji.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *