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

Kilka pytan o FreeRTOSa...

15 Kwi 2010 12:46 2809 16
  • Poziom 12  
    Witam,
    po dłuższych analizach zdecydowałem się na freertos'a ...
    Jednakże jestem jeszcze zielony w temacie rtosów przeszukałem trochę polskich zasobów na jego temat. Jednak stwierdzam, że w większości przypadków są to jakieś akademickie regułki których pewnie nie rozumie ten kto je wymyślił :(
    Na stronie FreeRtos'a jedyny przejrzysty manual to pewnie ten za który trzeba zapłacic 35$.
    Czy może mi ktoś na chłopski rozum wytłumaczyć czym sie róznią taski od Co-routines.
    Na jakiej zasadzie działa semafor.
  • Sklep ElwronSklep Elwron
  • Poziom 33  
    Jeśli chcesz dobrze poznać tego rtos, kup sobie manuala, ja kupiłem j jestem bardzo zadowolony z niego. Na razie co routines się nie zajmuj, działają podobnie jak taski, tylko jest różnica w przydzielanej pamięci, z tego co pamiętam;) Jak zrozumiesz działanie tasków to z co routines nie będziesz miał problemów. Semafor, jest to zmienna określająca czy wydarzyło się jakieś przerwanie, potem w tasku wykonujesz kod.
  • Poziom 12  
    Chce zrealizować poniższe zagadnienie:
    układ RTC generuje przerwanie co 1 sek, w przerwaniu dokonam odczytu czasu/daty.
    Problem jest w tym, że dane te mogą być akurat używane w timerach.
    Jak realizować takie coś, ze system nie skoczy do przerwania dopóki timer korzystający z tych danych nie skończy pracy.
    Jak wogóle realizować takie coś, że np. dane; struktura jest modyfikowana przez kilka timerów.
  • Moderator Mikrokontrolery Projektowanie
    To skorzystaj z mutexów, ten RTOS je ma? Albo blokuj przerwania na czas odczytu zmiennej zawierającej datę i czas. Czyli blokujesz przerwania, przepisujesz datę i czas do zmiennej tymczasowej na której dalej działasz, odblokowywujesz przerwania.
  • Sklep ElwronSklep Elwron
  • Poziom 12  
    tmf napisał:
    To skorzystaj z mutexów, ten RTOS je ma? Albo blokuj przerwania na czas odczytu zmiennej zawierającej datę i czas. Czyli blokujesz przerwania, przepisujesz datę i czas do zmiennej tymczasowej na której dalej działasz, odblokowywujesz przerwania.

    takie rozwiązania to już mi kilka razy przeleciały przez głowę. Ja w zamyśle chcę maksymalnie wykorzystać mechanizmy tego RTOSa.
    W jakimś RTOSie są funkcje które blokują wykonywanie timerów, gdy zostanie wygenerowane przerwanie. Pozawalają tylko na dokończenie tego który trwał w trakcie przerwania... pytanie czy w freeRtos tez takie cos jest. Czy trzeba robić to recznie.
    Liczę na odpowiedz osób które są w nim dobrze zaznajomione...
  • Specjalista - Mikrokontrolery
    Każdy rtos ma mechanizmy blokujące inne taski przy dostępie do współdzielonych danych lub przy wykonywaniu czasowo krytycznych sekcji programu. FreeRTOS też takie posiada, oprócz mutexów i semaforów sa jeszcze:

    Code:
    taskENTER_CRITICAL()
    
    taskEXIT_CRITICAL()

    taskDISABLE_INTERRUPTS()
    taskENABLE_INTERRUPTS()
  • Poziom 21  
    Jak koledzy rozwiązują tego rodzaju problem:
    przykład:

    Funkcja która obsługuje SPI na czas jej wykonywania jest chroniona mutex'em
    Code:
    void AccessToSPI()
    
    {
       xSemaphoreTake( SPI_Mutex, portMAX_DELAY );   /*--access to SPI resource is disabled--*/
    ....
    *a
    ....
       xSemaphoreGive( SPI_Mutex );/*--access to SPI resource is ebabled again--*/

    }


    Urządzenie sterowane A poprzez interfejs SPI zgłasza przerwanie. Obsługa tego przerwania (skasowanie flag przerwań itp.) wymaga wpisania poprzez SPI jakiś komend.
    I teraz przypadek:
    Jeden z tasków używa funkcji AccessToSPI() aby wysłać daną do urządzenia B i jest w punkcie *a. W tym momencie przychodzi przerwania od urządzenia A które aby obsłużyć należy wysłać przy pomocy AccessToSPI() komende - jednak mutex chroni dostęp do tej funkcji stąd skasowanie flag przerwań jest niemożliwe i program będzie "wisał" w przerwaniu.
    W jaki sposób robi się to optymalnie?
  • Specjalista - Mikrokontrolery
    Obsługa SPI tylko i wyłącznie w przerwaniu od SPI i tylko dla celów drivera do SPI, a reszta zadań na SPI do kolejki i realizowana poprzez driver SPI napisany pod kątem obsługi kolejki zadań na SPI.
  • Poziom 21  
    Z założenia nie korzystam z przerwań od SPI - wszystko się sprawdzało jesli nie korzystałem z systemu op. Dzięki za podpowiedz - spróbuje jeszcze poszukać gotowych sterowników SPI pod freertosa .
  • Poziom 21  
    Przeglądałem rozwiązanie obsługi SPI pod Freertos z demo, ale z tego co widzę wszystkie opierają się o pooling.
    //---
    U mnie wygląda to w zasadzie podobnie, tyle że z użyciem kolejkowania
    Code:
    void prvSPI_GatekeeperTask(void *pvParameters)
    
    {
       _SPI_Params CurrentStructSPI;
       for(;;)
       {
          xQueueReceive( xSPI_Queue, &CurrentStructSPI, portMAX_DELAY );
          xSPI_ExecuteTransaction(CurrentStructSPI);
       }
    }

    jednak tu pozostaje kwestia priorytetu dla prvSPI_GatekeeperTask - który może zostać zablokowany na długi czas (no chyba żeby przydzielić mu configMAX_PRIORITIES ). Ale i tak nie sprawdzi się w takiej sytuacji gdy w przerwaniu np. INT0 należy wysłać komendę do zewnętrznego układu celem skasowania flagi która wywołała przerwanie INT0 - ale i to da sie obejść - czasowa dezaktywacja przerwania INT0 po czym natychmiast - z wykorzystaniem przełączenia kontekstu ) - jest to jakieś rozwiązanie, ale w kolejce mogą się znajdować inne zadania które przedłużą czas dezaktywacji przerwania.
    //---
    michalko12 napisał:
    Obsługa SPI tylko i wyłącznie w przerwaniu od SPI i tylko dla celów drivera do SPI, a reszta zadań na SPI do kolejki i realizowana poprzez driver SPI napisany pod kątem obsługi kolejki zadań na SPI.


    Mógłby kolega trochę jaśniej..
  • Specjalista - Mikrokontrolery
    Wszystko można jakoś obejść...

    Przykładowo:
    Driver powinien być taskiem z wysokim priorytetem blokowanym semaforem na czas transmisji lub usypianym gdy brak jest zadań na spi.
    Tworzysz kilka funkcji które są callbackami dla drivera i wykonują odpowiednie transakcje na spi. Każdą taka funkcję trzeba zarejestrować w driverze z priorytetem jako parametr. Funkcje są rejestrowane w tablicy którą driver przegląda od najwyższego priorytetu czyli np od początku do końca. Gdy natrafi na jakieś aktywne zadanie kopiuje sobie wskaźnik do tej funkcji do tymczasowej zmiennej i zeruje stan aktywności tego zadania w tablicy. Za każdym razem gdy tylko driver jest wywoływany sprawdza czy kopia != NULL i w razie czego wywołuje funkcję, jeśli kopia == NULL driver przechodzi do przeszukania tablicy z zadaniami.
    Tworzysz funkcję która jest interfejsem między aplikacją a driverem powodującą ustawienia danego zadania aktywnym i przy okazji wybudzającą driver. Funkcja operująca na SPI musi po zakończeniu zasygnalizować driverowi że ukończyła operację na SPI i żeby ten wyczyścił kopię wskaźnika i przeszukał tablicę w celu znalezienia innych zadań.

    W tym przerwaniu od INT0 powinieneś tylko wywołac funkcje aktywującą dane zadanie i ewentualnie wywołać scheduler żeby przeszeregował taski.

    I na przyszłość, jak masz jakiś problem na którego nie znalazłeś rozwiązania to zakładaj w oddzielnym wątku.
  • Poziom 17  
    Ojoj, wizja tego drivera mnie przestraszyła. Bardzo zawiła i wymagająca rejestrowania funkcji na okoliczność wykonania zadania.
    To na pewno działa bo pewnie coś takiego masz, ale zastanów się czy nie lepsze byłoby coś takiego.
    - driver ma normalne API; pośród innych, jest funkcja spiSendMessage(spi_message_t * message_ptr);
    - struktura typu 'spi_message_t' posiada oczywiście bufor, wartość oznaczającą ilość bajtów w buforze i np. priorytet
    - teraz każdy może zawołać taką funkcję API bez rejestrowania czegokolwiek; wystarczy tylko zbudować taką strukturę i przekazać ją jako parametr
    - driver SPI kopiuję tę strukturę do kolejki wykorzystując mechanizm Queue FreeRtosa - na tym etapie można np. uwzględnić priorytety
    - jeśli długość kolejki jest niezerowa to driver zajmuje się wiadomościami jedna po drugiej

    Efekt podobny, ale w moim przykładzie nie tworzysz funkcji, które potem rejestrujesz a struktury z jasno opisanymi polami.

    Ale to tylko przykład/wizja. Pewnie są jeszcze lepsze opcje.
  • Poziom 21  
    Sterownik napisałem wg tego schematu:
    Kilka pytan o FreeRTOSa...
    aktualnie testuje. Uwagi mile widziane.
  • Specjalista - Mikrokontrolery
    Każdy problem można rozwiązać na kilka sposobów, ty wybrałeś jakiś sposób, ten opis jest niezbyt jasny, za mało szczegółów, ja widziałem to trochę inaczej, ale jeśli testujesz to znaczy, że już coś działa. Napisanie programu pod RTOSa naprawdę jest trudną sztuką. W przypadku SPI nie ma problemu gdy na magistrali znajduje się tylko jedno urządzenie, gorzej jak jest już ich kilka i w dodatku każde ma inne formaty, prędkości itp. To co podał marmur99 nie bardzo nadaje się właśnie do takiego przypadku gdzie na SPI jest kilka urządzeń i każde na swoje wymagania.
  • Poziom 35  
    Napisanie softa pod RTOS nie jest niczym trudnym. Naginałem już freeRTOSa do zadań dla niego nie przeznaczonych - kompilowałem funkcje w trybie position independent i mogłem dynamicznie "instalować aplikacje" i je uruchamiać jak i killować, prawie jak pod prawidziwym OSem :)

    Jeśli SPI obsługuje kilka urządzeń, to powinno się stworzyć oddzielny task zajmujący się arbitrowaniem dostępu do spi pomiędzy kilkoma innymi taskami. Najlepiej napisać na to typedef struct dla 'transakcji', i te transakcje wrzucać w kolejkę, ew. stos lub listę, w zależności od algorytmu który obsługuje arbitraż i priorytety.
    Prawidziwy problem powstaje dopiero wtedy, gdy zdarzenie z sprzętowego przerwania wymaga in-place dostępu do SPI (np. obsluga expandera lub modulu komunikacyjnego), gdy istnieje wątek pracujący na SPI. Wtedy powinno się albo używać linii hold, lub, w przypadku jej braku, stosować zewn. obwody logiczne bramkujące zegar bez zmiany stanu linii CS. O kontekst dostępu na SPI z poziomu wątka martwi się sam kernel, ale musi zostać zaimplementowany mechanizm wstrzymujący trwającą transakcję z bierzącym peryferium gdy istnieje w sprzętowym przerwaniu program, który wymaga dostępu do spi in-place.

    Jeśli wątek arbitrujący dostęp do SPI wykorzystuje DMA, to DMA musi zostać wstrzymane na czas 'wstrzykniętego dostępu', a następnie, trzeba poczekać na wysunięcie/wsunięcie ostatniego bitu bierzącej transakcji SPI , i transakcję wstrzymać, bramkując zegar lub wykorzystując linię HOLD. Niestety, HOLD jest rzadko dostępny - mają go praktycznie tylko pamięci (ale juz NIE karty pamięci np. uSD).
  • Poziom 12  
    Witam,
    koncepcji padło kilka, ktoś zrealizował coś konkretnego?
  • Poziom 21  
    Tak - zaimplementowałem tranzakcję SPI wg podanego przeze mnie 'schematu'