Elektroda.pl
Elektroda.pl
X
PCBway
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Zarządzanie zadaniami w środowisku Arduino (TaskScheduler)

khoam 22 Lip 2019 20:07 2682 24
  • Zarządzanie zadaniami w środowisku Arduino (TaskScheduler)

    Każdy, kto zaczyna swoją przygodę z Arduino, zwykle na samym początku staje przed dylematem w jaki sposób prosto i przejrzyście zarządzać zadaniami, które uruchamiane powinny być w określonych i najczęściej różnych interwałach czasowych. Jest to problem tzw. harmonogramowania zadań. W niniejszym artykule została opisana biblioteka TaskScheduler, która w moim przekonaniu jest obecnie najlepszym narzędziem do harmonogramowania zadań w środowisku Arduino wszędzie tam, gdzie nie można skorzystać z RTOS.

    Biblioteka TaskScheduler jest „lekką” implementacją tzw. współpracy wielozadaniowej (ang. cooperative multitasking), bez użycia przerwań, z naciskiem na minimalne wykorzystanie pamięci RAM oraz flash. TaskScheduler jest dostępny w Menedżerze Bibliotek w Arduino IDE i wspiera następujące platformy sprzętowe: AVR (Uno/Nano/Mega/Micro/Mini oraz ATtiny85), ESP8266, ESP32, Teensy, STM32F1. W najnowszej wersji testowej 3.0.3 dodano wsparcie dla platform MSP430 raz MSP432.

    Podstawowe cechy tej biblioteki to (wersja 3.0.2 - stabilna):
    • umożliwienie okresowego wykonywania zadań, zgodnie ze zdefiniowanym interwałem czasowym wyrażonym w milisekundach (domyślnie) lub też mikrosekundach;
    • liczba iteracji danego zadania może być z góry określona lub też zadanie może się cyklicznie uruchamiać w „nieskończoność”;
    • podstawowe parametry zadań takie, jak interwał czasowy, liczba iteracji czy rodzaj funkcji wywoływanej przez zadanie (tzw. callback methods) mogą być dynamicznie zmieniane w trakcie działania programu;
    • oszczędzanie energii poprzez wejście w tryb uśpienia (light sleep), kiedy żadne z zadań nie jest zaplanowane do uruchomienia;
    • możliwość priorytetyzacji określonych grup zadań przypisanych do rożnych kontrolerów;
    • obsługa identyfikatorów zadań i punktów kontrolnych w programie, w celu obsługi wystąpień błędów oraz watchdog.

    Szczegółowa dokumentacja (w języku angielskim) znajduje się w:
    (opis działania) https://github.com/arkhipenko/TaskScheduler/wiki/Full-Document
    (funkcje biblioteczne) https://github.com/arkhipenko/TaskScheduler/wiki/API-Documentation
    (przykłady) https://github.com/arkhipenko/TaskScheduler/tree/master/examples

    W TaskScheduler poszczególne zadania są łączone w łańcuchy, które są przetwarzane przez jeden lub więcej kontroler zadań (scheduler), w kolejności w jakiej zostały dodane do łańcucha. Następnie są one cyklicznie uruchamiane zgodnie z ustalonym programowo interwałem czasowym. TaskScheduler nie narzuca ograniczenia w postaci maksymalnej liczby zdefiniowanych, czy też uruchomionych zadań. Liczba ta wynika jedynie z ilości dostępnych zasobów pamięci na danej platformie sprzętowej. Łańcuch zadań zaimplementowany jest jako lista dwukierunkowa.

    Zadanie, które jest już w trakcie wykonywania nie może zostać przerwane przez inne zadanie, nawet takie o wyższym priorytecie. Jest to niewątpliwie wada tego rozwiązania wynikająca z faktu nieużywania przerwań przez TaskScheduler. Konsekwencją tego jest również „zakaz”, a przynajmniej maksymalne ograniczenie używania funkcji typu delay() w funkcjach callback wywoływanych przez poszczególne zadania. Oczywistym jest też, że zapętlenie, czy też zawieszenie danego zadania spowoduje zatrzymanie działania całego programu. Warto więc zaimplementować obsługę watchdog w programie na wypadek takich sytuacji.

    TaskScheduler nie blokuje przerwań w trakcie wykonywania zadań, więc nic nie stoi na przeszkodzie, aby używać równolegle własnych procedur obsługi przerwań w krytycznych sekcjach programu. Co więcej, przewidziano w bibliotece TaskScheduler możliwość asynchronicznego wyzwalania wybranych zadań za pomocą przerwań (wewnętrznych lub zewnętrznych) – zadania takie mają najwyższy priorytet, o ile nie zablokuje się przerwań.
    Zarządzanie zadaniami w środowisku Arduino (TaskScheduler)

    Na rysunku z lewej strony pokazany jest algorytm działania TaskScheduler. Wywołanie kontrolera zadań powinno być umiejscowione w pętli loop() - nie powinny się tam znajdować wywołania innych funkcji, aby nie zaburzyć procesu harmonogramowania zadań. Nie jest to bezwzględny wymóg, ale rekomendacja.

    Prosty przykład wykorzystania biblioteki TaskScheduler, którego kod zamieszczam poniżej, jest kolejną reinkarnacją programu do migania diodą (co 1 sekundę). Wykorzystana zostanie dioda LED wbudowana na płytce (LED_BUILTIN). Funkcjonalność programu została poszerzona o dodatkowe zadanie: co 3 sekundy jest czytana „analogowo” wartość z portu A0, a wynik tego pomiaru wyświetlany jest w monitorze portu szeregowego Arduino IDE wraz z numerem kolejnej iteracji (liczonej od zera) – zadanie to wykonuje się tylko 10 razy, po czym staje się nieaktywne.

    Wszystkie programy prezentowane w tym artykule zostały przetestowane na platformie Arduino Uno, NodeMCU V3 (ESP8266) oraz ESPduino-32 (ESP32).
    Kod programu:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Przykładowy wynik działania:
    Kod: bash
    Zaloguj się, aby zobaczyć kod

    W pętli loop() umieszczone jest wywołanie funkcji kontrolera execute(), wykonuje ona jeden przebieg harmonogramowania oraz uruchamia zadania zgodnie z ich zaplanowanym interwałem czasowym. Funkcja ta dodatkowo wyłącza te zadania, które przekroczyły liczbę zdefiniowanych dla nich iteracji oraz (opcjonalnie) przełącza procesor w tryb uśpienia, jeżeli żadne z zadań nie jest zaplanowane do uruchomienia.

    W zadaniu blinkLedTask przyjęto, że będzie się ono uruchamiało co 1 sekundę (TASK_SECOND) i bez ograniczenia liczby iteracji (TASK_FOREVER zdefiniowane jako wartość -1). Funkcja callback dla tego zadania to blinkLedCallback().
    W zadaniu readAnalogPinTask przyjęto natomiast, że będzie się ono uruchamiało co 3 sekundy i nie więcej niż 10 razy. Funkcja callback dla tego zadania to readAnalogPinCallback().
    Oba zadania definiowane są poprzez wywołanie konstruktora Task, który przyjmuje następujące parametry:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Jak widać, w powyższym przykładzie zdefiniowane zostały tylko trzy pierwsze parametry konstruktora Task, pozostałe przyjmują wartości domyślne.

    W celu określenia interwału czasowego zadania lepiej jest używać stałych (definicji): TASK_MILLISECOND, TASK_SECOND, TASK_MINUTE czy TASK_HOUR, wtedy niezależnie od wybranego trybu naliczania czasu (milisekundy albo mikrosekundy) rzeczywista wartość interwału czasowego pozostanie niezmienna. W trakcie działania programu można zmieniać interwał czasowy zadania za pomocą funkcji setInterval(). Można również wymusić kolejną iterację zadania, poza jego ustalonym harmonogramem za pomocą funkcji forceNextIteration().

    Liczbę iteracji zadania można również określić jako TASK_ONCE, wtedy to zadanie wykona się tylko jeden raz, o ile w trakcie działania programu nie zmienimy tego parametru funkcją setIterations(). Każde zadanie można również restartować (zeruje się wtedy licznik iteracji tego zadania) za pomocą funkcji restart() lub restartDelayed(). W trakcie wykonywania zadania można na bieżąco sprawdzać, ile iteracji tego zadania pozostało jeszcze do wykonania (getIterations()), czy wykonywana jest jego pierwsza iteracja (isFirstIteration()) lub czy też wykonywana jest ostatnia iteracja zadania (isLastIteration()).

    W trakcie działania programu można również zmieniać przypisanie funkcji callback dla danego zadania za pomocą setCallback().

    Przypisanie zadania do kontrolera wykonuje się za pomocą funkcji addTask(). Zadanie przypisane do kontrolera zostanie uruchomione w pierwszym wywołaniu funkcji kontrolera execute() w pętli loop(), o ile wcześniej zostanie włączone. Funkcja kontrolera enableAll() włącza wszystkie przypisane do niego zadania. W trakcie działanie programu można włączać lub wyłączać poszczególne zadania za pomocą funkcji enable(), enableDelayed() oraz disable().

    W następnym przykładowym programie została dodana nowa funkcjonalność: po wykonaniu wszystkich 10 iteracji zadania readAnalogPinTask (odczyt i wyświetlanie wartości z portu A0) następuje zmiana interwału czasowego zadania blinkLedTask (miganie diodą) z 1 sekundy na 250 milisekund. Dodatkowo zmieniony został tryb zliczania czasu dla kontrolera zadań, z milisekund na mikrosekundy.
    Kod programu:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Tym razem oba zadania zostały zadeklarowane ze wszystkim parametrami. Nie są już potrzebne wywołania funkcji kontrolera addTask() oraz enableAll(), ponieważ w deklaracji zadań tych umieszczono wskaźnik do zmiennej kontrolera zadań (&controller) oraz ustawiono parametr zadania aEnable na wartość true (zadanie jest włączone w momencie inicjalizacji).

    W deklaracji zadania readAnalogPinTask podano również wskaźnik do funkcji callback onDisableReadAnalogPinTask(), która odpowiada za zmianę interwału czasowego zadania blinkLedTask. Wywołuje się ona w momencie, kiedy zadanie readAnalogPinTask staje się nieaktywne – w tym przypadku, kiedy zostanie wykonana ostatnia jego iteracja.

    Przed włączeniem pliku nagłówkowego TaskScheduler.h umieszczono definicję _TASK_MICRO_RES, która powoduje, że mechanizm zliczania czasu przez kontroler zadań zmienia się z trybu milisekundowego na mikro-sekundowy. Jest to jeden z parametrów kompilacji dla biblioteki TaskScheduler. W programie użyliśmy stałych TASK_SECOND oraz TASK_MILLISECOND, więc nie wpłynie to na rzeczywistą wartość interwałów czasowych obu zadań. Przełączenie w tryb mikro-sekundowy ma jednak swoją cenę: w trybie tym nie można już korzystać z oszczędzania energii poprzez wejście w tryb uśpienia (light sleep).

    Jest jeszcze kilka innych parametrów kompilacji dla biblioteki TaskScheduler, najważniejsze zostały opisane poniżej. Szczegółowy opis ich wpływu na działanie znajduje się w dokumentacji biblioteki, do której link został podany na początku artykułu. Parametry te są również opisane w komentarzach na początku pliku nagłówkowego TaskScheduler.h.

    _TASK_TIMECRITICAL – włączenie śledzenia dokładności wykonania zadań, zgodnie z ich ustalonym interwałem czasowym; istnieje możliwość sprawdzania np. czy kolejne iteracje danego zadania nie są opóźniane.

    _TASK_SLEEP_ON_IDLE_RUN – włączenie opcji oszczędzania energii poprzez wejście w tryb uśpienia (light sleep); w wersji 3.0.2 ta opcja jest dostępna tylko dla platformy AVR; parametr ten jest ignorowany, jeżeli jest również ustawiony parametr _TASK_MICRO_RES.

    _TASK_STATUS_REQUEST – włączenie możliwości blokowania zadań w oczekiwaniu na określone zdarzenie (sygnał pochodzący od innego zadania lub z innego punktu programu).

    _TASK_WDT_IDS – włączenie opcji umożliwiającej wstawianie i zapisywanie punktów kontrolnych w przebiegu funkcji callback, co umożliwia identyfikację problemów (np. nieoczekiwane restarty) z uruchamianym kodem; szczególnie przydatne, kiedy korzysta się z watchdog.

    _TASK_LTS_POINTER – włączenie opcji, która umożliwia rozszerzenie działania funkcji callback o automatyczne pobieranie i przekazywanie (przez referencję) zmiennych lub struktur, przed wywołaniem funkcji callback dla danego zadania (w sposób pośredni umożliwia więc przekazywanie argumentów dla funkcji callback).

    _TASK_PRIORITY – włączenie możliwości kreowania więcej niż jednego kontrolera zadań i przypisywaniu tym kontrolerom priorytetów; wszystkie zadania przypisane do kontrolera o wyższym priorytecie będą automatycznie posiadały wyższy priorytet nad wszystkimi zadaniami przypisanymi do kontrolera o niższym priorytecie.

    _TASK_TIMEOUT – włączenie opcji umożliwiającej w trakcie działania programu wywoływanie przerw w wykonywaniu zadań w sytuacjach, kiedy jest to wymagane; przerwa taka powoduje, że zadanie staje się nieaktywne na czas określony przez tzw. timeout, który jest niezależny od zdefiniowanego interwału czasowego dla zadania.

    To jest już wszystko, jeżeli chodzi o podstawowy opis biblioteki TaskScheduler, Zachęcam do jej używania w środowisku Arduino, pozwala ona na zaoszczędzanie wiele czasu (i linii kodu) wszędzie tam, gdzie mamy do czynienia z koniecznością harmonogramowania tzn. uruchamianiem wielu zadań, które powinny się wykonywać z różną częstotliwością oraz wtedy, kiedy chcemy mieć jak największą kontrolę nad wykonywaniem tych zadań oraz zależy nam na dobrej diagnostyce błędów.

    Zachęcam również do zapoznania się z dokumentacją biblioteki TaskScheduler – linki zostały podane na początku artykułu. Jeżeli będzie zainteresowanie, postaram się przygotować następną część, w której opisze bardziej zaawansowane mechanizmy dostępne w tej bibliotece. W załączeniu umieszczam kody obu programów, które zostały opisane w tym artykule oraz niniejszy artykuł w formacie PDF.

    Fajne! Ranking DIY
    Potrafisz napisać podobny artykuł? Wyślij do mnie a otrzymasz kartę SD 64GB.
    O autorze
    khoam
    Poziom 33  
    Offline 
    Specjalizuje się w: esp32, c++, linux
    khoam napisał 1775 postów o ocenie 180, pomógł 215 razy. Mieszka w mieście Piaseczno. Jest z nami od 2007 roku.
  • PCBway
  • #2
    Belialek
    Poziom 22  
    Kawał dobrej roboty z opisem tej biblioteki - ogarnięcie timerów to dla mnie dramat, a tutaj wszystko podane na tacy. Dziękuję!
  • PCBway
  • #4
    khoam
    Poziom 33  
    Belialek napisał:
    Kawał dobrej roboty z opisem tej biblioteki - ogarnięcie timerów to dla mnie dramat, a tutaj wszystko podane na tacy. Dziękuję!

    Dziękuję. W dziale Arduino do znudzenia pojawiają się problemy z "ręcznym" odmierzaniem czasu w celu harmonogramowania zadań. Może ten artykuł pomoże niektórym zaoszczędzić nieco czasu ... i postów :)

    Slawek K. napisał:
    @khoam, wielkie brawa

    Dzięki. Niepokoi mnie trochę brak "tradycyjnej" krytyki Arduino, może ze względu na sezon wakacyjny? ;)
  • #5
    Slawek K.
    Poziom 31  
    Główni hejterzy arduinowi maja zablokowane konta a inni są w permanentnym procesie usuwania i zakładania nowych kont, może dlatego ;)

    Pozdr
  • #7
    o_Tadeusz
    Poziom 15  
    W loop widzę wywoływanie
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Czy to oznacza, że taski są wywoływane w pętli głównej i jeden z nich może zablokować pozostałe?
  • #8
    Janusz_kk
    Poziom 21  
    Dokładnie, dlatego takie taski są bez sensu, jedynie na przerwaniach mają sens.
  • #9
    khoam
    Poziom 33  
    o_Tadeusz napisał:
    Czy to oznacza, że taski są wywoływane w pętli głównej i jeden z nich może zablokować pozostałe?

    Jeżeli funkcja callback w którymś z zadaniu będzie zawierała np. nieskończoną pętlę, to tak się stanie.
    W artykule jest napisane:
    khoam napisał:
    Oczywistym jest też, że zapętlenie, czy też zawieszenie danego zadania spowoduje zatrzymanie działania całego programu. Warto więc zaimplementować obsługę watchdog w programie na wypadek takich sytuacji.


    Dodano po 1 [minuty]:

    Janusz_kk napisał:
    Dokładnie, dlatego takie taski są bez sensu, jedynie na przerwaniach mają sens.

    Spróbuj w obsłudze przerwania umieścić nieskończoną pętlę, aby się przekonać co się stanie.
  • #11
    Janusz_kk
    Poziom 21  
    khoam napisał:
    Spróbuj w obsłudze przerwania umieścić nieskończoną pętlę, aby się przekonać co się stanie.

    Zależy od procka, w zwykłychj avr-ach się zablokuje ale tam gdzie jest więcej poziomów przerwań te inne będą chodzić,
    to po 1 a po 2 kto w przerwaniu robi taką pętlę, jak już to tylko jako główna w main.
  • #12
    khoam
    Poziom 33  
    Janusz_kk napisał:
    to po 1 a po 2 kto w przerwaniu robi taką pętlę, jak już to tylko jako główna w main.

    To był tylko przykład na zawieszenie/zapętlenie się zadania. Może on wystąpić z różnych powodów.

    Janusz_kk napisał:
    ale tam gdzie jest więcej poziomów przerwań te inne będą chodzić,

    Jest to w dalszym ciągu sytuacja, która powinna być wykryta oraz obsłużona, jako błąd.

    Dodano po 3 [minuty]:

    o_Tadeusz napisał:
    Czyli ta biblioteka to taka rozbudowana https://forum.arduino.cc/index.php?topic=538663.0

    Biblioteka Timer, którą wskazałeś, zawiera niewielką cześć funkcjonalności TaskScheduler, więc trudno jest porównywać obie biblioteki. Oczywiście jeżeli komuś to wystarcza, to jego decyzja, której biblioteki użyje. Biblioteka Timer nie jest już rozwijana od ponad 5 lat.
  • #13
    o_Tadeusz
    Poziom 15  
    Janusz_kk napisał:
    khoam napisał:
    Spróbuj w obsłudze przerwania umieścić nieskończoną pętlę, aby się przekonać co się stanie.

    Zależy od procka, w zwykłychj avr-ach się zablokuje ale tam gdzie jest więcej poziomów przerwań te inne będą chodzić,

    Takie luksusy to Xmega (ale podobno TaskScheduler na nim nie działa) albo ARM. Jeśli ktoś umie używać wielopoziomowych przerwań to wątpię aby używał TaskScheduler, prędzej sięgnie po RTOS.
    Analizując TaskScheduler można stwierdzić, że został stworzony dla osób, które nie potrafią napisać procedur obsługi przerwań czy używać RTOS albo wykorzystać millis, co przystępnie opisano https://forbot.pl/blog/kurs-arduino-ii-wielozadaniowosc-opoznienia-z-millis-id18418 a potrzebują namiastki multitaskingu.

    Znalazłem opis RTOS dla arduino https://starter-kit.nettigo.pl/2018/10/system-operacyjny-czasu-rzeczywistego-dla-arduino/ Może ktoś podzielić się wrażeniami z użytkowania RTOS na AVR?
    W przykładach widzę
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Aż taki duży stos jest potrzebny? Parę tasków i skończy się pamięć w UNO zwłaszcza, ze napisano
    Cytat:

    Trzeci parametr to rozmiar stosu w słowach (nie w bajtach). Słowo na Arduino to 16 bitów (2 bajty), tak więc 128 słów to 256 bajtów pamięci.

    Niepokoi mnie też
    Kod: c
    Zaloguj się, aby zobaczyć kod

    co oznacza, że gwarantowany czas kolejnych zadziałań tasku może wynosić 15ms i tyle samo czasu taks może się wykonywać. Nie da się tego zmniejszyć do 1ms?
  • #14
    khoam
    Poziom 33  
    o_Tadeusz napisał:
    Analizując TaskScheduler można stwierdzić, że został stworzony dla osób, które nie potrafią napisać procedur obsługi przerwań czy używać RTOS albo wykorzystać millis

    To oczywiście nie jest prawda. Biblioteka TaskScheduler ułatwia harmonogramowanie zdań w środowisku Arduino, niezależnie od tego, czy ktoś potrafi pisać procedury obsługi przerwań, wykorzystywać millis(), a nawet używać RTOS.

    W artykule jest napisane:
    khoam napisał:
    Co więcej, przewidziano w bibliotece TaskScheduler możliwość asynchronicznego wyzwalania wybranych zadań za pomocą przerwań (wewnętrznych lub zewnętrznych) – zadania takie mają najwyższy priorytet, o ile nie zablokuje się przerwań.


    Dodano po 12 [minuty]:

    o_Tadeusz napisał:
    to Xmega (ale podobno TaskScheduler na nim nie działa)

    Nie "działa", ponieważ nie ma sensownego ArduHAL dla XMega. Nic jednak nie jest stoi na przeszkodzie, aby użyć własnych funkcji millis() oraz micros() (odpowiedniki tych w ArduHAL), a następnie używać TaskScheduler z tymi funkcjami. Oczywiście niezbędny jest kompilator C++.

    Dodano po 26 [minuty]:

    o_Tadeusz napisał:
    Może ktoś podzielić się wrażeniami z użytkowania RTOS na AVR?

    Jest osobny wątek na Forum pod tytułem "RTOS - wszystko, co chciałbyś wiedzieć i nie boisz się zapytać":
    https://www.elektroda.pl/rtvforum/topic3581141.html
    Może tam znajdziesz odpowiedź na swoje pytania dotyczące RTOS dla AVR.
  • #15
    figa_miga
    Poziom 19  
    khoam napisał:

    Slawek K. napisał:
    @khoam, wielkie brawa

    Dzięki. Niepokoi mnie trochę brak "tradycyjnej" krytyki Arduino, może ze względu na sezon wakacyjny? ;)


    Ja się tam za jakiegoś krytyka nie uważam, nawet arduino nie używam... ale czy to nie jest jakiś "pic na wodę"?.
    Czym ten scheduler różni się od napisania prostych warunków wykonania zadania w pętli głównej, gdzie flaga na jego wykonanie ustawiana jest w obsłudze timera?.
  • #16
    khoam
    Poziom 33  
    figa_miga napisał:
    Czym ten scheduler różni się od napisania prostych warunków wykonania zadania w pętli głównej, gdzie flaga na jego wykonanie ustawiana jest w obsłudze timera?.

    Na temat tych "różnic" napisałem w artykule, a przynajmniej się starałem. Kompletna dokumentacja TaskScheduler jest tutaj:
    https://github.com/arkhipenko/TaskScheduler/wiki/Full-Document

    Na początek proponuję napisanie kodu tylko z "użyciem prostych warunków wykonania zadania w pętli głównej", który będzie 100% odpowiednikiem funkcjonalnym jednego z przykładów z biblioteki TaskScheduler:
    https://github.com/arkhipenko/TaskScheduler/b...e12_Priority/Scheduler_example12_Priority.ino

    Tego rodzaju doświadczenie będzie najbardziej przekonywujące niż jakiekolwiek inne formy argumentacji :)

    Dodano po 4 [godziny] 26 [minuty]:

    khoam napisał:
    Nie "działa", ponieważ nie ma sensownego ArduHAL dla XMega.

    Okazałem się chyba niepoprawnym pesymistą ;)

    Znalazłem w necie (nieoficjalne) ArduHAL dla XMega: https://github.com/XMegaForArduino/arduino
    Zainstalowałem definicję płytek. Wybrałem ATXMega128A1U. Przykłady z artykułu skompilowały się bez problemu. Niestety nie mam możliwości przetestowania kodu - nie dysponuję żadną płytką z XMega.
  • #17
    o_Tadeusz
    Poziom 15  
    khoam napisał:

    o_Tadeusz napisał:
    Może ktoś podzielić się wrażeniami z użytkowania RTOS na AVR?

    Jest osobny wątek na Forum pod tytułem "RTOS - wszystko, co chciałbyś wiedzieć i nie boisz się zapytać":
    https://www.elektroda.pl/rtvforum/topic3581141.html
    Może tam znajdziesz odpowiedź na swoje pytania dotyczące RTOS dla AVR.

    Wczoraj przeczytałem RTOS - wszystko, co chciałbyś wiedzieć i nie boisz się zapytać i boje się zapytać bo rzeczowych informacji jest tam niewiele. Większość (172 wypowiedzi) to bełkot o wyższości "świąt Bożego Narodzenia na świętami Wielkanocy".
  • #18
    khoam
    Poziom 33  
    o_Tadeusz napisał:
    co oznacza, że gwarantowany czas kolejnych zadziałań tasku może wynosić 15ms i tyle samo czasu taks może się wykonywać. Nie da się tego zmniejszyć do 1ms?

    Nie da się. W tej implementacji FreeRTOS dla AVR, tiki są generowane przez przerwania WD - ich interwał można więc ustawiać w zakresie od 15 ms do 500 ms, co czyni ten RTOS (w moim przekonaniu) praktycznie bezużytecznym, ze względu na rozdzielczość timeout-ów.
  • #19
    o_Tadeusz
    Poziom 15  
    khoam napisał:
    W tej implementacji FreeRTOS dla AVR, tiki są generowane przez przerwania WD

    Chore.
    khoam napisał:
    co czyni ten RTOS (w moim przekonaniu) praktycznie bezużytecznym

    Według mnie też.
  • #20
    Janusz_kk
    Poziom 21  
    khoam napisał:
    Nie da się. W tej implementacji FreeRTOS dla AVR, tiki są generowane przez przerwania WD - ich interwał można więc ustawiać w zakresie od 15 ms do 500 ms, co czyni ten RTOS (w moim przekonaniu) praktycznie bezużytecznym, ze względu na rozdzielczość timeout-ów.

    Pobrałem najnowszą wersjębo zainteresowało mnie wykorzystanie wd do przełączania zadań ale w katalogu
    ..\FreeRTOS\FreeRTOSv10.2.1\FreeRTOS\Source\portable\GCC\ATMega323\
    znalazłem taką ciekawostkę:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Z tego wynika że on ustawia timer1 do obsługi zegarów systemowych.
  • #21
    o_Tadeusz
    Poziom 15  
    Janusz_kk napisał:
    Z tego wynika że on ustawia timer1 do obsługi zegarów systemowych.

    Szkoda timera1 do tego celu. Większość AVR ma niewiele 16 bitowych timerów jak timer1 (prawie zawsze to timery nieparzyste). Gdy timery są 4 to do wykorzystania będzie tylko jeden 16bit, bo timer1 zajmuje RTOS.
  • #22
    khoam
    Poziom 33  
    Janusz_kk napisał:
    Z tego wynika że on ustawia timer1 do obsługi zegarów systemowych.

    To prawda, jest taka opcja, ale nie jest to domyślne ustawienie, właśnie ze względu na "utylizację" Timer1.
    Dużo ciekawiej wygląda zużycie pamięci RAM w mega328 dla pierwszego przykładu w artykule (dwa proste zadania) - jest to mnie więcej 3:1 tzn. 3 razy więcej RAM pożre wersja z tym FreeRTOS.
  • #23
    o_Tadeusz
    Poziom 15  
    khoam napisał:
    Dużo ciekawiej wygląda zużycie pamięci RAM w mega328 dla pierwszego przykładu w artykule (dwa proste zadania) - jest to mnie więcej 3:1 tzn. 3 razy więcej RAM pożre wersja z tym FreeRTOS.

    Poczytałem o RTOS i na 2kB RAM nie ma to sensu chyba, że do migania diodą ale wtedy RTOS nie jest potrzebny.
  • #24
    Janusz_kk
    Poziom 21  
    khoam napisał:
    To prawda, jest taka opcja, ale nie jest to domyślne ustawienie,

    Skoro tak to pokaż w kodzie gdzie ten WD jest ustawiany i przerwanie od niego, bo ja nie znalazłem.
  • #25
    khoam
    Poziom 33  
    Janusz_kk napisał:
    Skoro tak to pokaż w kodzie gdzie ten WD jest ustawiany i przerwanie od niego, bo ja nie znalazłem.

    Odnoszę się do kodu ze strony https://github.com/feilipu/Arduino_FreeRTOS_Library
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Dalsze dyskusje na temat FreeRTOS na AVR proszę kontynuować w wydzielonym wątku:
    https://www.elektroda.pl/rtvforum/topic3602562.html