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

[atmega32][c]Nadpisywanie się obszrów pamięci - tylko dla hardkorów.

_StinG_ 02 Sie 2017 23:46 2259 26
  • #1 16622456
    _StinG_
    Poziom 14  
    Witam wszystkich.

    Mam dość nietypowy problem.

    Piszę swój soft do AVT980 (http://serwis.avt.pl/manuals/AVT980.pdf), just for fun.
    Wszystko fajnie pęknie, ale jak startuje moduł RTC i obsługa 1wire dochodzi do dziwnych jazd po pamięci.
    Czasem nadpisują się wyświetlane wartości, a czasem wręcz restartuje się procek (średnio raz na minutę).

    Jak działa sam moduł RTC: to nie ma problemu (2 miesiące chodził bez żadnych incydentów)
    Jak działał sam moduł odpowiedzialny za 1-wire też nie było problemu (próby kilku dniowe)

    I teraz ta najciekawsza część:
    Jak przeniosłem wyświetlanie daty/godziny z funkcji (callback'a) do głównej pętli programu (w
    callbacku zmieniałem tylko i wyłącznie zmienną updateTime ). To również nie zaobserwowałem żadnych
    niepokojących zachowań.

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


    Ktoś ma jakiś pomysł?
    P.S. Dodam tylko, że próbowałem już zrzucania wszystkich rejestrów (+SREG) na stos przy wejściu do przerwania i nie pomogło.

    Cały projekt dostępny jest publicznie: https://github.com/sting86/aquarium_drv :master:hash280b0e4
  • Pomocny post
    #2 16622526
    excray
    Poziom 41  
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    To nie jest poprawna inicjalizacja RTC.
  • #3 16622647
    _StinG_
    Poziom 14  
    Ok. A czy mógł byś rozwinąć?
  • #4 16622740
    grko
    Poziom 33  
    @_StinG_ Jak wyglądają funkcje: RTC_GetDayName oraz RTC_GetDayOfWeek?
  • Pomocny post
    #5 16622759
    ex-or
    Poziom 28  
    Wygląda na przepełnienie stosu.
    Na początek wywal wszystkie stringi do FLASH, np.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    i

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #6 16622772
    _StinG_
    Poziom 14  
    grko napisał:
    @_StinG_ Jak wyglądają funkcje: RTC_GetDayName oraz RTC_GetDayOfWeek?


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


    Dodano po 7 [minuty]:

    @ex-or Moim pierwotnym pomysłem było albo przepełnienie stosu, albo nie zrzucanie jakichś rejestrów na stos. W związku z tym zacząłem zrzucać ręcznie wszystkie rejestry i się nie poprawiła sytuacja. Ale jeśli dobrze myślę, to taka zmiana powinna zwiększyć częstotliwość występowania błędu, jeśli w grę wchodził by pierwszy przypadek, a tak się nie stało, powtarzalność pozostała taka sama. Nie mniej jednak, jak wrócę do domu, na pewno spróbuję Twoich sugestii i dam znać wieczorem jak wyszło.
  • Pomocny post
    #7 16622797
    excray
    Poziom 41  
    _StinG_ napisał:
    Ok. A czy mógł byś rozwinąć?

    Od momentu jak włączysz tryb asynchroniczny dostęp do rejestrów T2 powinien być realizowany w specjalny - asynchroniczny sposób. Odsyłam do DS.
  • #8 16622805
    ex-or
    Poziom 28  
    O, następny zjadacz RAMu:

    _StinG_ napisał:
    char *daysName[] = {"Pn", "Wt", "Sr", "Cz", "Pt", "So", "Nd"};


    napisz to tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #9 16623162
    JacekCz
    Poziom 42  
    Czy rady pomogły?

    Masz jak koledzy sugerują znaczne zużycie stosu jak na mikroprocesor.
    Funkcje używają struktur i buforów lokalnych na stosie, jest to na pewno w jakimś sensie "eleganckie", gdyby funkcje były wielokrotnie (współbieżnie) to zapewni dobre działanie. Przy dobrej kontroli programu takie współbieżne wywołanie ma nie wystąpić. Jakby poprzedzić słowem static zmienne przeniosą się ze stosu do pamięci "głównej", tracąc cechy współbieżności itd ale zyskując inne rzeczy. Takie myślenie jest częste w bibliotece standardowej C i stosujące tę koncepcję funkcje są stosownie opisane.

    Faktem jest że pamięć "główna" i stos pracuje z tej samej pamięci RAM, tylko przesuwa się między nimi granica. Statystykę pamięci "głównej" podaje kompilator w swoich logach, do pewnego stopnia jest to wiarygodne. Natomiast kompilacja nie wychwyci przepełnienia stosu.

    Koledzy dobrze radzą o przeniesienie do flash, chciałem tylko dać formalne uzupełnienie

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #10 16623224
    grko
    Poziom 33  
    Ja jednak mimo wszystko odradzam dodawania static do zmiennych, które mogłyby być na stosie. W sumie te zmienne zabierają maksymalnie ze 40 bajtów stosu i dodawanie do nich static jest kompletnie bez sensu. Jeżeli przepełnia Ci się stos to może oznaczać, że masz za dużo zmiennych globalnych i stos po nich sobie pisze. Pokaż tutaj log kompilacji oraz output narzędzia size (avr-size). Będzie można wtedy więcej powiedzieć czy masz problemy ze stosem.
  • #11 16623273
    Konto nie istnieje
    Konto nie istnieje  
  • #12 16623290
    grko
    Poziom 33  
    Piotrus_999 napisał:
    Jak najbardziej typowy. Policz sobie na karteczce gdzie jest stos i co na nim odkladasz i będziesz wiedział.


    Seriously? Może jeszcze do karteczki liczydełko polecisz? Do tego są narzędzia wbudowane w gcc a nie karteczka. Poza tym, nawet nie używając tych narzędzi można wiele powiedzieć o programie tylko po tym co zwróci avr-size.
  • #13 16623307
    JacekCz
    Poziom 42  
    grko napisał:
    Ja jednak mimo wszystko odradzam dodawania static do zmiennych, które mogłyby być na stosie. W sumie te zmienne zabierają maksymalnie ze 40 bajtów stosu i dodawanie do nich static jest kompletnie bez sensu. Jeżeli przepełnia Ci się stos to może oznaczać, że masz za dużo zmiennych globalnych i stos po nich sobie pisze. Pokaż tutaj log kompilacji oraz output narzędzia size (avr-size). Będzie można wtedy więcej powiedzieć czy masz problemy ze stosem.


    zgadzam się z sensem Twojej wypowiedzi, przeniesienie z 'auto' do 'static' to czynność którą tzreba przemyśleć a niekiedy odradzić.
    Do czasu wypowiedzi Pytającego nie wiemy czy/gdzie marnuje się dużo stosu, bo same 50B to niewiele
  • #14 16624041
    _StinG_
    Poziom 14  
    @excray
    Masz trochę racji ale nie całkowicie. Do inicjalizacji wciąż używamy tych samych rejestrów, różnica jest tylko taka, ze nie czekam aż te wartości zaczną obowiązywać (2 cykle TM2) i teraz: miało by to znaczenie, gdybym chciał przechodzić do sleepa, lub gdybym chciał zmieniać wartości w jednym z rejestrów TIM2, ale te ustawiam tylko raz, na początku programu, a do trybu uśpienia nie przechodzę, więc w tym jedynym przypadku, ta inicjalizacja będzie działać. Ale oczywiście poprawię to w wolnej chwili, żeby było po Bożemu (żebym mógł to w przyszłości w innych projektach wykorzystać).
    P.S. Nawet już dodałem issue odpowiednie na githubie, żeby nie zapomnieć.


    @ex-or
    Zmieniłem tak, bo __flash jest u mnie niedostępny (czas zmienić toolchain, ale to nie teraz)
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Ale jedyne co się zmieniło to fakt, że teraz się to nie wyświetla, kolejna zmina, czyli
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Działa jak należy.

    Mimo poprawek nic się nie zmieniło w zachowaniu.
    @JacekCz
    Na razie jeszcze nic nowego. Nie udało mi się potwierdzić, że wina leży po stronie "stack overflow". A odnośnie tych statików, to nie jest najlepszy pomysł. Trzeba pamiętać, że tego typu zmienne, będą w ramie zajmować przestrzeń nawet gdy ich nie będziesz używał.

    @Piotrus_999
    Z tym liczydłem i kartką papieru to chyba kolegę troszkę poniosło, a o słowie użytym w tytule "hardkor" nie będę się rozwodził.

    @grko Logi z kompilacji (i post kompilacji w tym avr-size)
    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    Więc jeśli to przepełnienie stosu to nadal nie wiem, gdzie gubię 2kB ramu...
  • #15 16624104
    grko
    Poziom 33  
    Nie chce mi się analizować całego programu ale jest możliwe, że jednak dochodzi do przepełnienia stosu. Jednak według mnie masz tu problem z dostępem do zasobów z kontekstu przerwania oraz pętli głównej. Funkcje _onTimeCbf oraz _onKeyCbf powinny być albo reentrant (nie powinny odnosić się bezpośrednio/pośrednio do tych samych zmiennych globalnych) albo blokować w odpowiednich miejscach przerwania. Najlepiej daruj sobie te callbacki z przerwania i użyj po prostu flagi i wywołaj oba callbacki z kontekstu main. Rozwiąże to oba problemy: stosu oraz dostępu z wielu kontekstów do tych samych zmiennych.

    Dodam jeszcze, że cały moduł RTC to po prostu wynajdywanie koła na nowo bo w avr-libc są dostępne funkcje obsługi czasu. Warto z nich po prostu skorzystać aby nie tracić czasu;]
  • #16 16624161
    _StinG_
    Poziom 14  
    Ogólnie cały ten projekt ma taką charakterystykę. Chodzi tu o to, żeby poćwiczyc sobie trochę. :-)
    Co do samego kbd, ten jest chwilowo nie używany, więc nie pracuje on na tych samych zmiennych co etc. A nawet jak pracował, to wszystko działało poprawnie.
    A nie chce jeszcze rezygnować z tych cfb, bo to bardzo eleganckie i elastyczne rozwiązanie. Jeszcze nie czas na wywieszenie białej flagi ;-)
  • Pomocny post
    #17 16624215
    grko
    Poziom 33  
    _StinG_ napisał:

    Co do samego kbd, ten jest chwilowo nie używany, więc nie pracuje on na tych samych zmiennych co etc. A nawet jak pracował, to wszystko działało poprawnie.


    Bazuje na tym co jest na githubie. Z tego co tam jest (nawet pomijając już ten kbd) to ten sam problem dotyczy OW_Magic oraz callbacka RTC. Obie funkcje dobierają się przykładowo do wyświetlacza z różnych kontekstów. To po prostu nie ma prawa działać.

    _StinG_ napisał:

    A nie chce jeszcze rezygnować z tych cfb, bo to bardzo eleganckie i elastyczne rozwiązanie.

    Te callbacki to średnie rozwiązanie. Zwłaszcza takie jakie Ty masz tam zrobione. To znaczy z całą litanią wywołań oraz dostępu do zasobów nie zabezpieczanych sekcją krytyczną. Jeżeli chcesz mieć coś eleganckiego to zaimplementuj sobie coś na kształt workqueue. Wtedy będziesz sobie w swoim przerwaniu/callbacku zlecał funkcje do wykonania. Te zlecenia będziesz realizował przykładowo w pętli głównej sekwencyjnie. Zapewniam Cię, że zniknie problem z jednoczesnym dostępem do zasobów oraz z przepełnieniami stosu.
  • #18 16644469
    _StinG_
    Poziom 14  
    Niestety nie udało mi się jednoznacznie ustalić czy dochodzi do przepełnienia stosu, ale na pewno temat jak najbardziej owocny i przydatny.
    Głównie dzięki koledze @ex-or nauczyłem się jak korzystać z flasha.
    Makro __flash co prawda nie będzie przeze mnie używane, bo nie używam IARa, ale znalazłem i na to rozwiązanie. Na przyszłość będę pamiętał, żeby używać pgmspace.h .
    Dziękuję wszystkim za żywą dyskusję i chęci w rozwiązywaniu problemu.
    Myślę, że na tym etapie możemy zamknąć temat.

    @grko
    Na chwilę obecną faktycznie przeniosłem używanie LCD do maina i tak jak pisałem już w pierwszym poście, to rozwiązuje problem.
  • Pomocny post
    #19 16644936
    ex-or
    Poziom 28  
    _StinG_ napisał:
    Makro __flash co prawda nie będzie przeze mnie używane, bo nie używam IARa

    Kwalifikator __flash jest w gcc od wersji, zdaje się 4.7 i nie jest to makro lecz rozszerzenie języka, tzw. named address spaces: https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html
  • #20 16645860
    _StinG_
    Poziom 14  
    @ex-or Ty statyczny flashowy wariacie. Faktycznie działa :) Po zmianie toolchaina zamiast przeczytać komunikat błędu (error: '__flash' specified for auto variable 'text'), przeczytałem jakiś szemrany wpis insynuujący, że __flash jest w IARze. Mea culpa.
    A tak swoją drogą powyższy błąd pojawił się, jak w ciele funkcji spróbowałem zadeklarować zmienną text bez słówka static jak poniżej
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jak rozumiem tylko zmienne globalne i statyczne (które przecież działają prawie tak samo jak globalne) mogą być przechowywane we flashu. Zgadza się?
    Bo w przypadku zmiennych automatycznych dostaniemy czułe słówka jak wyżej wspomniane.
  • #21 16645983
    Konto nie istnieje
    Konto nie istnieje  
  • #22 16646313
    _StinG_
    Poziom 14  
    @Piotrus_999
    Popraw mnie jeśli się mylę. Mając proca w architekturze Princeton gdy użyjesz kwalifikatora "const" zmienne z automatu wpadną do pamięci flash (jeśli mnie pamięć nie myli tak się stanie choćby w przypadku avr32 i arm). Zmienna taka nie musi być statyczna i kompilator sobie z tym radzi. Oczywiście próba dobrania się do takiego obszaru pamięci przez np. "zręczne" rzutowanie zakończy się runtime errorem (chyba segfault jak dobrze pamiętam). Oczywiście w architekturze Harwardzkiej, mogło by być to trochę trudniejsze do zrobienia ale na pewno nie niemożliwe. Podejrzewam, że dało by się przykryć taką funkcjonalność w kompilatorze.
    Ale oczywiście świetnie rozumiem, dlaczego takiego rozwiązania się nie wprowadza w prockach z już dość mocno ograniczonymi zasobami.
  • #23 16646410
    Konto nie istnieje
    Konto nie istnieje  
  • #24 16646557
    _StinG_
    Poziom 14  
    @Piotrus_999 Zerknij tutaj: Link Z tego jasno wynika, że nie muszą być mieć kwalifikatora static. A i z doświadczenia z armami pamiętam, że też nie musiałem takowego używać, żeby stała trafiła do pamięci RO.
    Ale mniejsza o to, bo trochę zaczynamy odbiegać od tematu. Do zobaczenia w innych wątkach.
  • #25 16646570
    Freddie Chopin
    Specjalista - Mikrokontrolery
    _StinG_ napisał:
    A i z doświadczenia z armami pamiętam, że też nie musiałem takowego używać, żeby stała trafiła do pamięci RO.

    To masz dziwne doświadczenia. Takie hardkorowe.
  • #26 16646706
    Konto nie istnieje
    Konto nie istnieje  
  • #27 16647329
    _StinG_
    Poziom 14  
    @Freddie Chopin Czyżbym wyczuwał zgryźliwość z Twojej strony? Jeśli chcesz się podzielić jakimś źródłem, który podważa to co mówię, to śmiało, ale po co dodawać komentarz, który nie wnosi nic do dyskusji?
    @Piotrus_999 Podesłałem Ci link, żebyś zerknął i sam ocenił czy się mylę, czy nie. Wcześniej zarzuciłeś, że nie mam racji, a ja znalazłem źródła, że jednak mogę ją mieć. Nikogo tym nie uraziłem a przynajmniej nie miałem takich intencji.

    Nie mówię, że jestem nieomylny (inaczej bym na forum nie zadawał pytań), ale interesują mnie tylko rzeczowe odpowiedzi na zadane pytania.

    Na tym etapie wątek chciał bym zamknąć, bo coraz bardziej odbiegamy od tematu.

    @ex-or Dzięki za wszystkie sugestie. Może nie został temat wyczerpany jak bym chciał, ale na pewno Twoje rady ( i nie tylko: @grko, @excray wasze również) pomogą mi usprawnić kod. Pozdrawiam.
REKLAMA