Strona główna Artykuły News distortos - 7 miesięcy i 0x3FF commitów!
distortos - 7 miesięcy i 0x3FF commitów!
Ocena użytkowników: / 2
SłabyŚwietny 
Wpisany przez Freddie Chopin   
Niedziela, 22 Luty 2015 20:52

Wspomniany w poprzednim newsie projekt distortos wciąż się rozwija. Dziś minęło dokładnie 7 miesięcy od pierwszego commita w repozytorium, a całkowita liczba tychże commitów osiągnęła sympatyczną wartość 1023. Wielu czytelników - przynajmniej tych którzy zorientowani są w RTOSach dla mikrokontrolerów - zastanawiać się będzie "po co komu kolejny projekt RTOSa?". Odpowiedź na to pytanie jest bardzo złożona i mógłbym na ten temat napisać osobny artykuł, jednak na razie musi wystarczyć link do pliku README, w którym starałem się opisać zasadnicze powody istnienia tego projektu. Myślę, że choćby z racji położenia dużego nacisku na wsparcie dla C++ i C++11 jest to projekt warty uwagi, choć cecha ta nie powinna umniejszać innych jego zalet (niektóre wciąż są oczywiście "przyszłe" (; ), ważnych dla osób które nie zamierzają używać C++ (ta cecha na pewno jest przyszła, na razie dostępne jest jedynie API w C++11).

Wciąż wiele pozostało do zrobienia, ale przez ten czas udało się zrealizować całkiem sporo rzeczy, które działają nadzwyczaj dobrze (;

Najważniejszą rzeczą są oczywiście wątki (klasy Thread, StaticThread oraz ThreadBase), które dzięki nowościom ze standardu C++11 mogą przyjmować dowolną ilość argumentów dowolnego typu, a nie tylko znane z innych RTOSów void* i nic poza tym. Co więcej - funkcja wątku może być klasyczną funkcją, funkcją z klasy ("member function"), funktorem albo lambdą.

Wszystkie powyższe cechy są również obecne w timerach programowych (klasa SoftwareTimer).

Scheduler obsługuje pełne wywłaszczanie wątków na podstawie priorytetów (których może być 256), natomiast jeśli istnieje kilka wątków o tym samym priorytecie, to będą one szeregowane według algorytmu FIFO lub round-robin (algorytm jest konfigurowalny dla każdego wątku indywidualnie).

Najbardziej bazowym obiektem synchronizacyjnym jest chyba semafor (klasa Semaphore). Możliwe jest skonfigurowanie maksymalnej wartości jaką "przyjąć" może semafor, dzięki czemu możliwe jest również używanie tego obiektu jak semafora binarnego. Semafor może być "sygnalizowany" z przerwania.

Bardziej zaawansowanym mechanizmem synchronizacji jest mutex (klasa Mutex). Tak jak w POSIXie, możliwe jest skonfigurowanie wszystkich trzech "trybów" - normalnego, "error-checking" oraz "recursive" - i wszystkich trzech "protokołów" - normalnego, "priority inheritance" oraz "priority protocol" (znanego również jako "priority ceiling"). W przeciwieństwie do wielu innych RTOSów, protokół "priority inheritance" działa bez żadnych ograniczeń: z dowolną ilością "poziomów" dziedziczenia, niezależnie od tego ile mutexów jest zablokowanych przez wątek i w jakiej kolejności (diagram i opis testu sprawdzającego tą właśnie cechę).

Mechanizmem bazującym na mutexach jest klasyczna "condition variable" (klasa ConditionVariable).

Do klasycznej komunikacji pomiędzy wątkami i przerwaniami (w dowolnej kombinacji) użyć można kolejek. Kolejki dostępne są w czterech wariantach:

Wiadomości dodawane do kolejki bez obsługi priorytetów (...FifoQueue) szeregowane są według algorytmu FIFO, natomiast kolejki obsługujące priorytety (...MessageQueue) umożliwiają dodawanie wiadomości o jednym z 256 priorytetów. Kolejki bez wsparcia dla obiektów (...Raw...) kopiują wiadomości przy pomocy funkcji memcpy(), natomiast kolejki wspierające obiekty obsługują wszystkie wymagane w takiej sytuacji operacje (konstruktor, destruktor, operatory przypisania, swap, emplace, ...).

Wszelkie operacje blokujące dostępne są też w wariantach nieblokujących oraz w wersji blokującej z timeoutem (względnym lub bezwzględnym), który dzięki wprowadzonemu w C++11 std::chrono może być wyrażany wygodnie w dowolnych jednostkach (np. w sekundach, minutach, godzinach, ... - link), a nie tylko w "tickach" systemowych.

Wszelkie błędy sygnalizowane są za pomocą kodów błędów - funkcje nie używają ani zmiennej errno, ani wyjątków C++.

Jedyną obsługiwaną obecnie architekturą jest ARMv7-M, czyli ARM Cortex-M3 (można użyć ARM Cortex-M4 bez uruchamiania FPU) (dodano 20.03.2015) i ARM Cortex-M4(F), a jedynym "oficjalnie" wspieranym układem jest STM32F407VG (znanym z płytki STM32F4Discovery), choć użycie dowolnego innego układu z odpowiednim rdzeniem będzie trywialne.

Na koniec chyba najlepsze - użycie wszystkich wymienionych powyżej funkcjonalności możliwe jest bez wykorzystania pamięci alokowanej dynamicznie. Wszystkie opisane wcześniej obiekty mogą zostać stworzone jako obiekty globalne lub jako obiekty na stosie.

Na pewno jeszcze kilka ciekawych rzeczy pominąłem...

Zachęcam do testów, pytań, komentarzy, sugestii i współpracy (; Stay tuned!

Zmieniony: Piątek, 20 Marzec 2015 09:47