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

atmega2560 - przerwania nie działają po rozbudowie funkcji bufora, I2C, USART

pawel260 27 Sie 2012 17:39 1725 14
  • #1 11251832
    pawel260
    Poziom 10  
    Pracuję obecnie nad układem obsługującym kilka czujników na I2C oraz jednym na USARTcie i wysyłaniu przeliczonych i obrobionych danych przez drugi USART do innego mikroprocka.

    Program, którym obsługuję całość, składa się z:
    1. zewnętrznych przerwań generowanych przez czujniki (linie INT0...7), gdzie są ustawiane flagi, że czujniki mają nowe dane
    2. z przerwania od odbioru danych po USARTcie, gdzie odebrane bajty wpisywane są do buforu
    3. z przerwania od skończenia konwersji na ADC (triggerem jest przepełnienie timera0) ustawiającego flagę, że dane można zczytać i obrobić
    4. z przerwania compare match od timera1, ustawiającego flagę, że należy wysłać to co mamy do tej pory.
    W pętli głównej wszystkie flagi są zaifowane i czyszczone po wejściu w daną procedurę, gdzie wykonywany jest odbiór danych i ich obróbka.

    Wszystko działało sensownie do momentu rozbudowania funkcji interpretujących bufor (generalnie chodzi, że zajmują więcej czasu). Obecnie program wykonuje się na początku poprawnie jednak po pewnym czasie (5-10 sekund) niektóre przerwania przestają się wykonywać. Powstawiałem trochę instrukcji wysyłania po usarcie w różnych miejscach, żeby zobaczyć co się dzieje i w momencie wieszania przestają się wykonywać przerwania od timera1 oraz wszystkie INT0..7 od czujników. Nadal jednak wykonuje się przerwanie od odebrania danych po USARTcie oraz przerwanie od zakończenia konwersji ADC i główna pętla programu wykonuje odpowiadające im ify. Gdy skróci się wykonywany w ifach kod, to program wraca do normalnego działania. Czym takie zachowanie może być spowodowane ? Z logiki działania wydaje się, że przerwania powinny nadal się wykonywać niezależnie od ilości kodu w funkcji main. Czy ktoś ma jakieś sugestie ?
  • #3 11252343
    pawel260
    Poziom 10  
    Procedury przerwań zewnętrznych:


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




    oraz główna pętla programu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Z odpalenia diagnostycznego terminala nagrałem kawałek, w którym przerwania zanikają:
    i tu mała legenda
    01 02 - kolejne kroki ifa związanego z acc w głównej pętli (wykonywane po wystąpnieniu 11 - czyli przerwania zewnętrznego z czujnika)
    03 04 - kolejne kroki odczytu z ADC w głównej pętli (wykonywane po ustawieniu flagi od zakończenia konwersji ADC, triggerowanej przepełnieniem timer0)
    05 06 - kolejne kroki interpretacji bufora gps (wykonywane po odebraniu całego zdania od GPS, wykonywane po wystąpieniu 14 tyle razy ile znaków w zdaniu)
    07 08 - kolejne kroki wysyłania obrobionych danych na drugim usarcie (odpalane po wystąpieniu 13)

    11 - przerwanie od acc
    13 - przerwanie od timera zaznaczającego flagę wysyłania danych
    14 - przerwanie odebrania danych od GPS

    02 03 04 13 07 08 11 11 10 11 01 11 02 03 04 01 02 10 11 01 02 11 01 02
    03 04 11 01 02 10 11 01 02 13 07 08 11 11 10 11 01 11 02 03 04 01 02 11
    01 10 02 03 04 11 01 02 11 01 02 10 11 01 02 13 03 04 07 08 11 11 10 11
    01 11 02 03 04 01 02 11 01 10 02 11 01 02 11 01 02 03 04 10 11 01 02 13
    07 08 11 11 10 11 01 11 02 03 04 01 02 11 01 10 02 03 04 11 01 02 11 01
    02 10 11 01 02 13 07 08 11 11 14 14 14 10 14 14 11 14 14 14 01 14 11 14
    02 03 04 14 01 14 14 02 03 04 14 11 01 14 14 10 02 14 14 14 11 01 14 14
    02 14 14 14 11 01 14 14 02 14 03 04 14 11 14 01 10 14 02 14 14 13 07 08
    14 11 14 14 14 14 14 11 14 14 14 10 14 14 11 14 14 14 14 01 11 14 02 03
    04 14 05 06 01 14 14 02 14 14 14 14 14 14 14 03 04 14 14 14 14 14 14 14
    14 14 14 14 05 06 14 14 14 14 14 03 04 14 14 14 14 14 14 14 14 14 14 14
    14 14 05 06 14 14 14 03 04 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14
    03 04 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 03 14 04 14 14 14 14
    14 14 14 14 14 14 14 14 14 14 14 05 06 03 04 14 14 14 14 14 14 14 14 14
    14 14 14 14 14 14 14 03 04 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14
    03 04 14 14 14 14 14 14 05 06 03 04 03 04 03 04 03 04 03 04 03 04 03 04
    03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04
    03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04
    03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04 03 04
    03 04 03 04 03 04 03 04 03 04 03 04 14 14 14 14 14 14 14 14 03 04 14 14



    i pytanie jest dlaczego te zewnętrzne przerwania w pewnym czasie zanikają ? gdy odejmie się trochę kodu z pętli głównej z dowolnego ifa, to działa.
    Może dodam jeszcze, że kod jest wykonywany dość szybko, przerwanie od acc przychodzi na 200Hz, przerwanie od GPS ma obecnie 1Hz, przerwanie timera od wysyłania 25Hz, ADC odpala się około 60Hz

    Dodano po 1 [godziny] 33 [minuty]:

    z tego co wiem, w ISR pozostałe przerwania są wyłączane, czy mam rację ? nie istnieje więc chyba możliwość, że odpala się za dużo przerwań i łącznie za dużo rzeczy odkładanych jest na stos ? Swoją drogą wywołanie takie prostego ISR z jedną linijką kodu również wiąże się z odkładaniem wszystkich zmiennych, na których pracuje w danym momencie uC na stos, czy to oznacza, że w sumie obsługa takiego prostego ISR tak naprawdę trwa dość długo ?
  • Pomocny post
    #4 11253130
    dondu
    Moderator na urlopie...
    Jeżeli Twoja funkcja transmisji wygląda podobnie jak ta:

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

    ... (czyli zawiera pętlę oczekującą) to się nie dziw, że wywołując ją w przerwaniu może powodować nieprawidłowe działanie przerwań. Objawy będą właśnie takie jak opisujesz:

    pawel260 napisał:
    ... niektóre przerwania przestają się wykonywać.

    A konkretnie są tracone, jeżeli były zgłoszone wielokrotnie w czasie, gdy nie zostały obsłużone.
    Tak na wszelki wypadek: http://mikrokontrolery.blogspot.com/2011/04/problemy-c-przerwania.html

    Rozwiąż to także flagami, a wtedy okaże się czy to było przyczyną, czy jednak należy szukać dalej.
  • #5 11253232
    pawel260
    Poziom 10  
    To prawda, moje funkcje USART_Transmit zawierają dokładnie tą pętlę czekającą, jednak zostały dodane tylko dla diagnostyki problemu, dokładnie te same objawy, czyli zanikanie wysyłania od funkcji Data_send w pętli głównej programu, pojawiają się bez nich, co sugeruje, że przerwanie od compare match timera1 się przestaje wykonywać. Data_send oczywiście też korzysta z tych samych prostych funkcji USART_Transmit, jednak nie jest ona wywoływana w przerwaniu.

    Dzięki za artykuł, przyda mi się przeczytać tak czy siak. Może jakieś chociaż sugestie gdzie jeszcze błędu poszukać i jak spróbować go diagnozować ?
  • #7 11253274
    pawel260
    Poziom 10  
    To może okazać się trudne, bo kodu jest sporo i w wielu plikach. Wciąż to wygląda na to, że przestaje działać gdy ma za dużo kodu do przetrawienia. Generalnie problemy pojawiły się jak dołożyłem dzisiaj kilka więcej funkcji atof do zrzucenia danych ze stringów z gps we floaty. I tak jak mówię, wywalenie praktycznie każdej dłuższej funkcji z main, powoduje, że problem znika. Nie umiem tylko wyobrazić sobie tego mechanizmu co go blokuje.

    Kod zaraz postaram się jakoś wrzucić.
  • #8 11253280
    dondu
    Moderator na urlopie...
    To nie wrzucaj. Może raczej opisz jaki podział zadań masz, jeżeli to co w pierwszym poście nie jest wszystkim.

    atof - zmienny przecinek - tutaj faktycznie może leżeć przyczyna jeżeli używasz w przerwaniach.
  • #9 11253370
    pawel260
    Poziom 10  
    ale atofy są odpalane tylkow funkcji GPS_Data_Interpretation, która czyta z bufora to co zostało w przerwaniach zapisane przez GPS i zwyczajnie wrzuca do floatów, przerwania powyżej to wszystkie, które są używane
  • #10 11253425
    dondu
    Moderator na urlopie...
    Dlatego napisałem, że jeżeli używasz w przerwaniach.
    Ale jeżeli nie, to przyczyna leży gdzie indziej.

    Pozostaje szukanie przez eliminowanie poszczególnych funkcjonalności, a po znalezieniu konfliktu zastanowienie się dlaczego powstaje i jak go obejść.
    To żmudna robota, ale chyba jedyna możliwa.

    Może jeszcze ktoś się włączy do dyskusji ...
  • #11 11253440
    pawel260
    Poziom 10  
    Kod przerwania od odebrania danych przez USART od gps'a jest u góry, ale jeszcze raz go podam:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Czy może się okazać, że ten kod jest zbyt długi dla tego przerwania ?

    Funkcja interpretująca dane z GPS'a ma się następująco (jest odpalana w main, po ustawieniu w powyższym przerwaniu flagi o odebraniu całego nowego zdania)

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



    i teraz widzę, że bufor nie jest typem volatile, jednak z drugiej strony operacje na nim nie są wykonywane poza ISR i w nim jednocześnie. Choć jednak chyba zdarza się, że bufor jest czytany w GPS_Data_Interpretation, gdy ISR już na nim działa. I volatile nie wydaje się być tu rozwiązaniem.
  • #12 11253448
    LordBlick
    VIP Zasłużony dla elektroda
    Moja rada - nie próbuj odpluskwiać wszystkiego na raz...
    Wyodrębnij jeden blok funkcjonalności i się upewnij, ze działa bez zastrzeżeń, a potem następny...
  • #13 11253459
    dondu
    Moderator na urlopie...
    pawel260 napisał:
    Czy może się okazać, że ten kod jest zbyt długi dla tego przerwania ?

    Nie podajesz z jaką częstotliwością pracuje mikrokontroler, ale nie sądzę, byś miał tutaj problem.

    pawel260 napisał:
    ... i teraz widzę, że bufor nie jest typem volatile, jednak z drugiej strony operacje na nim nie są wykonywane poza ISR i w nim jednocześnie. Choć jednak chyba zdarza się, że bufor jest czytany w GPS_Data_Interpretation, gdy ISR już na nim działa. I volatile nie wydaje się być tu rozwiązaniem.

    Jeżeli jest to wspólny obszar danych, to musisz zadbać o prawidłowe ich wykorzystywanie.

    LordBlick sugeruje to co ja - sprawdzaj po kolei.
  • #14 11253461
    pawel260
    Poziom 10  
    Wygląda po prostu na to, że przez dorzucenie dodatkowego kodu zaczynają wychodzić wcześniejsze niedoróbki w moim kodzie, do tej pory działał bez zarzutów, choć zdarzały mu się chwile, w których zwalniał

    po dodaniu volatile do flag oraz buforów i poprawieniu jednego kawałka interpretującego dane z gps całość działa i się nie wiesza. Tylko jakoś wciąż trochę brakuje mi zaufania do tego mojego tworu..
  • #15 11256726
    nsvinc
    Poziom 35  
    Nie uzywanie volatile dla danych które modyfikujesz z ISRa a interpretujesz w superloopie to jest prosta droga do wygenerowania sobie wszelkich możliwych szopek.
    Nie zawsze jest sens dodawać volatile do buforów - piszę na ARMy w keilu i nie zemściło sie na mnie nigdy ze elementy tablic nie są volatile, gdzie w szczególności dotyczy to wszelkiego rodzaju kolejek.
    Kompilator może zrobić 'to czego sie obawiamy' raczej tylko w przypadkach kodów typu
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Bez volatile wartość z tablicy najpewniej zostanie pobrana z pamięci do rejestru raz, i jesli ta wartosc to nie jest 7, to zwiech, nawet jesli w miedzyczasie ISR wpisze nieszczęsne 7 do tej tablicy.

    Są znikome szanse na to, że taki zwiech wystąpi w przypadku interpreterów zawartosci bufora (e.g. parserów) gdzie powyzsze pętle nie mają racji bytu a tablice są indeksowane zmiennymi.

    Ale koniecznie do wszelkich flag/indeksów które zmienia ISR a czyta superloop, volatile jest konieczny do życia jak alkoholikowi flaszka ;]
REKLAMA