ISIX-RTOS – przykład 1 – sterowanie LED w wątkach

 

Opis systemu ISIX-RTOS i jego funkcji opublikowaliśmy w artykule “Mini system operacyjny dla STM32 – wprowadzenie”, który można przeczytać tu.

Pokażemy w jaki sposób stworzyć kod startowy dla systemu oraz dwa nowe zadania (wątki). Prezentowany program umożliwia sterowanie diodami LED zamontowanymi w zestawie STM32Butterflyw następujący sposób: dioda LED1 miga cyklicznie, natomiast dioda LED2 jest włączana i wyłączana po wciśnięciu manipulatora joysticka. 

Start systemu zrealizowany jest w bibliotece lib-stm32, odpowiedzialnej za inicjalizację systemu zgodnie z wymogami ANSI C/C++. Przed wywołaniem globalnych konstruktorów obiektów wywoływana jest funkcja __external_startup() następnie funkcja główna main().
Kod funkcji __external_startup pokazano na list. 1.

List. 1. Kod funkcji __external_startup

Funkcja uc_periph_setup() jest odpowiedzialna za konfigurację kontrolera pamięci oraz ustawienie pętli PLL mikrokontrolera tak, aby rdzeń był taktowany z maksymalną dozwoloną częstotliwością (72 MHz). Następnie konfigurowany jest kontroler przerwań NVIC, w trybie jeden bit priorytetu przerwania oraz trzy bity podpriorytetu. Dodatkowo ustalono priorytet przerwań używanych przez system ISIX-RTOS (PENDSV, SVC, SYSTICK) na najniższy możliwy. Kolejna wywoływana funkcja isix_init jest odpowiedzialna za inicjalizacje systemu, jako argument przyjmuję ona liczbę priorytetów wykorzystywanych przez scheduler. Liczba dostępnych priorytetów jest dowolna (ograniczona wielkością dostępnej pamięci), w praktyce wystarcza najczęściej kilkanaście priorytetów. Następnie wywoływana jest funkcjatimer_setup(), która jest odpowiedzialna za konfigurację przerwania zegarowego SYSTICK, tak aby było ono generowane z częstotliwością ISIX_HZ. Wartość tej częstotliwości w przykładzie ustalono na 1000 Hz. Po wykonaniu funkcji startowej oraz wywołaniu konstruktorów globalnych, wykonywana jest funkcja główna main() (list. 2).

List. 2. Główna funkcja main()

Najpierw jest tworzony obiekt klasy ledblink, której zadaniem jest cykliczne miganie diodą LED1 (patrz dokumentacja zestawu STM32Butterfly), następnie obiekt klasy ledkey, której zadaniem jest cykliczna zmiana stanu diody LED2 w wyniku naciśnięcia manipulatora joysticka. Następnie jest wywoływana funkcja isix_start_scheduler(), która powoduje uruchomienie szeregowania zadań przez system ISIX-RTOS. Obie klasy (ledblink, ledkey) dziedziczą z klasy bazowej isix::task_base. Każda klasa dziedzicząca z klasy task_base musi implementować metodę wirtualną main(), która jest wykonywana w oddzielnym wątku tworzonym przez konstruktor klasy task_base. Implementację klasy blinker odpowiedzialnej za cykliczne miganie diodą LED1 przedstawiono na list. 3.

List. 3. Implementacja klasy blinker

W liście inicjalizacyjnej konstruktora wywoływany jest konstruktor klasy bazowej task_base(), który jest odpowiedzialny za tworzenie nowego zadania (wątku). Jako argumenty przyjmuje on rozmiar stosu zadania oraz jego priorytet. W konstruktorze jest także konfigurowany port GPIO PE.14, do którego w zestawie STM32Butterfly podłączono diodę LED1. Wątek realizowany jest w pętli nieskończonej metody wirtualnej main(). Wątek zmienia stan LED, a następnie wywołuje funkcję isix_wait(), której zadaniem jest uśpienie wątku na czas określony przez stałą BLINK_TIME.
Najistotniejsze fragmenty implementacji klasyledkey przedstawiono na list. 4.

List. 4. Fragmenty implementacji klasyledkey

Podobnie jak poprzednio w liście inicjalizacyjnej jest wywoływany konstruktor klasy bazowej oraz inicjalizowane są porty GPIO. Wątek odpowiedzialny za wspomniane wcześniej zadanie zrealizowany jest przez metodę wirtualną main() w pętli nieskończonej. Zmiana stanu diody LED2 następuje w momencie puszczenia manipulatora joysticka (zbocze narastające na wejściu mikrokontrolera). Detekcję zrealizowano w sposób klasyczny przez porównanie bieżącego stanu klawisza ze stanem poprzednim. W momencie, gdy wykryjemy zbocze jest zmieniany stan zmiennej is_enabled, następnie na podstawie stanu zmiennej dioda LED2 jest włączana lub wyłączana. Na koniec cyklu wywoływana jest funkcja isix_wait() z argumentem DELAY_TIME (25 ms), która usypia bieżący wątek na krótki czas, tak aby wyeliminować drgania zestyków.

Do pobrania

O autorze