Skocz do zawartości

FreeRTOS na ESP32...prośba o pomoc w zrozumieniu kilku rzeczy/funkcji


Pomocna odpowiedź

(edytowany)

Jeszcze pytanko odnośnie semaforów..mam dwa taski o takim samym priorytecie które coś tam wysyłają  na serial...ustawiam czas przez jaki kod może czekać na zwolnienie semafora, i pytanie, wtedy kod czeka cały czas na zwolnienie semafora czy zaczyna wykonywać inny kod i po jakimś czasie wraca do tej funkcji w której semafor był zablokowany...(domyślam sie że ta ostatnia wersja bo to właśnie ma robić frreRTOS, ale wolę się upewnić😉)

Edytowano przez farmaceuta
(edytowany)
10 minut temu, ethanak napisał:

eee... kod zaczyna wykonywać inny kod... znaczy sie jaki inny? 

Znaczy się w sensie wykonuje sie inny task lub loop etc...a po upływie ustalonego czasu zagląda do taska i sprawdza czy semafor już wolny.. 

 

10 minut temu, ethanak napisał:

Z ciekawości: po co ustawiasz timeout?

Taki przykład akurat znalazłem...😉 Czyli jest to argument opcjonalny, no a jeśli nie ustawie czasu to mam rozumieć że frreRTOS będzie częściej sprawdzał czy semafor już wolny, tak?

Edytowano przez farmaceuta

Nic nie będzie częściej, zacznij od tego żeby zozumieć jak działaja semafory w każdym uczciwym systemie (no, może poza windowsem, bo tam jest chyba cały czas polling).

Ogólnie system dopuści do zamknięcia semafora przez jakiś task, jeśli task ktory go otworzyl na to pozwoli (tzn. nastąp[i przełączenie kontekstu). Nie wcześniej i nie później. A co dokładniejszych informacji zwróć się do dokumentacji, mi się jakoś nie chce przepisywać jej rozdziałów na forum...

  • Pomogłeś! 1
6 minut temu, ethanak napisał:

Ogólnie system dopuści do zamknięcia semafora przez jakiś task, jeśli task ktory go otworzyl na to pozwoli (tzn. nastąp[i przełączenie kontekstu). Nie wcześniej i nie później.

No coś mi tam zaczyna świtać powolutku😉 dzięki za pomoc i cierpliwość 😜 jak coś to będę denerwował i pytał dalej 😜

I już pytam😜... Mam 

SemaphoreHandle_t SerialSem;

I dalej 

if ( SeriaSem == NULL )
{
  SerialSem = xSemaphoreCreateMutex();  
  
  if ( ( SerialSem ) != NULL )
    xSemaphoreGive( ( SerialSem ) );  
}

Pytanie czy mogę odrazu stworzyć semafor podczas tworzenia zmiennej ?

SerialSem

Coś w stylu 

SemaphoreHandle_t SerialSem = xSemaphoreCreateMutex();

Czy jest to raczej błędne podejście(nie sprawdzanie czy zmienna jest NULL) (przepraszam za nazewnictwo jeśli się mylę, to początki)

Cześć @farmaceuta Ostatnio pracuję przy ESP-IDF i przez ostatni miesiąc przechodziłem podobną ścieżkę co ty. Na pewno mogę polecić Ci framework ESP-IDF bo jest naprawdę prosty. Trzeba tylko usiąść na trochę dłużej i robi się fajnie 🙂 Zaznacze że nie jestem ekspertem.

RTOS realizuje tu coś na wzór wielowątkowości. Typowo wątki współdzielą zasoby czyli mają ten sam RAM globalny, albo statyczny, a same są deklarowane na stercie. Choć nazwa parametru sugeruje że to stos, to stos taska to fragment sterty działający jak stos.

Trochę światła na ten temat rzuca plik semphr.h i komentarz do xSemaphoreCreateMutex()

 * Internally, within the FreeRTOS implementation, mutex semaphores use a block
 * of memory, in which the mutex structure is stored.  If a mutex is created
 * using xSemaphoreCreateMutex() then the required memory is automatically
 * dynamically allocated inside the xSemaphoreCreateMutex() function.  (see
 * https://www.FreeRTOS.org/a00111.html).  If a mutex is created using
 * xSemaphoreCreateMutexStatic() then the application writer must provided the
 * memory.  xSemaphoreCreateMutexStatic() therefore allows a mutex to be created
 * without using any dynamic memory allocation.
 
  * @return If the mutex was successfully created then a handle to the created
 * semaphore is returned.  If there was not enough heap to allocate the mutex
 * data structures then NULL is returned.

Oznacza że pamięć jest dynamicznie alokowana na stercie (heap), a zwracany jest handler. Jakbyś przeklikał sobie co oznacza ten handler to trafisz w końcu na strukturę ze wskaźników. Więc w zasadzie możesz zadeklarować ten handler wewnątrz funkcji. Zrób to tylko mądrze, bo jeżeli deklarujesz zmienną wewnątrz funkcji to robisz ją na stosie (tu związanym z taskiem). Jeżeli robisz return tej zmiennej to w prostym przypadku kończy się procedura obsługi funkcji na stosie, pamięć się automatycznie zwalnia i dostajesz wartość z return. Ale jeżeli zaalokujesz coś większego co operuje na adresach i zwrócisz adres a czegoś powtałego na stosie, to po wyjściu z funkcji już tego nie będzie. A zauważ że handler choć nie wygląda jak pointer to jest tak naprawdę opakowaniem (typedef) na pointer.

typedef QueueHandle_t SemaphoreHandle_t;
//...
typedef struct QueueDefinition   * QueueHandle_t;
//...
typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
    int8_t * pcHead;           /*< Points to the beginning of the queue storage area. */
    int8_t * pcWriteTo;        /*< Points to the free next place in the storage area. */

    union
    {
        QueuePointers_t xQueue;     /*< Data required exclusively when this structure is used as a queue. */
        SemaphoreData_t xSemaphore; /*< Data required exclusively when this structure is used as a semaphore. */
    } u;

Dlatego zadeklarowanie handlera globalnie, czyli na górze kodu lub jako static spowoduje że umieści się w statycznej czesci RAMu (jak niezainicjowany to chyba .bss) i masz dostęp ze wszystkich tasków.

Jak interesuje cię założenie czegoś bardziej statycznego to masz taki wariant - patrz fragment komentarza do funkcji. Może się to przydać gdy taski/mutexy mają funkcjonować przez cały czas.

Poza tym polecam Ci Espressif IDE albo platformio do takich tematów 🙂 

  • Lubię! 1
  • Pomogłeś! 1

@Gieneq zwał jak zwał, chodzi mi o to, czy pod idf znajdę wszystko to co mogę znaleźć pod Arduino.

Arduino IDE (builder czy cli) nie kompilują tego, co już mają w cache. Normalnie cache jest usuwany przy zamknięciu IDE, ale jak się trochę pogmera  tak, aby ręcznie skonstruować fqbn to można przechowywać katalogi cache i build gdzie chcesz.

Owszem, make w tym momencie wygrywa, ale builder musi po drodze znaleźć biblioteki, a to w sumie trwa najdłużej. A czas pracy linkera będzie taki sam...

  • Lubię! 1

Jeśli ktoś bardzo potrzebuje używać bibliotekę przeznaczoną dla Arduino to nic nie stoi na przeszkodzie, żeby ją dodać do projektu ESP-IDF. Prawdę mówiąc w kursie STM32L4 mieliśmy używać biblioteki graficznej z Arduino, ale pomysł w końcu upadł, chociaż sama biblioteka działała bez problemu pod STM32Cube.

  • Lubię! 1
  • Pomogłeś! 1

Dzięki Ci Wielkie @Gieneq za obszerna odpowiedź!😉 Coraz więcej mi zaczyna świtać logiki w tym wszystkim dzięki wam🙂 oczywiście się wezmę w przyszłości za esp-idf ale póki co potestuje to co się do tej pory nauczyłem w kwestii freeRTOS'a i esp32 na IDE...👍

  • Lubię! 1
  • 2 tygodnie później...

Ze swojej strony mogę polecić żeby uczyć się FreeRTOSa używając STM32 i generując kod w Cube. W Cube można wyklikać konkretne taski czy wątki dzięki czemu nie trzeba mieć od razu tak dużej wiedzy żeby cokolwiek uruchomić.

  • Lubię! 2

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...