ISIX-RTOS v3 - System operacyjny dla mikrokontrolerów rodziny Cortex-M (2). Konfigurowanie środowiska, pierwszy projekt

ISIX-RTOS v3 - System operacyjny dla mikrokontrolerów rodziny Cortex-M (2). Konfigurowanie środowiska, pierwszy projekt

Jedynymi elementami potrzebnymi do pracy z systemem ISIX jest kompilator gcc dla architektury ARM oraz interpreter języka Python3. W najprostszym przypadku do pracy z kodem źródłowym wystarczy dowolny edytor tekstu np. Notepad++ lub VIM. W obecnych czasach większość użytkowników przyzwyczajona jest do pracy ze środowiskami IDE, w związku z powyższym w niniejszym artykule przedstawimy opis, jak skonfigurować kompletne środowisko z wykorzystaniem lekkiego IDE „Visual Studio Code” firmy Microsoft, dla uproszczenia nazwanym dalej VSCode.

Oprogramowanie VSCode jest otwartoźródłowym, wieloplatformowym lekkim i konfigurowalnym środowiskiem wspierającym wiele języków, w tym interesujący nas C/C++. Zawiera ono wsparcie dla debugowania kodu, zarządzania wersjami za pomocą systemu kontroli wersji GIT, uzupełniania fragmentów kodu za pomocą inteligentnych podopowiedzi, oraz umożliwia jego łatwą reedycję. Przy tym jest on dużo „lżejszy” niż zalecany prawie dekadę temu środowisko zbudowane w oparciu na edytorze eclipse, który w dzisiejszych czasach stał się bardzo „ociężały”.

Konfiguracja środowiska

Instalację środowiska rozpoczynamy od pobrania interpretera języka python3, który dostępny jest pod adresem http://bit.ly/2Xg8ZQB. W zależności od posiadanej 32- lub 64-bitowej wersji Windows należy pobrać wersję „Windows x86 web based installer” lub „Windows x86_64 web based installer” oraz uruchomić instalator. Na ekranie konfiguracyjnym instalatora należy wybrać opcje jak na rysunku 1, a następnie kliknąć w przycisk „Install Now”.

Rysunek 1. Ekran konfiguracyjny instalatora

Na końcu instalacji program zapyta, czy chcemy wyłączyć limit długości ścieżki do 260 znaków, na co należy odpowiedzieć twierdząco i zakończyć proces. Aby sprawdzić, czy interpreter został zainstalowany prawidłowo, uruchamiamy wiersz polecenia systemu Windows, a następnie wpisujemy komendę python –version. Kolejnym narzędziem potrzebnym do pracy z systemem ISIX jest system kontroli wersji GIT, którego aktualną wersje możemy pobrać ze strony http://bit.ly/2XkXo2I. Należy wybrać wersję odpowiednią do posiadanego systemu. Podczas procesu instalacji należy zaznaczyć wszystkie elementy składowe, oraz wybrać folder docelowy, gdzie zostaną zapisane pliki. Kolejną czynnością jest wybór edytora tekstowego. Należy pozostawić domyślne ustawienia odnośnie do dodania narzędzia do ścieżki systemowej, wybrać bibliotekę „Windows Secure Channel” jako backend dla protokołu https oraz zostawić domyślne ustawienia odnośnie do znaków końca linii. Przy opcji wyboru terminalu należy pozostawić opcję MinTTY oraz zaznaczyć opcję „Enable Symbolic Links” (rysunek 2).

Rysunek 2. Zaznaczenie opcji „Enable Symbolic Links”

Do pracy ze środowiskiem ISIX jest niezbędny również kompilator gcc. Należy skorzystać z wersji dostępnej na mojej stronie domowej. Jest to specjalnie przygotowany kompilator zawierający biblioteki zoptymalizowane pod kątem zajętości pamięci Flash i RAM mikrokontrolera. W zależności od posiadanego systemu należy pobrać wersję 32-bitową http://bit.ly/2SjuLiE lub 64-bitową http://bit.ly/2SUEKA6.

Aby zainstalować kompilator, rozpakowujemy wybraną wersję do katalogu c:\tools, a następnie dodajemy do zmiennej środowiskowej PATH katalog c:\tools\arm-boff-mingw32-toolchain\arm-none-eabi\ bin dla wersji 32-bitowej lub c:\tools\arm-boff-mingw64-toolchain\arm- none-eabi\bin dla wersji 64-bitowej. Aby to zrobić, należy kliknąć prawym klawiszem myszy na Mój komputer → Właściwości, wybrać zakładkę Ustawienia zaawansowane → Zmienne środowiskowe, zaznaczyć opcję Zmienne systemowe → Path, kliknąć w przycisk Edytuj → Nowy, a następnie wpisać wskazaną wcześniej ścieżkę (rysunek 3).

Rysunek 3. Wpisanie ścieżki dostępu do kompilatora

Aby potwierdzić poprawność instalacji kompilatora, należy otworzyć wiersz poleceń cmd i wpisać polecenie arm-none-eabi-gcc-v. Jeśli zostanie wyświetlona informacja o wersji kompilatora, oznacza to, że proces instalacji przebiegł pomyślnie.

Po zainstalowaniu kompilatora należy pobrać oprogramowanie OpenOCD umożliwiające debugowanie systemów wbudowanych za pomocą interfejsów JTAG czy SWD. Oprogramowanie należy pobrać ze strony http://bit.ly/2NrS2ya, rozpakować go do katalogu c:\tools\ openocd , a następnie w analogiczny sposób jak poprzednio ścieżkę c:\ tools\openocd\bin dopisać do zmiennej środowiskowej PATH. Na zakończenie musimy pobrać sterowniki dla programatora ST-LINK ze strony http://bit.ly/2U5nOn1. Proces instalacji sterowników polega na rozpakowaniu pliku en.stw-lin00x.7z oraz uruchomieniu pliku stlink_winusb_install.bat, klikając prawym klawiszem myszy i wybierając opcję Uruchom jako administrator.

Do pracy z systemem ISIX przydatny będzie program terminalowy, ponieważ port RS232 często jest wykorzystywany do wyświetlania logów systemowych oraz komunikatów diagnostycznych. Możemy użyć programu PuTTY, który dostępny jest na stronie http://bit.ly/2Ud6EUk lub skorzystać z innego dowolnie wybranego programu terminalowego.

Do prawidłowego działania edytor VSCode potrzebuje dodatkowo kompilatora clang, który można pobrać z lokalizacji http://bit.ly/2Ve37Fv. Podobnie jak poprzednio, w zależności od tego czy dysponujemy systemem 32-bitowym, czy 64-bitowym, należy wybrać odpowiednią wersję. Podczas procesu instalacji należy zwrócić uwagę, aby w jednym z okien konfiguracyjnych wybrać opcję dodania ścieżki kompilatora clang do zmiennej środowiskowej PATH.

Ostatnim elementem, który będzie przydatny do pracy, jest samo środowisko Visual Studio Code, dostępne pod adresem http://bit.ly/2VhflNI. W zależności od preferencji możemy wybrać wersję instalatora, która zainstaluje VSCode w katalogu domowym lub wersję systemową, udostępniającą oprogramowanie dla wszystkich użytkowników. Podczas instalowania należy zaznaczyć wszystkie dodatkowe opcje (rysunek 4).

Rysunek 4. Zaznaczenie opcji dodatko

Po zakończonym procesie instalacji należy uruchomić VSCode oraz doinstalować dodatki niezbędne do pracy z kodem w języku C i C++. W tym celu po uruchomieniu środowiska należy wejść w zakładkę rozszerzenia za pomocą menu File → Preferences → Extension lub skrótu klawiszowego CTRL+SHIFT+X, a następnie za pomocą sklepu Marketplace zainstalować następujące dodatki (rysunek 5):

  1. C/C++.
  2. C/C++ Clang Command Adapter.
  3. C/C++ Compile and Run.
  4. C/C++ Snippets.
  5. C/C++ Intelisense.
  6. Easy C++ projects
Rysunek 5. Dodatki dostępne w witrynie marketplace

Pierwszy przykład dla zestawu STM32F411E-DISCO

Podobnie jak w przypadku nauki programowania na komputerze PC, gdzie jako jeden z pierwszych przykładów tworzymy aplikację typu Hello World, tak w przypadku przykładów wykorzystujących mikrokontrolery najczęściej tworzymy przykład błyskający diodą LED. Nie inaczej będzie w naszym przypadku, gdzie napiszemy program błyskający diodą LD3 zestawu STM32F411E-DISCO (fotografia 6) oraz wypisujący na porcie szeregowym co 1 sekundę informację tekstową z wykorzystaniem konsoli DEBUG systemu ISIX.

Fotografia 6. Zestaw STM32F411E-DISCO

Konfiguracja sprzętowa. Ponieważ zestaw STM32F411E-DISCO nie ma wyprowadzonego portu szeregowego, umożliwiającego bezpośrednie dołączenie zestawu do komputera, musimy skorzystać z dodatkowej przejściówki RS232(TTL) → USB. Możemy wykorzystać dowolną przejściówkę realizującą to zadanie. W przykładzie testowym użyto konwertera z układem FT232RL o oznaczeniu WSR-04502.

Układ należy połączyć z płytką ewaluacyjną za pomocą przewodów według konfiguracji pokazanej na fotografii 7 i w tabeli 1. Zestaw uruchomieniowy ma zintegrowany programator STLINKv2. Aby zaprogramować pamięć Flash, nie musimy mieć dedykowanego programatora. Wystarczy połączyć złącze CN1 zestawu z komputerem za pomocą przewodu USB Mini B → USB A.

Fotografia 7. Połączenia z płytką ewaluacyjną

Pierwszy przykład w środowisku VSCode

Aby skompilować przykładowy projekt, należy go wcześniej pobrać z repozytorium GIT projektu ISIX. W tym celu uruchamiamy ikonkę „Git Bash”, co spowoduje uruchomienie wiersza polecenia MINGW. W wierszu tym należy wpisać następujące polecenia:

git clone -b pub/ep0319 –recursive https://www.boff.
pl/cgit/public/isixsamples
cd isixsamples
git checkout -b mybranch
./bootstrap.sh

Powyższe polecenia powodują sklonowanie do katalogu domowego c:\users\ repozytorium zawierającego zestaw przykładów wraz z dodatkowym pod repozytorium zawierającym system ISIX. Po pobraniu kodu źródłowego należy uruchomić edytor VsCode, a z menu wybrać opcję „File → Open Folder”. Następnie należy wskazać katalog zawierający pobrany wcześniej kod źródłowy (isixsamples), co spowoduje otwarcie projektu w edytorze. Kolejną czynnością jest odpowiednia konfiguracja środowiska, tak aby uzyskać możliwość kompilowania, debugowania oraz uruchamiania aplikacji bezpośrednio z pomocą IDE. Konfiguracja ta odbywa się za pomocą bezpośredniej edycji plików w formacie JSON, co w przypadku bardziej zaawansowanych użytkowników jest dużym ułatwieniem, ponieważ nie musimy przechodzić przez wiele okien dialogowych.

Zaczniemy od konfiguracji systemu inteligentnych podpowiedzi. W tym celu w prawym oknie nawigacyjnym otwieramy plik z kodem przykładu, klikając dwukrotnie na plik stm32f411e_disco/app/blink. cpp. Następnie wciskamy kombinację klawiszy CTRL+P i rozpoczynamy wyszukiwanie opcji „C/C++ Edit Configuration” – wybieramy ją z listy wyszukiwania (rysunek 8).

Rysunek 8. Lista wyszukiwania

Po wybraniu opcji powinien wyświetlić się plik c_cpp_properties. json, który należy przystosować do pracy z systemem ISIX. W pliku tym należy skonfigurować ścieżki include dla projektu, definicję makr preprocesora, ścieżkę do kompilatora g++ dla ARM oraz standard języka. Dla naszego przykładu plik ten powinien wyglądać jak na listingu 1.

Listing 1. Plik c_cpp_properties.json
{
„configurations”: [
{
„name”: „ISIXRTOS”,
„includePath”: [
„${workspaceFolder}/build/isixrtos/libisix/include”,
„${workspaceFolder}/isixrtos/libisix/include”,
„${workspaceFolder}/isixrtos/libisix/arch/arm/include”,
„${workspaceFolder}/isixrtos/libisix/arch/arm/cortexm/m4f/include”,
„${workspaceFolder}/isixrtos/libisix/arch/arm/cortexm/include”,
„${workspaceFolder}/isixrtos/libisix/arch/include”,
„${workspaceFolder}/isixrtos/config/include”,
„${workspaceFolder}/isixrtos/libfoundation/include”,
„${workspaceFolder}/isixrtos/libperiph/periph/include”,
„${workspaceFolder}/isixrtos/libperiph/vendor/arm/cortexm/stm32/f4/include”,
„${workspaceFolder}/isixrtos/libperiph/periph/include/arch/arm/cortexm/stm32”,
„${workspaceFolder}/isixrtos/libperiph/periph/include/arch/arm/cortexm/stm32/f4”,
„${workspaceFolder}/isixrtos/libperiph/vendor/arm/cortexm/cmsis/include”,
„${workspaceFolder}/isixrtos/libperiph/vendor/arm/cortexm/cmsis/device/stm32/f4/include”,
„${workspaceFolder}/stm32f411e_disco/led_blink”,
„${workspaceFolder}/stm32f411e_disco/led_blink/board/include”
],
„defines”: [
„PDEBUG”,
„STM32MCU_MAJOR_TYPE_F4=1”,
„STM32F411xE”,
„USE_FULL_LL_DRIVER=1”,
„HAVE_ISIX_CONFIG_H=1”,
„_ISIX_KERNEL_CORE_=1”,
„__ARM_ARCH_7M__”,
„RCC_PLLI2S_SUPPORT”,
„RCC_PLLR_SYSCLK_SUPPORT”,
„RCC_PLLR_SYSCLK_SUPPORT”,
„HSE_VALUE=8000000”
],
„compilerPath”: „/usr/bin/arm-none-eabi-g++”,
„cStandard”: „c11”,
„cppStandard”: „c++17”,
„intelliSenseMode”: „gcc-x64”
}
],
„version”: 4
}

Aby skompilować oraz zaprogramować mikrokontroler bezpośrednio z poziomu IDE, należy wskazać sposób budowania oraz zestaw dodatkowych komend wykonywanych z poziomu IDE. W tym celu ponownie wybieramy kombinację klawiszy CTRL+P, a następnie wyszukujemy i wybieramy opcję: Tasks:Configure, co powinno spowodować wyświetlenie pliku tasks.json. W naszym przypadku plik ten powinien wyglądać jak na listingu 2. Plik ten opisuje komendy, jakie mogą być wykonywane bezpośrednio z poziomu edytora VSCode. Występują tutaj bezpośrednie odwołania komend do systemu budowania waf. Jak już wcześniej wspomniano, zbudowanie przykładu z wykorzystaniem systemu waf składa się z następujących kroków:

Konfigurowanie projektu [python waf configure --debug –crystal-hz=8000000].

Budowanie projektu [python waf].

Programowanie [p y th o n waf program].

Listing 2. Plik tasks.json
„version”: „2.0.0”,
„tasks”: [
{
„label”: „build”,
„type”: „shell”,
„command”: „python”,
„args”: [
„${workspaceFolder}/waf”,
],
„group”: {
„kind”: „build”,
„isDefault”: true
},
„problemMatcher”: {
„owner”: „cpp”,
„fileLocation”: [
„relative”,
„${workspaceFolder}/build”
],
„pattern”: {
„regexp”: „^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$”,
„file”: 1,
„line”: 2,
„column”: 3,
„severity”: 4,
„message”: 5
}
}
},
{
„label”: „clean”,
„type”: „shell”,
„command”: „python”,
„args”: [
„${workspaceFolder}/waf”,
„clean”
],
„problemMatcher”: []
},
{
„label”: „distclean”,
„type”: „shell”,
„command”: „python”,
„args”: [
„ ${workspaceFolder}/waf”,
„distclean”
]
},
{
„label”: „configure”,
„type”: „shell”,
„command”: „python”,
„args”: [
„${workspaceFolder}/waf”,
„configure”,
„--debug”,
„--crystal-hz=8000000”
],
„problemMatcher”: []
},
{
„label”: „program”,
„type”: „shell”,
„command”: „python”,
„args”: [
„${workspaceFolder}/waf”,
„program”
],
„problemMatcher”: []
}]

Każde polecenie zawiera sekcję cmd, w której możemy podać dodatkowe argumenty dla wybranej komendy. W przypadku opcji build mamy zdefiniowaną sekcję problemMatcher, która za pomocą wyrażeń regularnych parsuje wyniki ze standardowego wyjścia kompilatora, umożliwiając podświetlanie i przejście do linii, gdzie znajdują się błędy kompilacji oraz ostrzeżenia.

Potrafimy już zbudować projekt, pozostała nam jeszcze konfiguracja debugera, tak byśmy mogli debugować kod bezpośrednio z poziomu IDE. Aby to zrobić, należy nacisnąć kombinację klawiszy CTRL+P, a następnie znaleźć i uruchomić opcje Debug:Open launch.json, co powinno spowodować wyświetlenie pliku konfiguracyjnego launch.json. Domyślne wpisy w pliku należy zamienić w sposób pokazany na listingu 3. Plik zawiera zarówno konfigurację samego debuggera gdb, jak i konfigurację oprogramowania openocd pozwalającą uruchomić proces debugowania oprogramowania jednym kliknięciem myszki. Nie musimy w osobnym oknie uruchamiać serwera openocd, podobnie po zakończeniu procesu debugowania serwer jest automatycznie zatrzymywany, co jest bardzo wygodnym rozwiązaniem.

Listing 3. Plik konfiguracyjny launch.json
{
„version”: „0.2.0”,
„configurations”: [
{
„name”: „(gdb) Launch”,
„type”: „cppdbg”,
„request”: „launch”,
„program”: „${workspaceFolder}/build/stm32f411e_disco/led_blink/411disco_blink”,
„args”: [],
„stopAtEntry”: true,
„cwd”: „${workspaceFolder}”,
„environment”: [],
„externalConsole”: true,
„windows”: {
„MIMode”: „gdb”,
„miDebuggerPath”: „arm-none-eabi-gdb.exe”,
„miDebuggerServerAddress”: „localhost:3333”,
„miDebuggerArgs”: „-x ${workspaceFolder}/libstm32/scripts/gdbinit”,
„debugServerPath”: „openocd.exe”,
„debugServerArgs”: „-c \”set ISIX_INTERFACE stlink-v2; set ISIX_INTERFACE_TARGET stm32f4x; set ISIX_INTERFACE_SWD 1; set
ISIX_INTERFACE_SPEED_KHZ 2000; \” -s C:\\tools\\openocd\\share\\openocd\\scripts -f ${workspaceFolder}\\isixrtos\\libperiph\\scripts\\
openocd\\jtag.cfg”,
„serverLaunchTimeout”: 20000,
„serverStarted”: „Listening on port 3333 for gdb connections”,
„filterStderr”: true,
„filterStdout”: false,
},
„setupCommands”: [
{
„description”: „Enable pretty-printing for gdb”,
„text”: „-enable-pretty-printing”,
„ignoreFailures”: true
}],
„logging”: {
„moduleLoad”: false,
„trace”: false,
„engineLogging”: false,
„programOutput”: true,
„exceptions”: true
},
„targetArchitecture”: „arm”
}
]
}

Opisany proces konfiguracyjny może wydawać się czytelnikom stosunkowo skomplikowany, niemniej jednak zadanie to wykonujemy jednorazowo. Tworząc nowe projekty, możemy wykorzystać opisaną konfigurację jako referencyjną. Zmian wymagać będą tylko niektóre wpisy dotyczące ścieżek do plików wykonywalnych czy nazwy w projekcie. Widać tutaj ogromną zaletę konfiguracji z pomocą plików JSON w stosunku do Eclipse, gdzie z każdym nowym projektem wszelkie ustawienie trzeba było konfigurować od nowa w wielu oknach dialogowych.

Mamy w pełni skonfigurowane środowisko IDE, możemy zatem przystąpić do skompilowania oraz załadowania pierwszego projektu. Pierwszą czynnością jest proces konfiguracji projektu. Aby tego dokonać, wciskamy kombinację klawiszy CTRL+P i wyszukujemy opcję Run Tasks (rysunek 9), następnie z menu wyszukiwania wybierając opcję Configure (rysunek 10).

Rysunek 9. Wybranie opcji „Run Tasks”
Rysunek 10. Wybranie opcji „Configure”

Po skonfigurowaniu projektu przystępujemy do procesu kompilacji. Aby tego dokonać, postępujemy analogicznie, tym razem wybieramy opcję Build. Aby się przekonać, czy projekt działa, należy go załadować do mikrokontrolera, możemy tego dokonać podobnie jak poprzednio, wybierając opcję Program, co spowoduje rozpoczęcie procesu programowania pamięci Flash. Jeśli proces programowania zakończył się pomyślnie, dioda LD3 powinna zacząć błyskać w cyklu 0,5 s.

Potrafimy już kompilować oraz programować pamięć Flash mikrokontrolera, na koniec pokażemy, jak w prosty i wygodny sposób można debugować oprogramowanie. Załóżmy, że chcemy sprawdzić zawartość zmiennej lokalnej i w funkcji test_thread(). Aby tego dokonać, klikamy lewym klawiszem myszy w edytorze tuż za numerem wybranej linii, co spowoduje ustawienie pułapki (breakpoint). Teraz wystarczy wywołać menu debuggera, wciskając klawisz CTRL+D oraz wcisnąć przycisk zielonej strzałki w prawym górnym rogu, co spowoduje uruchomienie debugowania. Gdy program dotrze do wspomnianego punktu zatrzymania, linia, w której postawiono pułapkę, zostanie podświetlona. Wskazując myszką wybraną zmienną, możemy obejrzeć jej wartość (rysunek 11).

Rysunek 11. Podgląd wartości

Korzystając z menu sterującego debugowaniem na górze ekranu albo z odpowiadających mu skrótom klawiaturowym, możemy sterować wykonywaniem kodu, tak jak w innych popularnych środowiskach programistycznych. Program oprócz błyskania diodą wyświetla na konsoli szeregowej komunikaty zawierające napis Loop , gdzie n jest liczbą komunikatów, które zostały wysłane na port szeregowy. Aby je zobaczyć, wystarczy uruchomić program PuTTY i podłączyć się do wirtualnego portu szeregowego, ustalając prędkość transmisji na 115 200.

Opis projektu

Repozytorium isixsamples umożliwia zbudowanie przykładów dla kilku różnych rodzajów zestawów ewaluacyjnych. Konfiguracja dokonywana jest za pomocą polecenia python waf configure –board=xxx --crystal-hz=yyy, gdzie xxx jest odpowiednim kodem opisującym daną płytkę, natomiast yyy jest częstotliwością rezonatora kwarcowego HCLK. W naszym przypadku dla zestawu STM32FF411-DISCO zamiast xxx należy podać ciąg tekstowy stm32f411e_disco, a zamiast yyy należy wpisać wartość 8’000’000. Jeśli chcemy się dowiedzieć na temat innych dostępnych opcji konfiguracyjnych, możemy wydać polecenie python waf–help. Gdy pracujemy nad projektem, każdorazowe wpisywanie szeregu opcji do polecenia configure nie jest zbyt wygodne, dlatego w systemie ISIX wprowadzono dodatkowy mechanizm przechowujący opcjonalne parametry konfiguracyjne. Konfiguracja może być również zapisana w pliku config.json (listing 4).

Listing 4. Konfiguracja zapisana w pliku config.json
{
„jtag”: {
„target”: „stm32f411e_disco/led_blink/411disco_blink”,
„type”: „stlink-v2”,
„speed”: 2000,
„swd”: 1
},
„configure” : {
„disable_isix”: false,
„disable_exceptions” : true
}
}

Parametry konfiguracyjne możemy dopisać do sekcji configure. Jeśli dana opcja konfiguracyjna nie wystąpiła w wierszu polecenia, system użyje opcji zawartej w tej sekcji. W pliku występuje również dodatkowa sekcja o nazwie jtag, przechowująca konfigurację programatora. W sekcji możemy wpisać ścieżkę do pliku elf zawierającą plik wykonywalny do zaprogramowania pamięci Flash. Możemy również zdefiniować typ posiadanego programatora. Opcje te są niedostępne z poziomu polecenia configure.

Zajmijmy się teraz kodem przykładu pokazanego na listingu 5. Funkcja główna main() jest odpowiedzialna za inicjalizację systemu, konfigurację układów peryferyjnych oraz utworzenie jedynego aktywnego wątku. Na początku konfigurowany jest port szeregowy stanowiący standardowe wyjście konsoli systemowej. Następnie, za pomocą biblioteki periph, jest konfigurowany jako wyjście port PD13, do którego jest dołączona dioda LED. Teraz jest tworzony nowy wątek test_thread, a na koniec uruchamiany planista systemu ISIX, co rozpoczyna pracę systemu. Przy tworzeniu wątku warto zwrócić uwagę na argumenty funkcji task_create, które zawierają odpowiednio w kolejności: adres funkcji realizującej kod wątku, argument przekazany do funkcji wątku, rozmiar stosu oraz priorytet wątku. W przeciwieństwie do systemów operacyjnych wykorzystujących jednostkę zarządzania pamięcią MMU, rozmiar stosu dla wątku/procesu musi być znany na etapie jego utworzenia. Wszystkie zadania, jakie realizuje ten prosty kod, realizowane są przez funkcję wątku test_thread. Funkcja składa się z pętli nieskończonej, w której za pomocą dbprintf() wypisywana jest wartość zmiennej na konsoli szeregowej oraz z pomocą funkcji gpio_set() ustawiany jest stan portu PD13, co powoduje włączanie lub wyłączanie diody LED do niego dołączonej.

#include <config/conf.h>
#include <foundation/sys/dbglog.h>
#include <periph/drivers/serial/uart_early.hpp>
#include <periph/gpio/gpio.hpp>
#include <isix.h>
namespace {
constexpr auto led_0 = periph::gpio::num::PD13;
}
namespace app {
void test_thread(void*) {
for(int i=0;;++i) {
isix::wait_ms(500);
if(i%2==0) dbprintf(„Loop %i”,i>>1);
periph::gpio::set(led_0, i%2);
}
}
}
auto main() -> int
{
static isix::semaphore m_ulock_sem { 1, 1 };
isix::wait_ms( 500 );
dblog_init_locked(
[](int ch, void*) {
return periph::drivers::uart_early::putc(ch);
},
nullptr,
[]() {
m_ulock_sem.wait(ISIX_TIME_INFINITE);
},
[]() {
m_ulock_sem.signal();
},
periph::drivers::uart_early::open,
„serial0”, 115200
);
// Configure PD13 pin LED as an output
periph::gpio::setup( led_0, periph::gpio::mode::out{
periph::gpio::outtype::pushpull,
periph::gpio::speed::low
});
isix::task_create( app::test_thread, nullptr, 1536, isix::get_min_priority() );
dbprintf(„<<<< Hello STM32F411E-DISCO board >>>>”);
isix::start_scheduler();
return 0;
}

Przy okazji warto wspomnieć o bibliotece libperiph i konfiguracji urządzeń. W trzeciej odsłonie systemu ISIX wprowadzono konfigurację parametrów sterowników za pomocą mechanizmu globalnej konfiguracji, która odczytywana jest przez system ze zmiennej configuration, zwyczajowo przechowywanej w pliku dts.cpp. Na przykład konfiguracja wspomnianego wcześniej portu szeregowego konsoli przedstawia się jak na listingu 6. Jak można zauważyć, łatwo da się konfigurować dowolne parametry i ustawienia portu szeregowego, na przykład możemy wybrać linie konfiguracyjne dla linii RXD, TXD.

Listing 6. Konfiguracja portu szeregowego
constexpr device devices[]
{
{
„serial0”, reinterpret_cast<uintptr_t>(USART2),
bus::apb1, LL_GPIO_AF_7,
unsigned(std::log2(LL_APB1_GRP1_PERIPH_USART2)),
ser0_pins,
nullptr
},
{}
};
//! The machine config
constexpr configuration the_machine_config {
clk,
devices
};

Lucjan Bryndza, EP
lucjan.bryndza@boff.pl

Artykuł ukazał się w
Elektronika Praktyczna
marzec 2019

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik marzec 2021

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio marzec 2021

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka Podzespoły Aplikacje marzec 2021

Automatyka Podzespoły Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna marzec 2021

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Praktyczny Kurs Elektroniki 2018

Praktyczny Kurs Elektroniki

24 pasjonujące projekty elektroniczne

Elektronika dla Wszystkich kwiecień 2021

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów