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

[stm32][FreeRTOS] - Pytania odnośnie kolejki.

djmdp 15 Sty 2014 10:29 2109 18
  • #1 15 Sty 2014 10:29
    djmdp
    Poziom 16  

    Witam, Z freeRTOSem dopiero się zapoznaje, mam kilka pytań odnośnie kolejek, bazuje na tutorialu twórcy tego systemu, lecz nie do końca rozumiem niuanse przez język angielski.
    Mam przykładowo 2 zadania, jedno wysyła dane do kolejki, drugie ma je odbierać. Odbiornikiem jest vTaskLCD(); który ma wysłać dane do wyświetlacza, natomiast vSenderLCD(); wysyła dane do wyświetlacza przez kolejkę. Interesuje mnie, jak ustalić priorytety tych zadań, oraz na jakich zasadach/ w jakiej kolejności powinno to być zrobione. Przykład:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Tutaj zakładam, że LCD_Screen jest już zainicjalizowane,
    pytanie nr.1 - czy 3ci parametr funkcji xQueueReceive lub pochodnej, mówi "zablokuj to zadanie na 10 ticków zegara"?,
    pytanie nr.2 - czy jeśli funkcja xQueueSend(xLCDQueue, (void *) &dane, (portTickType)0); zostanie zapełniona (1-elementem) to automatycznie zadanie vSenderLCD() zostanie wywłaszczony przez vTaskLCD()?
    pytanie nr.3 - Czy taskYIELD(); jest to zablokowanie danego zadania?

    Krótko mówiąc mój plan był taki - vSenderLCD wysyła do kolejki pierwszy wskaźnik &CONNECTING, po czym blokuje się (czas określony na 0) - przełącza na zadanie vTaskLCD(); gdy dane z kolejki zostaną odebrane, wyświetli się pierwsza linia lcd, zadanie się zablokuje taskYIELD(); ponownie uruchomi się vSenderLCD(); i prześle kolejny wskaźnik &ip_str, po czym zablokuje się robiąc miejsce vTaskLCD itd... tym sposobem na przemian są aktualizowane obie linie 2 wierszowego wyświetlacza LCD. Może ktoś zweryfikować moje informacje na temat kolejek, poprawić, ewentualnie dodać swój pomysł na podane proste zagadnienie? priorytet zadania vTaskLCD jest wyższy niż vSenderLCD z wiadomych przyczyn. Mechanizm źle działa w ten sposób, że linie wyświetlane są nie według kolejności którą zadałem, stąd ten post i prośba o rozszerzenie informacji.

    0 18
  • #2 15 Sty 2014 11:09
    BlueDraco
    Specjalista - Mikrokontrolery

    I pomyśleć, że gdyby dobrze napisać obsługę LCD, nie byłby potrzebny żaden "TaskLCD", bo program, które chce pisać dane mógłby to zrobić natychmiast i bez oczekiwania...

    0
  • #3 15 Sty 2014 11:11
    djmdp
    Poziom 16  

    Luuudzie, no oczywiście, że mógłbym odrazu pisać dane do wyświetlacza, lecz akurat tutaj chodzi mi o zapoznanie się z mechanizmem kolejek a zagadnienie wyświetlacza jest dobrą formą do przetrenowania i zrozumienia tego mechanizmu.
    Poza tym, osobiście wolę kontrolować HW wyświetlacza stale w jednym miejscu.

    0
  • #4 15 Sty 2014 11:13
    grko
    Poziom 32  

    I musiałby wyłączyć przerwania albo zatrzymać schedulera.

    Edit: task od LCD lepiej wyglada tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #5 15 Sty 2014 11:18
    BlueDraco
    Specjalista - Mikrokontrolery

    Napisałem "bez oczekiwania", a więc bez wyłączania przerwań ani zatrzymywania schedulera więcej szczegółów w marcu, chociaż rozwiązania podobne do mojego pałętają się po Internecie już od jakiegoś czasu ;).

    0
  • #6 15 Sty 2014 11:19
    djmdp
    Poziom 16  

    Zamierzacie pomóc czy wywyższać się kto ma lepsze rozwiązania?

    0
  • #8 15 Sty 2014 11:29
    Freddie Chopin
    Specjalista - Mikrokontrolery

    djmdp napisał:
    pytanie nr.1 - czy 3ci parametr funkcji xQueueReceive lub pochodnej, mówi "zablokuj to zadanie na 10 ticków zegara"?,

    Nie do końca. Po pierwsze chodzi o _MAX_ 10 ticków, bo równie dobrze może to być 0. Parametr ten mówi ile funkcja będzie czekać na wolne miejsce w kolejce. Jeśli kolejka jest pusta to nie ma na co czekać...

    Cytat:
    pytanie nr.2 - czy jeśli funkcja xQueueSend(xLCDQueue, (void *) &dane, (portTickType)0); zostanie zapełniona (1-elementem) to automatycznie zadanie vSenderLCD() zostanie wywłaszczony przez vTaskLCD()?

    Jeśli ten drugi jest aktualnie zablokowany na odbieraniu z tejże kolejki i przy okazji ma wyższy priorytet to tak.

    Cytat:
    pytanie nr.3 - Czy taskYIELD(); jest to zablokowanie danego zadania?

    Nie.

    4\/3!!

    0
  • #9 15 Sty 2014 11:30
    djmdp
    Poziom 16  

    @Grzegorz Kostka -> Dobra, teraz znacznie lepiej, czyli taki mechanizm przesyłania działa następująco: xQueueSend wysyła adres do kolejki i jeśli jego parametr xTicksToWait == 0 oznacza, że automatycznie po wykonaniu tej funkcji zadanie o wyższym priorytecie (w tym przykładzie vTaskLCD) wywłaszczy zadanie vSenderLCD i opróżni kolejkę zwracając pdPASS co pozwala na wykonanie funkcji wysłania danych do LCD w moim przypadku i zablokowanie zadania vTaskLCD do czasu kiedy kolejka będzie znów pełna, dobrze zrozumiałem?

    0
  • #10 15 Sty 2014 11:31
    Freddie Chopin
    Specjalista - Mikrokontrolery
  • #11 15 Sty 2014 11:38
    djmdp
    Poziom 16  

    Po poprawkach już wydaje się działać:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Kod: c
    Zaloguj się, aby zobaczyć kod

    I teraz to działa jak powinno - a przynajmniej widzę, że z dobrym wynikiem, linie na lcd są wyświetlane w kolejności którą zadałem, więc zadania muszą się dobrze przełączać, czy są jakieś lepsze metody na przesyłanie danych do wyświetlacza między zadaniami?

    0
  • #12 15 Sty 2014 11:43
    grko
    Poziom 32  

    Jak w xQueueSend ustawisz xTicksToWait na 0 oznacza to tylko, że funkcja nie będzie blokowała tego zadania. W twoim przypadku funkcja xQueueSend może zwrócić pdFALSE w przypadku jak kolejka będzie zapełniona. Jak dasz xTicksToWait portMAX_DELAY to masz pewność że się wyśle. Oczywiście nie będziesz miał tego problemu gdy zadanie od LCD będzie miało wyższy priorytet od zadania w którym robisz xQueueSend.

    Jak nie chcesz mieć zadania od LCD to możesz dostęp do wyświetlacza realizować przez:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Pamiętaj, że mutexów nie można używać w przerwaniu.

    0
  • #13 15 Sty 2014 11:51
    djmdp
    Poziom 16  

    No dokładnie, ale przede wszystkim na wyższym priorytecie vTaskLCD oparłem swoją konstrukcję. Czy jest jakiś ciekawszy sposób przesyłania danych do LCD? Sprawniejszy?

    0
  • #14 15 Sty 2014 12:11
    BlueDraco
    Specjalista - Mikrokontrolery

    Jest. Jak napisałem wyżej - poszperaj w sieci, a ja moje rozwiązanie pokażę w marcu.
    Co więcej, typowy sposób obsługi z interfejsem dwukierunkowym i badaniem bitu BUSY nie jest dobry, bo, gdy uważnie przeczytamy dokumentację HD44780, okaże się, że wartość 0 bitu BUSY nie oznacza, że sterownik jest gotowy. ;)

    0
  • #15 15 Sty 2014 12:17
    ginar
    Poziom 21  

    Mozesz podejrzyc to:
    https://obrazki.elektroda.pl/7272988100_1305471519.jpg
    Kiedys napisałem taki 'driver' na SPI i UART pod FreeRtosa.
    Ten schemat przedstawia jego pierwszą wersje. Opis nie jest najlepszej 'jakosci' ale można wysnioskować jak to działa.
    Ogólnie wiele tasków może chciec wysłac dane do LCD. Ich życzenia są kolejkowane zgodnie z przydzielonym im priorytetem. Na końcu task 'driverLCD' może przegladac kolejke i wybierac kolejno zgodnie z przypisanym priorytetem

    0
  • #16 15 Sty 2014 12:36
    djmdp
    Poziom 16  

    @Blue Draco - Szczerze powiedziawszy, nie wgłębiałem się zbyt w obsługę HD44780, jedyne co modyfikowałem, to pozbycie się R/W i wprowadzenia odpowiedniego timingu, jakby to powiedzieć, sprzęt który zdziałałem testuje się lekko mówiąc w setkach sztuk i nigdy nie napotkałem na problem z tą obsługą (nie na freeRTOS bo z tym dopiero zaczynam). Oczywiście LCD jest odświeżany co stały czas.
    Jeszcze jedno - jak określę czas po jakim zadanie odbiorcze zostanie odblokowane na xTicksToWait = 100ms, to oznacza, że po 100ms, zadanie wybudzi się na czas sprawdzenia czy kolejka jest pełna i znów uśpi się na kolejne 100ms, czy pozostanie w normalnym obiegu schedulera (będzie obsługiwane co czas przełączania schedulera)?

    0
  • #17 16 Sty 2014 19:15
    dziechu
    Poziom 27  

    djmdp napisał:
    to pozbycie się R/W i wprowadzenia odpowiedniego timingu

    A jakiego timingu? Dla każdej serii dobierany doświadczalnie? Albo z góry założony z takim zapasem że hoho:)

    Dodano po 3 [minuty]:

    BlueDraco napisał:
    Co więcej, typowy sposób obsługi z interfejsem dwukierunkowym i badaniem bitu BUSY nie jest dobry, bo, gdy uważnie przeczytamy dokumentację HD44780, okaże się, że wartość 0 bitu BUSY nie oznacza, że sterownik jest gotowy

    A jaki jest dobry? 0 na BUSY nie oznacza że sterownik jest gotowy... ok, ale wykorzystuje się to tak, że gdy 0 na BUSY - wysyła się dane/komendy do wyświetlacza i jest ok.

    0
  • #18 16 Sty 2014 19:37
    BlueDraco
    Specjalista - Mikrokontrolery

    Jeśli procesor nie jest zbyt szybki (np. AVR), to jest ok. Przy szybkim już nie.
    Ponieważ bit BUSY nie niesie informacji o gotowości, a jego sprawdzanie zajmuje dodatkowo czas - lepiej jest użyć interfejsu jedokierunkowego.

    0
  • #19 16 Sty 2014 20:19
    dziechu
    Poziom 27  

    Nie bardzo rozumiem. Wszystkie procedury obsługi HD44780 z badaniem bitu busy, traktują go jako informację że można wysłać następne dane, np. wysylam polecenie LCD_Clear i natychmiast po nim wysyłam jakiś komunika to wyświetlenia. Pierwsze znaki nie zostaną wyświetlone, ponieważ kontroler jest jeszcze zajęty, albo wysyłam komunikat w postaci serii znaków jeden po drugim natychmiast - nie zostaną prawidłowo wyświetlone. Muszę albo czekać na bit busy, albo doświadczalnie ustalić czas po którym mogę wysłać następny znak czy polecenie. Im szybszy kontroler tym gorzej, wysylając dane jedne za drugimi bez przerw i sprawdzania busy. Z kolei stały czas opóźnienia zależy od typu kontrolera, producenta itd. i dla każdego trzeba dobrać inny, albo dać z góry bardzo duży. Chyba że w momencie inicjalizacji zrobi się jakąś procedurę sprawdzającą czas zajętości a potem tylko ten czas się wstawia.

    Dodano po 4 [minuty]:

    W mojej dokumentacji jest to tak:
    "When the busy flag is 1, the HD44780U is in the internal operation mode, and the next instruction will not
    be accepted. When RS = 0 and R/W = 1 (Table 1), the busy flag is output to DB7. The next instruction
    must be written after ensuring that the busy flag is 0."
    I po mojemu jest to bit informujący o gotowości.

    0