Programowanie uC - wspoldzialanie przerwan i algorytmu - zasady sztuki

Witam,

Chciałem spytać Was, nieco bardziej doświadczonych programistów o sposób programowania uC, gdy program główny jest dość skomplikowany i zależy od wielu sygnałów. Dla ustalenia uwagi załóżmy, że uC ma współpracować m.in. z modułem radiowym CC1100 (podłączonym przez SPI) oraz niekiedy z modułem Ethernet (podłączony do USART) Główne zadania programu to dostęp do medium radiowego (a'la CSMA/CA), analiza ramek radiowych (różnych-różnistych - zgłoszenia, wiadomości sygnalizacyjne, wiadomości tekstowe, głos) i reakcja na nie.

PODEJŚCIE 1. Do tej pory (w innych projektach) robiłem tak:

  1. Procedury obsługi przerwań możliwie najkrótsze (odczyt danych z peryferiów, zapis do bufora w pamięci, pobieżna analiza i ustawianie flag - np. FRAME_COMPLETE dla programu głównego).
  2. Program główny po stwierdzeniu flagi FRAME_COMPLETE wywoływał funkcję Analiza, która ustalała protokół, konkretne znaczenie ramki, ustalając kolejne flagi "wyższej warstwy" (np. RECIEVED_CTS), które to flagi brane były pod uwagę w głównym programie. Coś w stylu (pseudokod dla wysyłania ramki w a'la CSMA/CA):

[IRQ] ... Zapisuj bajty do bufora if (ostatni bajt) then FRAME_COMPLETE ... reti

[MAIN] ... if (FRAME_COMPLETE) then FrameType = Analiza(bufor);

if (Stan == RTS_SENT and FrameType == CTS_RECIEVED and ChannelFree) then Send(data); Stan = DATA_SENT; else if (Stan == DATA_SENT and FrameType == ACK_RECIEVED and ChannelFree) then Stan = IDLE; i tu inne skomplikowane przejścia, zwłaszcza gdy np. wystąpią timeouty ...

[Analiza] ... if (cośtam) then FRAME_TYPE = CTS_RECIEVED; ...

Zaletą jest fakt, że program główny zawsze może zareagować niemal na wszystko. Wady - komplikacja warunków (kilka nałożonych na siebie diagramów stanów: protokołów będzie kilka, typów ramek ok. 20-30) i ogólnie wymięknąłem rozpisując program główny.

PODEJŚCIE 2. Czy nie byłoby grzechem pisanie procedury nadawania ramki po prostu jako funkcji: [SendFrame] Send(RTS); WaitFor(CTS_RECIEVED); if (Timeout) then return ERROR; Send(data); WaitFor(ACK_RECIEVED); if (Timeout) then return ERROR; RETURN OK;

Zaletą jest klarowny oczekiwany przebieg programu i uproszczenie głównego programu. Problemem na pewno są funkcje WaitFor(*), podczas których program jest obojętny na wiele innych sygnałów (np. pojawienie się ramek innych typów, flagi ustawiane przez procedury innych przerwań np. USART). Moim zdaniem można rozważyć w ciele WaitFor sprawdzanie niektórych warunków(flag). Jakie macie sposoby na programowanie uC obsługujących protokoły, muszących brać pod uwagę wiele flag? Dziękuję za wszystkie odpowiedzi, wskazówki, uwagi. Mam nadzieję, że nie zamąciłem zbytnio.

Reply to
Stefcio Z.
Loading thread data ...

Stefcio Z. napisał(a):

I to jest najlepsze podejście. Zminimalizuj czas przebywania procesora w przerwaniach. Zastosowanie automatu fsm albo nawet kilku do obsługi wszystkich protokołów będzie bardzo dobrym i wygodnym rozwiązaniem. Pewnie gotowych implementacji jest kilka i masz z czego wybierać, ja napisałem po swojemu.

formatting link

Reply to
Adam Dybkowski

Pszemol napisał(a):

Oczywiście - co nie zmienia faktu, że w przerwaniach najlepiej przebywać jak najkrócej. Jeżeli robisz system czasu rzeczywistego to ważne także jest, ile trwa najdłuższe przerwanie o wysokim priorytecie i na jaki maksymalny czas blokujesz przerwania w głównym programie.

Reply to
Adam Dybkowski

Adam Dybkowski napisał(a):

Może nie wyraziłem się wystarczająco jasno - jestem całkowicie świadom potrzeby maksymalnego skracania obsług przerwań i stosuję tę zasadę zawsze. Główne pytanie polega na tym, czy ktoś stosuje zastępowanie skomplikowanego diagramu stanów (który w kodzie bez dokumentacji graficznej jest w zasadzie nieczytelny) funkcjami działającymi w sposób "sekwencyjny" ("czekaj na konkretny sygnał, reaguj na inne najistotniejsze sygnały) wg ustalonej w diagramie stanów kolejności - tak jak to przedstawiłem w podejściu 2.

Reply to
Stefcio Z.

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.