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.
Kategoria: Programowanie
FPU w STM32F4 – jak używać Floating Point Unit
Jedną z największych zalet procesorów STM32F4 i ogólnie Cortex-M4 jest jednostka Floating Point Unit (FPU) przyspieszająca obliczenia na liczbach zmiennoprzecinkowych. Jej wykorzystanie wymaga od użytkownika włączenia FPU podczas działania programu oraz kompilacji z odpowiednimi flagami, aby używać instrukcji FPU. W tym wpisie omawiam jak obsługiwać FPU zarówno od strony programu jak i kompilatora oraz jak pisać kod, aby mieć pewność, że wykorzystuje on dobrodziejstwa FPU.
Watchdog w środowisku wielowątkowym
W poprzednim artykule omówiłem działanie watchdoga i zastosowanie w prostych aplikacjach zawierających całą obsługę w pętli głównej. Dzisiaj zajmiemy się częściej spotykanym, ale i trudniejszym, problemem – implementacją watchdoga w aplikacjach wielowątkowych.
Watchdog timer
Każdy, kto miał do czynienia z elektroniką wie, że jeśli urządzenie przestało działać, należy je zresetować. W niektórych systemach robienie tego ręcznie nie jest możliwe. Przyczyną może być trudny, czy wręcz niemożliwy, dostęp dla operatora np. w przypadku sondy kosmicznej. Są też przypadki, gdy czas potrzebny na zauważenie usterki i ręczny reset jest zbyt długi np. w przypadku aparatury medycznej podtrzymującej życie. W takich sytuacjach z pomocą przychodzi nam watchdog timer.
Exceptiony w mikrokontrolerach
Kiedy w programie na PC nastąpi exception, aplikacja zakończy się z błędem. W skrajnym przypadku dostaniemy blue screena i komputer się zresetuje. Wyjątki są obsługiwane przez system operacyjny. W mikrokontrolerach nie mamy dostępu do takich zaawansowanych funkcjonalności. Jednak w dalszym ciągu możemy wykonać dzielenie przez 0 lub odwołać się do null pointera. W tym artykule omówię w jaki sposób obsługiwać exceptiony w mikrokontrolerach. Zacznę od ogólnej procedury, następnie skupię się na detalach specyficznych dla procesorów PIC32 i Cortex-M.
O wskaźnikach i rzutowaniu w C
Zmienne programu są w pamięci reprezentowane jako pewien ciąg bitów. Dla komputera nie ma znaczenia, czy ten ciąg to liczba, string, struktura, czy cokolwiek innego. Pisząc programy definiujemy typy zmiennych i to na te typy rzutowane są wartości bitowe.
Języki wyższego poziomu jak np. C#, czy Python oddzielają tą implementację za pewną warstwą abstrakcji. Twórcy tych języków doszli do wniosku, że program nie powinien polegać na konkretnej reprezentacji bitowej. Możemy oczywiście za pomocą odpowiednich funkcji uzyskać dostęp do takiej bitowej reprezentacji, ale czynność ta celowo została utrudniona.
C jest jednak starszym językiem wyznającym zasadę, że programista wie co robi. Dlatego w C mamy łatwy dostęp do reprezentacji bitowej. Możemy używać wskaźników, czy rzutować typy na inne. Efektem jest większa wydajność wynikowych programów za cenę wolniejszego developmentu. Sprawdzanie błędów w C jest bardzo ubogie i nawet doświadczony programista może łatwo strzelić sobie w stopę.
W tym wpisie pokażę kilka potencjalnie niebezpiecznych fragmentów kodu oraz omówię jak radzi sobie z nimi standard MISRA C oraz jak to rozwiązano w C++.
Konwersja typów przy operacjach arytmetycznych w C
Aby wykonać operację arytmetyczną w C, kompilator musi dysponować dwoma operandami tego samego typu. Jeżeli programista o to wcześniej nie zadbał, konwersja jest wykonywana niejawnie. Na przykład:
- Zmienna o mniejszym rozmiarze jest konwertowana do większego np. uint8 na uint32, czy float na double.
- Zmienna bez znaku jest konwertowana na zmienną ze znakiem.
- Zmienna int jest konwertowana na float.
Konwersje typów są również wykonywane przy operacjach przypisania. Możemy na przykład do zmiennej uint przypisać liczbę ujemną. Możemy również do niej przypisać wynik operacji arytmetycznej, gdzie czasem wartość jest dodatnia, a czasem ujemna. Takie konwersje są dobrym miejscem do powstawania różnego rodzaju błędów i nieoczywistych, czy wręcz niezdefiniowanych zachowań.
Systemy bezpieczeństwa – sposoby przeciwdziałania błędom
W poprzednim artykule opisałem trochę podstawowych informacji dotyczących systemów bezpieczeństwa. Skupiłem się tam na podstawowych pojęciach i procesach. Dzisiaj mam zamiar omówić kilka aspektów technicznych. Będzie więc o tym jak takie systemy zachowują się w przypadku wykrycia błędu i jak minimalizują efekty ich wystąpienia.
Kiedy od softu zależy ludzkie życie – o systemach bezpieczeństwa
W internecie można spotkać głosy, że programiści nie wykonują odpowiedzialnych zadań i nie ma żadnych regulacji, których muszą przestrzegać. Bo co złego może się stać, jeśli strona nie będzie działać, albo komputer wywali bluescreena. W końcu świat się od tego nie zawali. Być może jest to prawdą w 99% projektów programistycznych. Jednak tam, gdzie na szali jest ludzkie życie, bardzo restrykcyjne regulacje obowiązują już od dawna. Wiem o czym mówię, ponieważ przez ostatnie dwa lata pracowałem przy systemie sterującym ruchem pociągów.
Jak optymalizować działanie programu?
Ostatnio w pracy miałem za zadanie dokonać optymalizacji pewnego fragmentu kodu. Postanowiłem, że to dobra okazja, aby zebrać trochę porad dotyczących optymalizacji i się nimi podzielić. Część porad odnosi się konkretnie do C, ale większość można uogólnić na każdy język. Entuzjaści wyciskania procesorów do granic możliwości mogą jednak poczuć się zawiedzeni, ponieważ nie będę się skupiał na trickach urywających pojedyncze takty. Bliżej mi do podejścia przedstawionego w dwóch zasadach optymalizacji:
- Nie rób tego.
- (Tylko dla ekspertów) Jeszcze tego nie rób.