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

[STM32] [STM32][DMA][USART] Jak wywołać przerwanie po nadejściu znaku końca ramki?

kozak_sc 20 Sie 2010 12:54 11877 32
REKLAMA
  • #1 8418729
    kozak_sc
    Poziom 23  
    Posty: 752
    Pomógł: 25
    Ocena: 117
    Witam
    Skonfigurowałem UART-a w STM32 do współpracy z DMA i teraz mam pytanko czy jest jakiś łatwy sposób na generację przerwania nie po skompletowaniu określonej liczby znaków tylko po nadejściu konkretnego znaku (znacznik końca ramki) ??
  • REKLAMA
  • #2 8418881
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Niestety nie ma takiej możliwości. UART zbierający dane przez DMA ma niewiele przypadków racji bytu, co innego przy nadawaniu. Lepszym rozwiązaniem jest UART z FIFO. Albo musisz zrezygnować z DMA na RX albo co jakiś czas sprawdzać co UART odebrał.
  • #3 8418894
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    Nie ma takiej możliwości. DMA w STM32 nie ma funkcji przerzutu do tokena.
    Takie coś ma np. DMA zaimplementowany w PIC32.

    Na twój problem stosuje się specyficzne obejście, tzw. szukacz :] (nie wiem
    czy jest to nazwane profesjonalnie, ale wiadomo ocb)

    Sytuacja:
    1) DMA jest skonfigurowany w circular mode, i przerzuca w kółko n danych
    do bufora o rozmiarze n. Wskaznik na pamięć ustawiasz na zerowy
    element bufora, z inkrementacją. Wskaznik na peryferium ustawiasz na UARTx->DR, bez inkrementacji.

    2) Tworzysz zmienną, inicjalizujesz zerem. Nazwijmy ją ple

    3) W main posuwasz ple do przodu aż do momentu gdy osiągnie ona
    DMAx->CNDTR-wielkosc bufora (pamietaj o minus!). Robisz to np.
    forem. Break-asz fora gdy znajdziesz interesujący cię token.

    4) ple w tym przypadku jest twoim szukaczem. Nie możesz nigdy zgubić
    jego najaktualniejszej wartości, nawet po opuszczeniu powyzej opisanego
    fora. Pamiętaj również o tym, że szukacza musisz odpowiednio zawijać na
    skraju bufora!

    Kodu niestety nie mogę udostępnić, bo jest komercyjny, a
    nie mam w tej chwili czasu przerabiać go do przykładu.

    ->michalko12
    Własnie DMA jest niezbędny podczas praktycznie dowolnego RX-a. TX sam
    decyduje o częstotliwości wysyłki znaków, no bo TY nadajesz, a KTOŚ odbiera -
    nie musisz dostosowywać w większości przypadków prędkości TX do odbiornika.
    Pamiętaj, że to RX jest krytyczny, bo KTOŚ nadaje, a TY masz zdążyć odebrać
    dane!
    Zbuduj interfejs przetwarzający w obie mańki 1M znaków z parserem,
    formaterem danych i obsługą pobocznych peryferiów BEZ DMA - wtedy Ci uwierzę...
  • REKLAMA
  • #4 8419067
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    nsvinc napisał:

    ->michalko12
    Własnie DMA jest niezbędny podczas praktycznie dowolnego RX-a. TX sam
    decyduje o częstotliwości wysyłki znaków, no bo TY nadajesz, a KTOŚ odbiera -
    nie musisz dostosowywać w większości przypadków prędkości TX do odbiornika.
    Pamiętaj, że to RX jest krytyczny, bo KTOŚ nadaje, a TY masz zdążyć odebrać dane!


    Cytat:
    UART zbierający dane przez DMA ma niewiele przypadków racji bytu, co innego przy nadawaniu.


    "Ma niewiele" a nie "wcale nie ma". W przypadku TXa jest tak samo, co ci po DMA przy pełnym RSie. Mówię tylko o przypadku STM32 gdzie te peryferia sa takie jakie są.


    nsvinc napisał:
    Zbuduj interfejs przetwarzający w obie mańki 1M znaków z parserem,
    formaterem danych i obsługą pobocznych peryferiów BEZ DMA - wtedy Ci uwierzę...


    Dlatego napisałem że lepszym rozwiązaniem jest FIFO i nie mówię że DMA jest be, bo nie jest, tylko nie we wszystkich przypadkach używanie DMA jest wygodne.
  • REKLAMA
  • #5 8419095
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    Oczywiście że FIFO. Ale w przypadku STM32 do tego FIFO dane wklada DMA.
    Tak jest w moim przykładzie.

    Czym jest "pełny RS"? A w STM32 jest jaki? Połowiczny?
    Przecież i tak masz wyprowadzone CTS i RTS, ktore raczej świadczą
    o "pełności" tego RSa.

    Co Ci po kontroli przepływu (chyba o to chodzilo z "pełnością"), skoro np.
    jeśli w danym momencie rdzen robi coś raczej istotnego (scheduler OSa,
    przerwanie...) a malutkie np. 128bajtowe FIFO jest pełne, to CTS idzie w dół - nie ma transmisji...

    Po co, skoro DMA może przerzucić zawartość FIFO do jakiegoś bardzo
    dużego bufora roboczego, a transmisja może iść dalej niezależnie od
    zajętości rdzenia?

    fakt, problem rozwiązuje potężne fifo o wielkości potrzebnego bufora roboczego,
    ale jaka jest opłacalność jego implementacji? Łatwiej użyć DMA i osiągnąć
    ekwiwalentny efekt.
  • #6 8427840
    kozak_sc
    Poziom 23  
    Posty: 752
    Pomógł: 25
    Ocena: 117
    W moim przypadku to akurat faktycznie DMA na odbiorze nie ma sensu bo otrzymuje kilkanaście ramek na sekundę (po kilkanaście znaków) więc szukanie cały czas w buforze końca ramki wyjdzie mi tak samo jak odbieranie znaku w przerwaniu sprawdzanie czy nie koniec i ładowanie do bufora. DMA chciałem dać dlatego żeby nie musieć się martwić odbiorem na kilku uartach a "mielić" ramki dopiero jak będą kompletne, niestety Cortex M3 tego nie wspiera a przesiadka tylko z tego powodu na PIC32 nie wchodzi w grę :P Dzięki koledzy za odpowiedź.
  • #7 12539214
    Svavo
    Poziom 23  
    Posty: 800
    Pomógł: 42
    Ocena: 30
    A właśnie, że jest sposób na efektywne wykorzystanie DMA przy odbiorze, nawet dla zmiennej długości ramek. Wystarczy ustawić przerwanie od stanu IDLE dla kanału szeregowego U(S)ART, które generowane jest po zakończeniu transmisji. W tym momencie wszystkie dane są już w zdefiniowanym w DMA obszarze pamięci.
  • #8 12539937
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Podobają mi się te rzeczy o których czytam tutaj (; Do tej pory myślałem że DMA raczej nie ma sensu przy odbiorze danych których długość jest nieznana/zmienna, a tu proszę... Wychodzi na to, że przy zastosowaniu standardowych mechanizmów RTOSa (programowe timery) + ewentualne przerwanie od IDLE można mieć samo odbieranie "gratis".

    4\/3!!
  • #9 12540085
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Tylko ile to kosztuje w oprogramowaniu... Coś dużo się tego robi.
  • #10 12540125
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Nie uważasz przecież chyba, że da się zrobić wydajny i szybki kod realizujący kilka skomplikowanych funkcji przy użyciu 10-ciu linijek kodu, no nie?

    Poza tym wg mnie taka idea ("nadganianie" DMA w buforze cyklicznym) nie kosztuje nic więcej kodu niż normalna obsługa przerwania, za to ile mniej czasu...

    4\/3!!
  • REKLAMA
  • #11 12540264
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    Tą ideę praktykuję od lat w m.in. różnego rodzaju interfejsach/translatorach, i jeszcze mnie to nie zawiodło. Różnica w ilości kodu - praktycznie żadna.
    Poza tym nie trzeba wcale mieć timerów ani zadnego supervisora, jeśli masz gwarancję, że dane przetworzysz szybciej, niz przychodzą. A parser i obróbka może się mielić najzwyklej w pętli głównej.

  • #12 12540392
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    nsvinc napisał:
    Poza tym nie trzeba wcale mieć timerów ani zadnego supervisora, jeśli masz gwarancję, że dane przetworzysz szybciej, niz przychodzą. A parser i obróbka może się mielić najzwyklej w pętli głównej.

    Ja tutaj patrzę od razu pod kątem podpięcia takiego odbioru pod strumienie (czyli FILE, scanf() itd.), które z racji swojej asynchroniczności generalnie potrzebują "czegoś" co by od czasu do czasu odczytywało dane i budziło wątki które na te dane czekają, więc jak znalazł timer programowy lub przerwanie.

    4\/3!!
  • #13 12541766
    Svavo
    Poziom 23  
    Posty: 800
    Pomógł: 42
    Ocena: 30
    Obsługa UART'a przez DMA czy (tylko) przerwania to najniższa warstwa stosu - to co zrobimy z danymi dalej zależy już od konkretnego przypadku. Przerwania i FIFO (o odpowiednim rozmiarze) znacząco odciążają CPU ale korzystając z DMA zostają tylko przerwania przy zakończeniu nadawania/odbioru. Poza przypadkiem, kiedy trzeba analizować każdy nadchodzący bajt, widzę same zalety korzystania z DMA.
  • #14 12542348
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    To działa tylko jeśli nadający wysyła kiedykolwiek to 'idle'. Komputer na życzenie nie potrafi - nie przejdzie [dane][idle][dane][idle] jeśli w kompie mam zapchaną kolejkę wyjściową. Wtedy pozostaje softem gonić index zapisu DMA.

    Dla strumieni transmisja synchroniczna często odpada ze względu na długi RTTI. Ale to też zależy od tego, co transportuje protokół. Ja często jestem zmuszony do transmisji izochronicznej, i nie ma czasu na ACK. A implementacja protokołu obsługującego ACK window to w 99% przypadków przerost formy nad treścią.
    Opracowałem dla siebie wzorzec protokołu multipleksowanego, gdzie po symbolu startu ramki wiadomo, czy ramka niesie dane izochroniczne, czy transakcję pytanie-odpowiedź. I implementuję to w praktycznie każde urządzenie ;]

    A kiedy nie trzeba analizować każdego nadchodzącego bajtu? - praktycznie zawsze trzeba, jeśli DMA nie potrafi rozpoznać narzuconych symboli (jak w PIC32). Poza tym - każdy szanujący się protokół dokleja CRC na koniec ramki, więc trzeba mielić każdy bajt chociażby po to, żeby karmić obliczarkę CRC.
    Korzystanie z DMA ma same zalety niezależnie od tego, co dalej robimy z danymi - w którymś topicu przytoczyłem obliczenia, które uwidaczniają różnicę w obciążeniu procesora.
  • #15 12547731
    Svavo
    Poziom 23  
    Posty: 800
    Pomógł: 42
    Ocena: 30
    nsvinc napisał:
    To działa tylko jeśli nadający wysyła kiedykolwiek to 'idle'. Komputer na życzenie nie potrafi - nie przejdzie [dane][idle][dane][idle] jeśli w kompie mam zapchaną kolejkę wyjściową. Wtedy pozostaje softem gonić index zapisu DMA.(...)

    IDLE określa stan "mark" (=1) na magistrali i nie ma potrzeby tego "znaku" wysyłać. Oznacza to po prostu brak danych na magistrali. Dzięki temu można odróżnić stan IDLE od DISCONNECTED.
  • #16 12547737
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    Jeśli magistrala jest przeciążona to nie występuje na niej 'brak danych'. Idle to jest 10 sampli jedynek pod rząd i faktycznie występuje jesli magistrala jest w danym momencie bezczynna - ale nie występuje, jak jest przeciążona.
    To o czym mówisz ma sens tylko przy transmisji synchronicznej, gdzie nadawca wysyla kompletna ramke i czeka na ACK od odbiorcy.
    Jeśli nadawca tłucze strumien zapychając całą dostępną przepustowość - nie ma szans...
  • #17 12547757
    Svavo
    Poziom 23  
    Posty: 800
    Pomógł: 42
    Ocena: 30
    nsvinc napisał:
    Jeśli magistrala jest przeciążona to nie występuje na niej 'brak danych'. Idle to jest 10 sampli jedynek pod rząd i faktycznie występuje jesli magistrala jest w danym momencie bezczynna - ale nie występuje, jak jest przeciążona.
    To o czym mówisz ma sens tylko przy transmisji synchronicznej, gdzie nadawca wysyla kompletna ramke i czeka na ACK od odbiorcy.
    Jeśli nadawca tłucze strumien zapychając całą dostępną przepustowość - nie ma szans...

    Jeśli magistrala jest przeciążona to siłą rzeczy nie występuje stan IDLE. W znanych mi protokołach opartych na łączu RS232/485 urządzenia zawsze pracują jako master<->slave, dlatego tu problem przeciążenia magistrali nie występuje.
  • #18 12548496
    asier
    Poziom 12  
    Posty: 18
    Ocena: 2
    Manual o IDLE mówi:
    Cytat:
    An Idle character is interpreted as an entire frame of “1”s followed by the start bit of the next
    frame which contains data (The number of “1” ‘s will include the number of stop bits).

    Czy ktoś może sprawdzał praktycznie kiedy faktycznie pojawia się flaga IDLE? Ja z powyższej informacji wnioskuję, że ta flaga ustawia się dopiero wtedy, gdy nadejdzie nowy znak poprzedzony odpowiednio długą ciszą na linii, czyli nie da się wykryć przerwy zanim nie nadejdzie kolejna ramka.
  • #19 12548512
    Svavo
    Poziom 23  
    Posty: 800
    Pomógł: 42
    Ocena: 30
    asier napisał:
    Manual o IDLE mówi:
    Cytat:
    An Idle character is interpreted as an entire frame of “1”s followed by the start bit of the next
    frame which contains data (The number of “1” ‘s will include the number of stop bits).

    Czy ktoś może sprawdzał praktycznie kiedy faktycznie pojawia się flaga IDLE? Ja z powyższej informacji wnioskuję, że ta flaga ustawia się dopiero wtedy, gdy nadejdzie nowy znak poprzedzony odpowiednio długą ciszą na linii, czyli nie da się wykryć przerwy zanim nie nadejdzie kolejna ramka.

    Jest dokładnie tak jak napisali w manualu, czyli flaga pojawia się po 10-ciu kolejnych bitach =1. W praktyce oznacza to odebranie całej paczki danych.
  • #20 12548543
    asier
    Poziom 12  
    Posty: 18
    Ocena: 2
    Svavo napisał:
    Jest dokładnie tak jak napisali w manualu, czyli flaga pojawia się po 10-ciu kolejnych bitach =1. W praktyce oznacza to odebranie całej paczki danych.

    To może uściślę pytanie. Czy w sytuacji, gdy skończył się pakiet danych i nie ma już następnych, dostanę przerwanie od IDLE po 10-ciu bitach ciszy od ostatniego znaku, czy też przerwanie pojawi się dopiero wtedy gdy w przyszłości rozpocznie się nowy pakiet danych?
  • #21 12548599
    Svavo
    Poziom 23  
    Posty: 800
    Pomógł: 42
    Ocena: 30
    Odpowiedź A
  • #22 12548621
    asier
    Poziom 12  
    Posty: 18
    Ocena: 2
    Svavo napisał:
    Odpowiedź A

    Dzięki! Ta informacja pomoże mi w przyszłości w przeróbce pewnego projektu.
  • #23 16247578
    mongoł2000
    Poziom 18  
    Posty: 623
    Pomógł: 15
    Ocena: 175
    Wiem , że stary temat, ale czemu koledzy nie używają mechanizmu wyszukiwania znaku w transmisji, która jest sprzętowa....opis w DS dotyczy Modbus, ale działa w normalnym trybie USART.
    Wpisuje się w miejsce rejestru ADD znacznik np. końca linii - 0x0D, a potem uruchamiamy przerwanie od Character Match.
    Druga możliwość to przerwanie po np.100 bitach na magistrali w bezczynności.
  • #25 16247812
    Konto nie istnieje
    Konto nie istnieje  
  • #26 16249208
    kozak_sc
    Poziom 23  
    Posty: 752
    Pomógł: 25
    Ocena: 117
    Cenach jak cenach. Ostatnio bardzo chętnie do projektów dajemy procki L1 ze względu na to że mają poprawionych bardzo dużo błędów w krzemie w stosunku do F1. W F103 na przykład procek idzie do faulta gdy do pamięci na FSMC chcą się odwołać jednocześnie CORE i DMA - porażka.
  • #27 16249435
    Konto nie istnieje
    Konto nie istnieje  
  • #28 16279115
    ufock
    Poziom 10  
    Posty: 10
    Ocena: 1
    kozak_sc napisał:
    Na STM32F1 nie ma takiej możliwości.

    Reference manual twierdzi inaczej. ;)
  • #30 16279627
    Konto nie istnieje
    Konto nie istnieje  

Podsumowanie tematu

✨ W dyskusji poruszono problem generacji przerwania w STM32 po nadejściu konkretnego znaku końca ramki przy użyciu DMA w UART. Użytkownicy wskazali, że standardowe podejście z DMA nie pozwala na takie działanie, sugerując alternatywne metody, takie jak użycie FIFO lub przerwań od stanu IDLE. Zastosowanie DMA w trybie cyklicznym oraz implementacja "szukacza" w buforze zostały zaproponowane jako rozwiązania. Wspomniano również o ograniczeniach w starszych modelach STM32, takich jak F1, które nie obsługują mechanizmu "character match", dostępnego w nowszych modelach, jak L4. Użytkownicy podkreślili, że w przypadku niskiej liczby ramek na sekundę, tradycyjne przerwania mogą być bardziej efektywne niż DMA.
Wygenerowane przez model językowy.
REKLAMA