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

[STM32F103] Odbieranie danych przez UART z wykorzystaniem DMA (na rejestrach)

kamil94goldman 20 Lip 2018 11:07 1677 20
  • #1 17339733
    kamil94goldman
    Poziom 3  
    Posty: 261
    Pomógł: 5
    Ocena: 3
    Witam,

    Próbuje zrealizować odbieranie danych przez UART z wykorzystaniem DMA. Ma to funkcjonować tak, że w funkcji "UART_Receive_DMA(uint8_t *Buffer, int Length)" podaje jako argumenty:
    - bufor do którego mają trafiać dane (tablica)
    - ilość oczekiwanych bajtow
    Po odebraniu tej paczki danych w przerwaniu od końca transmisji DMA dalej będę realizować sprawdzanie odebranych danych itp...

    Moja funkcja odbierająca dane przez UART z wykorzystaniem DMA działa dobrze tylko wtedy, gdy wysłana zostanie taka sama ilość danych jaka została podana w funkcji "UART_Receive_DMA()", gdy wyślę większą ilość danych okazuje się, że już kolejne wywołanie tej funkcji nic nie daje i żadne dane już nie trafiają do bufora odbiorczego, gdy testuje program debuggerem to wygląda wszystko dobrze w konfiguracji DMA, ale żadne dane nie przychodzą. Co robię źle w mojej funkcji "UART_Receive_DMA()" lub w konfiguracji UART?

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




    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #2 17339876
    Sparrowhawk
    Poziom 22  
    Posty: 368
    Pomógł: 57
    Ocena: 19
    Zastanów się nad faktem, że jak konfigurujesz DMA to podajesz ilość przesyłanych danych. Jak potem DMA ma odpalić przerwanie, skoro danych z UART jest mniej, niż zostało to określone?

    Problem i zaproponowane rozwiązanie odbioru danych o nieznanej długości przez UART poruszone zostało w tym wpisie:
    STM32 tutorial: Efficiently receive UART data using DMA
  • #3 17339887
    kamil94goldman
    Poziom 3  
    Posty: 261
    Pomógł: 5
    Ocena: 3
    Ale u mnie występuje problem gdy danych wysyłanych jest więcej niż to zadeklarowano w konfiguracji DMA i po tym DMA się zawiesza i nie odbiera już danych po kolejnym skonfigurowaniu DMA.
  • #4 17339907
    Sparrowhawk
    Poziom 22  
    Posty: 368
    Pomógł: 57
    Ocena: 19
    Ilość danych w paczkach jest zawsze taka sama (lub zgodna z tym czego akurat oczekuje DMA)?
    Wysyłasz kilka paczek jednocześnie, czy są odstępy pomiędzy nimi?
    Po każdej odebranej paczce restartujesz DMA pod nowe dane?
  • #6 17340109
    ex-or
    Poziom 28  
    Posty: 785
    Pomógł: 147
    Ocena: 151
    Ja tam nie wiem, ale jakoś podejrzanie wygląda, że jest włączone przerwanie odbioru danych UART (a handlera ani widu) a nie ma włączonego przerwania końca odbioru DMA.
  • #7 17340250
    Konto nie istnieje
    Konto nie istnieje  
  • #8 17340676
    kamil94goldman
    Poziom 3  
    Posty: 261
    Pomógł: 5
    Ocena: 3
    Freddie Chopin napisał:
    Opisz DOKŁADNIE problem, to co robisz, wrzuć kod którym to robisz i napisz co dokładnie wysyłasz, w jakich ilościach itd.


    No więc tak:
    W debuggerze testuje program, który przedstawiłem poniżej. Gdy wykonuje funkcję UART_Receive_DMA to ustawiam oczekiwaną ilość danych do odebrania. Program działa dobrze dopóki wysyłam z programu RealTerm tyle samo danych co określiłem w wyżej wymienionej funkcji. Lecz gdy wyślę np. 15 bajtów danych, a w funkcji UART_Receive_DMA ustawie 8 transmisji to po kolejnym wykonaniu tej funkcji, kolejne wysłane dane z programu RealTerm nie są odbierane.

    Program main.c:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Program usart2.c:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

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


    z3planety napisał:
    Po co masz przewanie od odbioru USART i DMA za jednym zamachem? Masz mieć włączone przerwanie od DMA a nie od USART-a.

    Poprawiłem lecz nic to nie pomogło.
  • #9 17340701
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Przerwanie DMA dostaniesz po wielokrotnościach ustawionej długości. Czyli po 8, 16, 24, 32, ... odebranych bajtach. Jeśli wyślesz 15, to przerwanie powinieneś dostać po wysłaniu jeszcze jednego bajtu.
  • #10 17340704
    Konto nie istnieje
    Konto nie istnieje  
  • #11 17340739
    kamil94goldman
    Poziom 3  
    Posty: 261
    Pomógł: 5
    Ocena: 3
    z3planety napisał:
    kamil94goldman napisał:
    DMA1->IFCR = 0;


    A co wg Ciebie robi ta operacja?

    Przed odpowiedzią przeczytaj odpowiednią stronę w RM-ie

    No tak, kasowane są jedynką. Poprawiłem na:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Lecz gdy wyślę np. 12 bajtów, a ustawiłem 8 transmisji, to po kolejnym wywołaniu funkcji konfiguracyjnej DMA (flagi są skasowane, rejestr cndtr ponownie jest ustawiony na 8 transmisji), kolejne dane (kolejna paczka np. innych 8 bajtów) nie jest już odbierana (tak jakby transmisja już nie działała).

    Freddie Chopin napisał:
    Przerwanie DMA dostaniesz po wielokrotnościach ustawionej długości. Czyli po 8, 16, 24, 32, ... odebranych bajtach. Jeśli wyślesz 15, to przerwanie powinieneś dostać po wysłaniu jeszcze jednego bajtu.

    Lecz w jaki sposób mogę zrobić odbieranie danych przez UART z wykorzystaniem DMA tak, że jeżeli wyślę więcej bajtów niż to określiłem to, żeby dalsza transmisja nie zawieszała się?
  • #12 17340802
    Konto nie istnieje
    Konto nie istnieje  
  • #13 17340807
    ex-or
    Poziom 28  
    Posty: 785
    Pomógł: 147
    Ocena: 151
    Sparrowhawk napisał:
    STM32 tutorial: Efficiently receive UART data using DMA

    :spoko:
    Istotna informacja. Trzeba też przeczytać komentarze bo w przypadku F103 nie jest to tak proste.
  • #14 17340811
    kamil94goldman
    Poziom 3  
    Posty: 261
    Pomógł: 5
    Ocena: 3
    z3planety napisał:
    Do kolejnej transmisji kanał DMA trzeba najpierw wyłaczyć. Samo załadowanie do rejestru i skasowanie flag ne wystarcza.


    Wywołuje tą funkcję, czyli wyłączam DMA, konfiguruję i włączam. Lecz to nic nie pomaga.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #15 17340825
    Konto nie istnieje
    Konto nie istnieje  
  • #16 17340845
    kamil94goldman
    Poziom 3  
    Posty: 261
    Pomógł: 5
    Ocena: 3
    z3planety napisał:
    jeszcze nie zapomnij o samym USARC-ie, który może byc w stanie błedu - bo obsluga DMA była właczona, ale DMA nić nie zabierało.


    A jeśli UART jest w stanie błędu to jak go usunąć?

    Zmodyfikowałem funkcję do takiej postaci jak poniżej. Czyli wyłączałem również UART i konfigurowałem ponownie, ale nic to nie pomogło.

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


    Dodano po 1 [minuty]:

    W HALu jest taka funkcja jak:

    HAL_UART_Receive(&huart1,(uint8_t *)data3,5,10);

    Umożliwia ona ustawienie nowej ilości transmisji. Chciałbym żeby moja funkcja działała tak samo.

    ex-or napisał:
    Sparrowhawk napisał:
    STM32 tutorial: Efficiently receive UART data using DMA

    :spoko:
    Istotna informacja. Trzeba też przeczytać komentarze bo w przypadku F103 nie jest to tak proste.


    Nie znalazłem tam nic co zbliżyło by mnie do rozwiązania mojego problemu.
  • #17 17345186
    Sparrowhawk
    Poziom 22  
    Posty: 368
    Pomógł: 57
    Ocena: 19
    z3planety napisał:
    jeszcze nie zapomnij o samym USARC-ie, który może byc w stanie błedu - bo obsluga DMA była właczona, ale DMA nić nie zabierało.
    Możesz rozwinąć, bo nie rozumiem, dlaczego włączenie DMA dla USART miałoby powodować błędy, jeśli dane nie przyjdą?

    @kamil94goldman:
    W HAL to jest taka funkcja:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Ta funkcja nie odbierze poprawnie np. 12 bajtów (Wysłanych w paczkach 8 + 4), jeśli zostanie wywołana z argumentem Size równym 8 (nawet dwukrotnie). Jeśli uważasz, że z pomocą HAL możesz odebrać więcej bajtów niż podałeś argumencie Size, to chętnie zobaczę taki przykład.

    kami94goldman napisał:
    Lecz w jaki sposób mogę zrobić odbieranie danych przez UART z wykorzystaniem DMA tak, że jeżeli wyślę więcej bajtów niż to określiłem to, żeby dalsza transmisja nie zawieszała się?


    tilz0R w swoim artykule napisał:

    Problem

    We receive each 5 minutes between 10 and 20 bytes but we don’t know exact number of bytes at a time...


    kamil94goldman napisał:
    Nie znalazłem tam nic co zbliżyło by mnie do rozwiązania mojego problemu.

    Jak czytam ten wątek, i czytam przytoczony przeze mnie artykuł to wydaje mi się, że artykuł dokładnie odpowiada rozwiązaniu twojego problemu.
  • #18 17345300
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Zawsze duże wrażenie robi na mnie optymizm tych, którzy *wiedzą*, ile dokładnie bajtów odbiorą po UART. życzę sukcesów w idealnym świecie. No moje oko szanse, że to będzie działać poprawnie , są bliskie zeru.

    Moim zdaniem odbiór przez DMA sensu nie ma. Istnieją opublikowane rozwiązania z buforem cyklicznym i DMA, których niektórzy Koledzy z forum używają z powodzeniem - i to działa, chociaż moim zdaniem jest to przerost formy nad treścią. uC bez problemu poradzi sobie z przerwaniami odbioru UART.
  • #19 17345352
    Konto nie istnieje
    Konto nie istnieje  
  • #20 17347490
    adamusx
    Poziom 27  
    Posty: 977
    Pomógł: 94
    Ocena: 28
    BlueDraco napisał:
    Moim zdaniem odbiór przez DMA sensu nie ma. Istnieją opublikowane rozwiązania z buforem cyklicznym i DMA, których niektórzy Koledzy z forum używają z powodzeniem - i to działa, chociaż moim zdaniem jest to przerost formy nad treścią. uC bez problemu poradzi sobie z przerwaniami odbioru UART.

    Tu nie do końca się zgodzę, stosuję odbiór przez DMA przy protokole Modbus i działa to świetnie i niezawodnie ( przetestowane w wielu urządzeniach przemysłowych). Nowe dane ładowane są do DMA, aż do wystąpienia timeout (generowany sprzętowo przez wykrycie przerwy w przychodzących danych uart). Oczywiście rozwiązanie ma sens tylko wówczas, gdy dane wysyłamy w pakietach (ramkach) , a nie na zasadzie ciągłego wysyłania bajtów w postaci ASCII bez odstępów.
  • #21 17347600
    Konto nie istnieje
    Konto nie istnieje  

Podsumowanie tematu

✨ Użytkownik próbuje zrealizować odbieranie danych przez UART z wykorzystaniem DMA na mikrokontrolerze STM32F103. Problem polega na tym, że funkcja "UART_Receive_DMA" działa poprawnie tylko przy wysyłaniu dokładnie takiej samej liczby bajtów, jak zadeklarowano. W przypadku wysłania większej ilości danych, DMA przestaje odbierać dane po kolejnym wywołaniu funkcji. Użytkownicy forum sugerują, aby upewnić się, że przerwania są poprawnie skonfigurowane, a także rozważyć użycie trybu cyklicznego DMA lub innego podejścia do obsługi nieznanej długości transmisji. Wskazano również na konieczność wyłączania DMA przed ponowną konfiguracją oraz na możliwość wystąpienia błędów w UART, które mogą wymagać resetu.
Wygenerowane przez model językowy.
REKLAMA