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

Atmega2560 - zmienna i4 nie inkrementuje się cyklicznie, UART wysyła tylko raz

arkady25 20 Lip 2017 15:38 1401 15
REKLAMA
  • #1 16598396
    arkady25
    Poziom 16  
    Koledzy,

    dlaczego zmienna i4 nie jest cyklicznie inkrementowana?
    Przynajmniej na porcie UART jest wysyłana tylko zwiększona o jeden i dalej już bez zmian.
    Dioda LED miga poprawnie.
    Problem pojawił się przy próbie wysyłania tablicy danych. Tablica jako taka jest odbierana na PC poprawnie, ale bez zmian poszczególnych bajtów.
    Do obsługi UART wspomagam się biblioteką z książki.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    [/code]
  • REKLAMA
  • #2 16598425
    JacekCz
    Poziom 42  
    Kod funkcji void uart_putc( char data ) czytam i czytam, i nie wiem co robi. Zwal to na upał :)

    Taka zagadka, może wysyłasz stale ten sam bajt, nigdy go drugi raz nie zastępując. Gospodarka kursorem bufora (pozycją w tablicy) jest dla mnie nieczytelna, nie umiem udowodnić że błędna.
  • #3 16598506
    arkady25
    Poziom 16  
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Funkcja uart_putc działa z buforem cyklicznym.

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

    działa poprawnie z funkcją :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Powstały problem sprowadziłem w kodzie do wysyłania jednego bajtu, który miał się zmieniać. Ale niestety nie chce mu się. Może on jest jakiś przyspawany
    Chyba nie ma znaczenia, że działam na płytce arduino mega.
  • REKLAMA
  • #4 16598522
    excray
    Poziom 41  
    Funkcja do wysyłania danych, a raczej koncepcja algorytmu jest skopana.
  • #5 16598532
    arkady25
    Poziom 16  
    Czy to może powodować przywracanie wartości zmiennej i4 do stanu sprzed pętli while?
    W mainie ustawiałem jej różne wartości. W pętli miała się inkrementować. Nic z tego. To co w takim razie jest wysyłane?
  • REKLAMA
  • #6 16598697
    JacekCz
    Poziom 42  
    arkady25 napisał:

    ...
    Funkcja uart_putc działa z buforem cyklicznym.

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

    działa poprawnie z funkcją :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Powstały problem sprowadziłem w kodzie do wysyłania jednego bajtu, który miał się zmieniać. Ale niestety nie chce mu się. Może on jest jakiś przyspawany
    Chyba nie ma znaczenia, że działam na płytce arduino mega.


    W/w testy a końcowa aplikacja to zupełnie inny poziom złożoności, że chodzi w przychylnych warunkach a we współbieżności nawala ,,, bosch to wiele rzeczy może się dziać. Tu null-terminated, tam nie, tam czas a tu nie itd...
    Twoje zeznania - bo na nich się opieram - silnie się kojarzą właśnie z gospodarką bajtowym buforem (cyklicznym). Trzech nas mówi to samo, żaden w upałach nie będzie debugował.

    Aha, "volatile" nie jest jakimś magicznym wytrychem "niech to przy współbieżności dobrze działa", volatile tablica[] jest prawdopodobnie bezskuteczne, a prawie na pewno źle rozumiane.
    Kod, nawet w upały, wali po oczach problemami ze współbieżnością, hazardami na zmiennych.

    arkady25 napisał:

    Do obsługi UART wspomagam się biblioteką z książki.

    Niestety często kod w książkach typu C+mikroprocesory jest daleki od ideału. Właśnie na prostu złudzeniu "u mnie 1234567890 chodzi"
  • #7 16598906
    arkady25
    Poziom 16  
    Czy mogę liczyć na końcowe sugestie, przykłady. Książka jak książka, ma sporo przykładów, więc wydaje się być pomocną.
    W takim razie powiedzcie czy na tej atmedze możliwe będzie uzyskanie (oczywiście nie w bardzo wyrafinowany sposób):
    - nadawania na trzech portach UART jako master, kilkadziesiąt bajtów co sekundę lub dłużej, prędkość 9600 bps jest wystarczająca,
    - odbieranie na czwartym kilkudziesięciu bajtów i odsyłanie ok. 1,5 kB, najlepiej z prędkością 115200 bps. Co kilka minut.
  • #8 16598969
    JacekCz
    Poziom 42  
    Gdyby w tym był problem - głównym sposobem znalezienia hazardu jest analiza wszystkich zmiennych używanych (tutaj) w przerwaniach.

    Każda która jest zapisywana z przerwania i z kodu głównego, nie wiadomo co "zwycięży".
    Dodatkowo każda operacja "odczyt i zapis" (zależnie od rozwinięcia nawet operator ++) może dać efekt nieokreślony (jeśli z drugiej flanki będzie ustawiona). Sekwencyjne porównanie i działanie na takiej zmiennej to niemal pewny błąd.
    Dodatkowo każdy zmienna większa niż "naturalny dla platformy integer" nie musi / nie będzie obsługiwana jednym rozkazem maszynowym, przerwanie może "wejść między wódkę i zakąski" (inkrement na większych ingerach.

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

    w obecności szalejących przerwań?

    Lekarstwem mocnym, ale to jak z każdym mocnym lekarstwem różnie bywa, jest wyłączenie i przywrócenie przerwań.
    Nie robiłem na A2560, czuję że możliwości jest więcej niż na najstarszych, koledzy może podpowiedzą.

    Lekarstwem precyzyjnym jest właściwy projekt.

    Aha, źródła wiedzy. Rozmawiałem z wieloma programistami, jest jakoś naturalnie oczekiwana "gwarancja podczas współbieżności", obrazowo (z pewną luką) język Java ma na to słowo "synchronized".
    A słowo volatile NIE MA takiego znaczenia, ono znaczy tylko "proszę nie składuj tej zmiennej podczas optymalizacji do rejestrów", jest to owszem pomocne (konieczne) do przerwań ale nie wystarczające. Jak widzę duży urodzaj vilatile mam pomarańczowe światełko, tak po prostu mam, nie pytaj dlaczego.

    Błędy od hazardów są losowe, czary mary itd... Każda zmienna globalna tu występująca jest "podejrzana".

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #9 16599160
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #10 16599593
    grko
    Poziom 33  
    @arkady25 A nie masz czasem włączonego watchdoga w fuse bitach? (WDTON)
  • #11 16599649
    arkady25
    Poziom 16  
    grko napisał:
    @arkady25 A nie masz czasem włączonego watchdoga w fuse bitach? (WDTON)

    Bardzo dobry trop, coś zaczyna się dziać.
  • REKLAMA
  • #12 16599676
    grko
    Poziom 33  
    @arkady25 Cóż, najlepiej było szukać hazardów oraz zwalić winę na błędną gospodarkę buforem kołowym w programie, który ma w sumie ze 40 linii oraz wysyła jeden znak na sekundę. Dobrze, że nie doszliśmy do barier i inwalidacji cache.
  • #13 16604829
    arkady25
    Poziom 16  
    Zagadka nadal nie jest rozwiązana.
    Według pomiarów, układ resetuje się po ok. 18 ms działania. Wstaje po ok. 75 ms.
    Atmega2560 - zmienna i4 nie inkrementuje się cyklicznie, UART wysyła tylko raz

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

    Fusy:
    BODLEVEL = DISABLED
    OCDEN = [ ]
    JTAGEN = [ ]
    SPIEN = [X]
    WDTON = [ ]
    EESAVE = [X]
    BOOTSZ = 4096W_1F000
    BOOTRST = [X]
    CKDIV8 = [ ]
    CKOUT = [ ]
    SUT_CKSEL = EXTXOSC_8MHZ_XX_16KCK_65MS

    EXTENDED = 0xFF (valid)
    HIGH = 0xD0 (valid)
    LOW = 0xFF (valid)

    LB = NO_LOCK
    BLB0 = NO_LOCK
    BLB1 = NO_LOCK

    LOCKBIT = 0xFF (valid)


    Programator AVRmkII (f-my Telwis).
    Kod kompilowany w AtmelStudio 6.1 i 7.0
    Układ na płytce Arduino Mega2560.
  • #14 16604910
    Konto nie istnieje
    Konto nie istnieje  
  • #15 16606995
    arkady25
    Poziom 16  
    Doczytałem w dokumentacji, iż ten układ ma rozbudowany moduł Watchdoga.
    I jeśli nawet nie jest wykorzystywany, to należy go wyłączyć. Niezależnie od fusbitu WDTON.

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


    Niezależnie od powyższego, w funkcji USART_Init błędne były dwie linijki, powinno być:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #16 16607060
    Konto nie istnieje
    Konto nie istnieje  
REKLAMA