W oknie właściwości (Properties) klikamy na RTOS being used i z rozwijanej listy wybieramy ThreadX, tak jak to zostało pokazane na rysunku 2. Teraz, kiedy konfigurator już „wie”, że ma konfigurować projekt do pracy z ThreadX, można dodawać wątki zadania do wykonania. Każdy wątek to funkcja zawierająca pętlę nieskończoną while(1) {}. Funkcje wątków mogą zależnie od systemu RTOS mieć jakieś argumenty. W konfiguratorze e2studio wątki definiuje się bardzo prosto. Otwieramy zakładkę Threads i w oknie Threads klikamy na ikonkę dodawania (z zielonym plusem). Po dodaniu wątku w oknie właściwości zmieniamy jego nazwę adekwatnie do wykonywanego zadania. Ja zmieniłem nazwę na LED Thread, ponieważ wątek będzie miał za zadanie sterowanie diodą LED. Zmieniłem też nazwę symbolu na led_thread. Ta nazwa pojawi się potem w kodzie i warto również powiązać ją z wykonywanym zadaniem.
Każde naciśnięcie SW1 ma powodować zgłoszenie przerwania. Każde przerwanie trzeba skonfigurować i obsłużyć przez napisanie procedury obsługi. Konfigurację przerwania, a przerwania zewnętrznego w szczególności można wykonać za pomocą konfiguratora. Najpierw dodajemy do wątku moduł drivera obsługującego przerwanie zewnętrzne, jak na rysunku 6.
- Priorytet 2.
- Kanał 6 (IRQ6).
- Wyzwalanie opadającym zboczem.
- Włączenie cyfrowego filtra drgań styku.
- Nazwa procedury obsługi external_irq6_callback – włączenie mechanizmu callback.
Parametry konfiguracji właściwości zostały pokazane na rysunku 7. Jeżeli w zakładce Callback okna Properties drivera IRQ zamiast opcji NULL wpiszemy jakąś swoją nazwę, to konfigurator zdefiniuje prototyp funkcji o tej nazwie wywoływanej w momencie zgłoszenia przerwania. Argumentem tej funkcji jest wskaźnik na strukturę zawierającą między innymi informacje o zdarzeniach dotyczących zmiany stanów na linii P301. Użytkownikowi pozostaje tylko napisać tę swoją funkcję, umieścić ją w programie źródłowym i testować tam zdarzenie przyciśnięcia SW1. Ta funkcja musi być formalnie zdefiniowana zgodnie z wymaganiami biblioteki SSP, tak jak to zostało pokazane na listingu 1. Nazwa procedury: irq6_callbacki, została nadana w oknie Callback zakładki properties drivera przerwania IRQ6 (rys. 7).
Jak pamiętamy, nasz program ma cyklicznie zapalać i gasić diodę LED po każdym naciśnięciu przycisku SW1. Do tego celu wykorzystamy zdefiniowany już mechanizm zgłaszania przerwania od zmiany stanu SW1 oraz semafor. Semafor dodajemy z poziomu konfiguratora, jak pokazano na rysunku 8. W oknie właściwości nadajemy swoją nazwę semafora – ja nazwałem go sw1_semaphore. Teraz projekt jest skonfigurowany i po kliknięciu na Generate Project Content zostaną wygenerowane odpowiednie pliki. W katalogu src zostały umieszczone pliki źródłowe hal_enty.c i led_thread_entry.c przeznaczone do edytowania przez użytkownika (rysunek 9). Oczywiście, konfigurator dodaje również pliki jądra RTOS, ale nimi nie będziemy się zajmować.
Działanie programu jest bardzo proste. O stanie diody LED (zapalona lub zgaszona, decyduje wartość wpisana do zmiennej level (zainicjowana na wartość 1). Funkcja biblioteki warstwy HAL g_ioport.p_api –> pinWrite zmienia stan linii portu w zależności od wartości zmiennej level. Potem zmienna level zmienia swój stan na przeciwny i program jest zatrzymywany na semaforze sw1_semaphore do czasu jego zwolnienia. Zwolnienie semafora jest wykonywane w procedurze przerwania zewnętrznego IRQ6 zgłaszanego po naciśnięciu przycisku SW1. W pętli nieskończonej ponownie jest wpisywana wartość zmiennej level do rejestrów portu P113 i stan diody LED zmienia się na przeciwny. Potem program zatrzymuje się na semaforze i cały cykl jest wykonywany ponownie. Pozostaje teraz skompilowanie projektu, zapisanie kodu wynikowego do pamięci Flash mikrokontrolera i sprowadzenie poprawności działania.
Tomasz Jabłoński, EP
Uwaga: pełny tekst artykułu oraz rysunki są dostępne w pliku PDF.