logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

AVR-GCC: Jak zorganizować transmisję przez modem bez blokowania funkcji main?

robiw 16 Cze 2014 13:23 1476 12
REKLAMA
  • #1 13712530
    robiw
    Poziom 26  
    Witam Kolegów,
    Mam pewien modem, za pomocą którego przesyłam pakiety danych. Do tego celu służy prosta funkcja, która z uwagi na oczekiwanie na rezultat transmisji blokuje mi funkcje main, tym bardziej, że funkcja ta może być wywoływana w różnych miejscach programu głównego. Zastanawiam się jak inaczej zorganizować tą transmisję, by nie blokować funkcji main a jednocześnie zapewnić odpowiednią obsługę transmisji (np. rezultat jednej transmisji jeszcze nie przyszedł (a może to trwać nawet 1s, gdy modem będzie próbował wysyłać dane) a ja chcę już zapoczątkować następną). Kolejki, semafory? Wykorzystać INT? Zarys funkcji poniżej:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Z góry serdecznie dziękuję... robiw
  • REKLAMA
  • #2 13714822
    Tom RealTime
    Poziom 11  
    nie pakując się w systemy z przełączanymi zadaniami, to nie wiem czy nie lepiej zrobić to na przerwaniu.
  • #3 13715027
    Phaeton
    Poziom 19  
    Jesli transmisja ma być nieblokująca to polling odpada. Jak rozumiem można podłączyć modem tak, że po wykonaniu rozkazu dostaniemy przerwanie (również gdy coś się nie powiedzie). Wtedy wg. mnie trzeba zrobić bufor (np. cyrkularny) do którego będzie wpisywać pakiety główny program i inicjowac transmisję. Przerwanie będzie sprawdzało status, zdejmowało wysłany pakiet z bufora, lub ewentualnie ponawiało transmisje na busy, czy sygnalizowało błąd. Po udanej transmisji gdy bufor nie jest pusty przerwanie od razu powinno rozpocząć następną transmisję. Oczywiście dostęp do bufora musi być synchronizowany. W ten sposób główny program wrzuca cos do bufora triggeruje transmisje i wraca do własnych zajęć.
  • #4 13715083
    BlueDraco
    Specjalista - Mikrokontrolery
    Jeśli nie RTOS, to automat, czyli po "polsku" - "state machine" (maszyna stanów - brrr...).
  • REKLAMA
  • #5 13715517
    robiw
    Poziom 26  
    To nie jest chyba najlepszy pomysł. Modem ten może sygnalizować zakończenie transmisji poprzez przerwanie zewnętrzne, jednak wiele funkcji z których wywoływana jest ta funkcja transmisji oczekuje statusu wykonania właśnie tej operacji transmisji. Żeby było jeszcze bardziej skomplikowanie to modem sygnalizuje przerwaniem zewnętrznym nadejscie wiadomości co wykorzystuje właśnie aplikacja. W tym przerwaniu, przy użyciu I2C odczytuje dane, które nadeszły. Zgłaszanie statusów transmisji zostało wyłączone z tego przerwania by nie komplikować sprawy. Zastanawiam się jak to wszystko sprytnie rozwiązać. robiw

    Dodano po 23 [minuty]:

    Sprawa wydaje mi się o tyle niełatwa, że funkcja transmisji wykorzystywana jest w kilku funkcjach aplikacji i od rezultatu jej wykonania zależą na przykład decyzję podejmowane w innych funkcjach. Na domiar złego, wysyłane są różne rozkazy z różna liczba towarzyszących danych. Mogę włączyć zgłaszanie przez modem statusów operacji transmisji za pomocą przerwania tylko wtedy musiałbym zmodyfikować sama funkcję przerwania bo ona wywoływana jest również wtedy, gdy modem otrzyma dane (niezależnie od statusów). Należałoby jednak powiązać jakoś otrzymywane statusy z wysyłanymi rozkazami i towarzyszącymi im danymi. Nie mam w tej chwili, co prawda, pewności czy modem może odebrać jakaś wiadomość zanim nie zgłosi statusu operacji transmisji (a może to trwać nawet 1s) bo jest typu half-duplex, choć to raczej nie powinno mieć znaczenia. Inną, jeszcze bardziej komplikująca właściwością jest to (widać to w zarysie funkcji transmisji), że po pierwszym statusie mówiącym o zajętości magistrali, funkcja transmisji zmienia ustawienia modemu w zakresie wykrywania kolizji i próbuje jeszcze raz i jeszcze raz (w tej chwili 5-krotnie), aż do odczytu statusu niepowodzenia transmisji. Taki schemat jej działania to jeszcze większe wyzwanie dla procedury wysyłającej dane w tle...robiw

    Dodano po 4 [minuty]:

    BlueDraco napisał:
    Jeśli nie RTOS, to automat, czyli po "polsku" - "state machine" (maszyna stanów - brrr...).


    RTOS odpada. Jak widziałbys rozwiązanie tego typu przy pomocy maszyny stanów? Jaki mechanizm wykorzystać w tym przypadku by nie zatrzymywać main? Cykliczne przerwanie timera? Jak je powiązać z przerwaniem odbierania statusów. Hmm...robiw

    Dodano po 2 [godziny] 6 [minuty]:

    Zastanawiam się nad rozwiązanie z buforem kołowym. Skonfiguruję modem tak, by wyzwalał przerwanie nie tylko w przypadku otrzymania danych, lecz również w przypadku gotowości statusu transmisji. Elementami bufora kołowego będzie struktura o następujących polach: komenda do wysłania, towarzyszące dane, liczba prób, status wysyłania). Funkcja wysyłająca będzie wyłącznie napełniała bufor kołowy nowymi danymi. Przerwanie do Timera wywoływane cyklicznie będzie sprawdzało, czy są jakieś dane do wysłania. Jeśli są to rozpoczyna transmisję i kończy swoje działanie. Przerwanie odpowiedzialne za odbiór statusów (jak i „zwykłych” danych) po otrzymaniu statusu będzie sprawdzało jego stan. Jeśli transmisja się powiodła to zdejmuje z bufora bieżącą strukturę, jeśli nie to w bieżącej strukturze zmienia status by przerwanie do Timera podjęło następną próbę wysyłania przy zmienionych parametrach nadajnika. Jeśli wykorzystano maksymalną liczbę prób i nadal nie wysłano bieżącej paczki danych to struktura ta zostanie z bufora usunięta a aplikacja powiadomiona o błędzie transmisji – np. pokaże stosowne okno informacyjne. Tutaj pojawia się i tak kolejny problem a może i nie jeden, do rozwiązania: w takim wypadku nie będzie można przesłać kolejnych danych zanim bieżące pole bufora nie zostanie obsłużone, gdyż w innym przypadku nie byłoby wiadomo do której transmisji dedykowany jest odebrany status co i tak zablokuje możliwość wysyłania kolejnych danych przez ten czas 1s (tyle może trwać „podjęcie” wszystkich prób). Druga sprawa, to fakt, iż niektóre transmisje zapoczątkowywane są po wywołaniu pewnych funkcji za pomocą okien (GUI) i funkcje te czekają na status transmisji. Trudno mi wyobrazić sobie sytuację, że okno zamykamy by nie blokowało aplikacji a później przychodzi oczekiwany status transmisji… jakieś pomysły na usprawnienie tego mechanizmu? Z góry serdeczne dzięki… robiw
  • REKLAMA
  • #6 13716397
    gaskoin
    Poziom 38  
    Masz jakąś specyfikację tego modemu?

    robiw napisał:

    BlueDraco napisał:
    Jeśli nie RTOS, to automat, czyli po "polsku" - "state machine" (maszyna stanów - brrr...).


    RTOS odpada. Jak widziałbys rozwiązanie tego typu przy pomocy maszyny stanów? Jaki mechanizm wykorzystać w tym przypadku by nie zatrzymywać main? Cykliczne przerwanie timera? Jak je powiązać z przerwaniem odbierania statusów. Hmm...robiw


    Niedawno był wątek na temat maszyn stanów, możesz tam zajrzeć. Generalnie I2C w pollingu jest słabym pomysłem, ze względu na bardzo niską częstotliwość tej magistrali. Jeśli masz polling to Twój procesor działa de facto z prędkością I2C.
    Co do implementacji maszyny stanów to robisz stan "oczekiwania", w którym sprawdzasz odpowiednie flagi (if zamiast while) i tyle. Jeśli flagi będą ustawione to przechodzisz do następnego stanu, w którym czytasz rejestry i tyle.
  • #7 13716452
    robiw
    Poziom 26  
    OK. Maszyna stanów jest mi bardzo dobrze znana, gorzej z jej nazwą w tej formie...zastanawiam się jednak nad problemami z poprzedniego mojego postu... robiw

    Dodano po 18 [minuty]:

    gaskoin napisał:
    Masz jakąś specyfikację tego modemu?


    http://www.cypress.com/?docID=45757

    robiw
  • #8 13716973
    Phaeton
    Poziom 19  
    Ok, czyli sprawa jest bardziej skomplikowana. Mam wrażenie że problem jest z całym designem kodu nie tylko z obsługą transmisji. Jeśli operacje I/O z zasady są długotrwałe a aplikacja ma do tego być interaktywna, to blokujące czekanie na status w jakimkolwiek miejscu odpada. I tu wraca wspomniana maszyna stanów sterowana zdarzeniami.
  • #9 13717004
    robiw
    Poziom 26  
    Design kodu jest typowy, nic nadzwyczajnego poza GUI. Niemniej jednak muszę rozwiązać problem informowania innych funkcji wywoływanych z poziomu okien o statusach transmisji... rozwiązanie z buforem kołowym jest ciekawe, ale niewystarczające... robiw
  • REKLAMA
  • #10 13717347
    excray
    Poziom 41  
    Każda transmisja w takim razie powinna mieś swój unikatowy ID, wrzucasz jej ID w kolejkę wraz ze znacznikiem "ważności" który jest zmniejszany co przerwanie zegarowe. Jeśli dojdzie do 0 zgłaszasz timeout dla danej transmisji i wywalasz ją z tej kolejki. Tak samo jeśli przyjdzie ACK. Dodatkowo dzięki temu w swoim GUI możesz wyświetlić po jakim czasie przyszła odpowiedź jeśli przyszła.
  • #11 13717376
    robiw
    Poziom 26  
    Już prawie mam obmyślone skuteczne rozwiązanie. Po co ID? Jeśli przed nadejściem statusu transmisji rozpocznę inna transmisję to nie będę miał pewności do której transmisji należy status, który później nadejdzie. Jeśli ustawie je jednak w kolejkę i przekażę całe sterowanie wysyłaniem do przerwania zegarowego to jestem w stanie to ogarnąć. To samo przerwanie, na podstawie statusu transmisji może ustawiać odpowiednie flagi dla main, by ta zmodyfikowała stany GUI... czyli może robić to, co wykonywały funkcje wywołujące transmisję. Tak czy inaczej potrzebuję sporo RAMu na bufor kołowy struktur danych przeznaczonych do wysłania bo same pakiety danych mogę mieć kilkanaście bajtów a do tego potrzebne są jeszcze inne elementy struktury by odpowiednio zorganizować działanie tego przerwania. Niemniej jednak, do samej organizacji GUI potrzebuję procek w większa ilością Flasha (a co za tym zwykle idzie, i RAMu) więc nie powinno być raczej problemu... robiw
  • #12 13717429
    excray
    Poziom 41  
    robiw napisał:
    Po co ID? Jeśli przed nadejściem statusu transmisji rozpocznę inna transmisję to nie będę miał pewności do której transmisji należy status, który później nadejdzie.

    Właśnie po to między innymi jest Ci potrzebny ID.
  • #13 13717447
    robiw
    Poziom 26  
    Nie rozumiem? W statusie transmisji nie masz żadnego ID, który mówiłby o tym do której transmisji jest ten status. Jak chcesz rozróżniać ID statusu? Zresztą funkcja wysyłająca będzie miała dostęp do indeksu aktualnie wysyłanej wiadomości i będzie ją ponawiała, aż wyczerpie liczbę prób po czym ustawi odpowiednie flagi dla main, usunie bieżącą wiadomość z bufora i przejdzie do kolejnej w kolejce - typowy bufor kołowy. Jeśli próby zakończą się powodzeniem, zrobi w zasadzie to samo...tylko flagi będą inne. Nie rozumiem idei z ID? robiw
REKLAMA