ISIX-RTOS – przykład 2 – kolejki FIFO i obsługa graficznego wyświetlacza LCD
Opis systemu ISIX-RTOS i jego funkcji opublikowaliśmy w artykule „Mini system operacyjny dla STM32 – wprowadzenie”, który można przeczytać tu. |
W przykładzie pokażemy komunikację pomiędzy procesami z wykorzystaniem wątków. Działanie aplikacji będzie sprowadzać się do migania diody LED D1 z częstotliwością 2 Hz (jeden wątek) oraz wyświetleniu napisu lub grafik odpowiadających kierunkom joysticka zamontowanego na płytce STM32Butterfly w chwili wskazania go przez użytkownika. Wątki wymieniają pomiędzy sobą informacje.
Rys. 1. Sposób dołączenie wyświetlacza do mikrokontrolera STM32F107
W przykładzie zastosowano wyświetlacz LCD z telefonu Nokia 3310 zamontowany na module KAmodLCD1. Dołączono go do płytki STM32Butterfly za pomocą przewodów CAB_A w sposób pokazany na rys. 1. Dane do przesyłane przez sprzętowy interfejs SPI1, linie sterujące pracą wyświetlacza LCD dołączono bezpośrednio do innych linii GPIO mikrokontrolera. Zasadę działania aplikacji z uwzględnieniem podziału na wątki przedstawiono na rys. 2.
Rys. 2. Podział aplikacji na wątki
Cykliczne miganie LED jest realizowane przez wątek pracujący niezależnie od reszty aplikacji. Część odpowiedzialną za wyświetlanie komunikatów po wciśnięciu pozycji joysticka zrealizowano jako dwa oddzielne wątki: wątek serwera wyświetlania oraz wątek obsługi joysticka. Zadaniem wątku serwera wyświetlania jest odbiór rozkazów poprzez kolejkę FIFO z innych wątków zwanych dalej klientami serwera wyświetlania, ich interpretację i fizyczne sterowanie wyświetlacza LCD. Wątek obsługi joysticka z punktu widzenia serwera wyświetlania jest klientem. Jego zadaniem jest odczyt stanu styków joysticka oraz w wyniku interpretacji stanu styków joysticka, wysyłanie odpowiednich rozkazów dla serwera wyświetlania np. wypisania tekstu. Aplikacja została napisana w C++. Hierarchię klas projektu przedstawiono na rys. 3.
Rys. 3. Hierarchia klas przykładowego projektu
Obiekt the_application jest głównym obiektem, którego instancja statyczna tworzona jest w funkcji głównej main() – list. 1.
List. 1. Instancja statyczna obiektu the_application
//App main entry point int main() { //Application object static app::the_application application; //Start scheduler isix::isix_start_scheduler(); }
Klasa the_application zawiera klasy odpowiedzialne za realizację poszczególnych zadań. W klasie tej tworzone są pojedyncze instancje klas: led_blink, display_server, graph_key. Dzięki zawarciu aplikacji w oddzielnej klasie mamy możliwość utworzenia instancji klasy w dowolny sposób np. na stercie, na stosie, czy statycznie, bez konieczności zmiany pozostałych części.
Klasa ledblink odpowiedzialna jest za miganie diodą LED i jest dziedziczona z obiektu isix::task_base implementującej obsługę wątków. Implementacja klasy jest praktycznie identyczna jak w poprzednio omówionym przykładzie dotyczącym diod LED dlatego zostanie tutaj pozostawiona bez szerszego komentarza. Miganie diodami LED odbywa się niezależnie od pozostałej części aplikacji, więc klasa ta nie komunikuje się z innymi obiektami.
Klasa display_server odpowiedzialna jest bezpośrednio za odbiór komunikatów z kolejki FIFO oraz wyświetlaniu ich na wyświetlaczu. Klasa zawiera w sobie dwa obiekty isix::fifo oraz nokia_display. Obiekt isix::fifo tworzony jest poprzez specjalizację szablonu klasy wzorcowej isix:<const display_msg*>:fifo:
//The message queue isix::fifoio_fifo;
a zatem do kolejki FIFO możemy z innych zadań/wątków przekazywać wskaźniki do obiektów komunikatów. Klasa display_msg jest klasą bazową dla klas text_msg , oraz klasy graph_msg dzięki czemu, do kolejki FIFO możemy przekazywać zarówno wskaźniki do obiektów klas text_msg (komunikat tekstowy), jak i display_msg (komunikat graficzny). Klasa text_msg jest prostym wrapperem przechowującym wskaźnik do C-stringu const char*, natomiast klasa display_msg jest wrapperem przechowującym strukturę img_def (list. 2).
List. 2. Klasa display_msg pochodzi z biblioteki graficznej SPGL i jest wrapperem przechowującym strukturę img_def
//Images namespace namespace images { //Image definition from pure C a SPGL library. struct img_def { int width; int height; const unsigned char *data; }; }