Skocz do zawartości

Czym są: RTOS, wielozadaniowość, taski?


SOYER

Pomocna odpowiedź

Jak się programowało gierki na C16 gdzie trzeba było upchać cały kod ze zmiennymi w 10 kB to 320k człowiek uważa za komfortową wartość 🙂

  • Lubię! 1
Link do komentarza
Share on other sites

Do czasu przesiadki z 8051 i AVR na STM32 i nowsze 64kB to było pamięci flash w większych prockach

Link do komentarza
Share on other sites

(edytowany)

Jest pewna rzecz której nie rozumiem w RTOS: w Mega uproszczonym przypadku mam skonfigurowany timer którego callabck jest wywoływany co sekundę, chcę w tej funkcji zwrotnej (od timera) dekrementować zmienną globalną na przykład sekundnik

static TimerHandle_t xtimeout_timer;
int s = 0;

xtimeout_timer = xTimerCreate("timeout_tmr",100,pdTRUE, 0,vtimeout_timer_clb);  
xTimerStart(xtimeout_timer,0);

później w funkcji zwrotnej

static void vtimeout_timer_clb(TimerHandle_t xTimer)
{
s--;
}

 następnie jest funkcja którą chcę przypisać do zmiennej wartość (jest to funkcja obsługiwana z espnow)

// Callback odbioru danych
 void esp_now_recv_cb(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len) {
	
  static espnowdata_t espdata;
  memcpy(&espdata, data, data_len);
  s = espdata.timeout;	
 } 

i w main task chciałbym printować zmienną s

      while(1)
    {
        ESP_LOGI(TAG, "Timeout %d (sek)", s);
        vTaskDelay(10);
    }    

I teraz zasadnicze pytanie, czy użycie w tym kontekście zmiennej globalnej jest uzasadnione? Jak to prawidłowo wykonać ponieważ nie chcę blokować głównej pętli oczekiwaniem na dane z kolejki lub powiadomienia (direct to task notifications) a nie wiem czy semafor byłby bardziej odpowiedni? To jest taka rzecz której nie do końca łapię w freeRTOS i tu jeśli ktoś ma wiedzę i ochotę to chciałbym aby przybliżył mi ten temat.

Dodam jeszcze że najważniejsze jest aby zmienna 's' została zapisana kiedy "przyleci" ramka danych z espnow. Program nie może tego przeoczyć

 

Edytowano przez _LM_
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Tak, później mi się przypomniało że pętla z kolejką może się również non stop kręcić. Dzięki, przetestuję sekcje krytyczną

Link do komentarza
Share on other sites

(edytowany)

Ok, ja wiem że to nie interfejs googla ale znalazłem ciekawą dyskusję nt: sekcji krytycznej oraz mutexów. Także zostawiam, może ktoś skorzysta. https://forums.freertos.org/t/how-to-choose-a-critical-section-protecton-approach-taskenter-critical-or-vtasksuspendall-or-mutex/9500

Jeszcze raz dzięki @ethanakza naprowadzenie 

Edytowano przez _LM_
Poprawiłem link
Link do komentarza
Share on other sites

3 godziny temu, _LM_ napisał:

ja wiem że to nie interfejs googla

No, to nie o to chodzi z interfejsem do googla 🙂 Ciekawy post na tym forum.

Dodam jeszcze, że wersja multicore FreeRTOS (czyli to co siedzi w ESP32) doskonale daje sobie radę z mutexami na dwóch rdzeniach. Chciałem apisać więcej, ale w sumie wszystko jest w wątku.

Dodam jeszcze tylko, że w przypadku jeśli zmienna jest rozmiaru atomowego to można zaryzykować niewstawianie critical section... ale ja nie lubię ryzykanctwa, bo coś się potem może zmienić.

  • Lubię! 1
Link do komentarza
Share on other sites

(edytowany)

Czy w takim przypadku mogę strukturę espnowdata_t wyjąć poza funkcję gdyż zawiera więcej pól potrzebnych w różnych miejscach kodu?

To budzi moją wątpliwość bo callback potrzebuje wskaźnika do pamięci gdzie dane są zapisywane. Adres struktury podczas pracy programu się nie zmieni. Czyli chyba ok? 

Edytowano przez _LM_
Link do komentarza
Share on other sites

(edytowany)
4 godziny temu, _LM_ napisał:

mogę strukturę espnowdata_t wyjąć poza funkcję

Tak by wypadało. I takie moje rozwiązanie - jeśli potrzebuję tylko ostatniego przesłanego rekordu (np. bieżący stan, bez logowania) a funkcja wykonuje się relatywnie długo:

portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;

...
espnowdata_t espdata,espdata_current;

void esp_now_recv_cb(const esp_now_recv_info_t *esp_now_info, const uint8_t *data, int data_len)
{
    portENTER_CRITICAL(&mux);
    memcpy(&espdata, data, data_len);
    portEXIT_CRITICAL(&mux);
} 

// i gdzieś w kodzie

function verylongduration()
{
    portENTER_CRITICAL(&mux);
    espdata_current = espdata;
    portEXIT_CRITICAL(&mux)

    // i teraz wszędzie używam espdata current, np.:

    ...
    printf("%s\n", espdata_current.timeout);
    ...
}

Oczywiście gdybym chciał coś logować to użyłbym kolejki, ale nie zawsze chcę, a to akurat prosty i bezpieczny przykład na utrzymanie spójności danych w zmienney espdata_current.

Edytowano przez ethanak
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Właściwie to myślałem żeby w tym przypadku użyć mutexa, tak też wynikałoby z wpisu który linkowałem, na żywo ciężko będzie wykryć która metoda jest szybsza

Link do komentarza
Share on other sites

Semafor niespecjalnie się nadaje do użycia we wszelkiego rodzaju callbackach, które mają swoje szybko zrobić i spadać a nie pozwalać na przełączenie tasku.

Link do komentarza
Share on other sites

W takim razie nie pozostaje nic jak przetestować nowe wiadomości w układzie docelowym. Choć jest jeszcze pytanie - to sobie sprawdzę osobno, czy sekcja krytyczna w układach wielordzeniowych blokuje przerwania na wszystkich alu czy tylko na tym gdzie jest uruchomiony rtos.. Dzięki @ethanak za pomoc, oddaję topik @SOYER - owi. 

Link do komentarza
Share on other sites

(edytowany)

Sekcja krytyczna nie blokuje przerwań, od tego masz funkcje isr. Poza tym co rozumiesz przez "na którym uruchomiony jest rtos"?

A @SOYER-owi nie zaszkodzi jak to przeczyta, w pewnej chwili będzie musiał się z tym zapoznać.

Edytowano przez ethanak
Link do komentarza
Share on other sites

(edytowany)
56 minut temu, ethanak napisał:

Sekcja krytyczna nie blokuje przerwań

Cytat

When using critical sections you must be aware that it affects your (worst case) interrupt response time. That means an ISR of a hardware interrupt might get delayed because all interrupts are disabled while executing code inside a critical section.
That’s the benefit of just suspending all tasks. Interrupts remain enabled and get handled by their corresponding ISRs.

Zdaję sobie sprawę że nie wszystkich bo choćby systick wciąż musi działać w tle 

56 minut temu, ethanak napisał:

Poza tym co rozumiesz przez "na którym uruchomiony jest rtos"?

Posłużę się pomocą naukową w postaci screena z menuconfig w esp idf
Code_e7ioFGQwzG.thumb.png.e546ce37efb609f0fc73f5ba7a25e7dd.png

Jest tam to pole 

Cytat

This version of FreeRTOS normally takes control of all cores of the CPU. Select this if you only want to start it on the first core. This is needed when e.g. another process needs complete control over the second core.

Dlatego stwierdzenie że RTOS jest uruchomiony na jednym rdzeniu uznaję za nieważne. Dobrze że o to dopytałeś bo bym wciąż żył w błędnym przekonaniu 🙂

Edytowano przez _LM_
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.