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

[ATMega16] Odczytywanie pamięci programu - dziwne zachowanie

elektronik_hobbysta 04 Kwi 2011 19:27 1305 8
  • #1 9360206
    elektronik_hobbysta
    Poziom 11  
    Witam,

    straciłem dzień na uporanie się z niesamowicie dziwnym zachowaniem programu. Otóż w pamięci programu mam zapisaną tablicę melodia[500][3] przechowującą w każdym wierszu odpowiednio częstotliwość tonu długość tonu i odstęp czasowy od następnego tonu.

    Procedura odegrajMelodie() ma za zadanie wywołać dla każdego wiersza procedurę generującą ton o częstotliwości i czasie trwania odczytanej z pamięci programu. I teraz co dziwne: podczas debugowania, do poszczególnych (poniższych) zmiennych, ładowane są prawidłowe wartości:

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


    Skupmy się na zmiennej frequency i pierwszym tonie jaki generuje układ (zaraz na początku) - ton 660Hz. Gdy uruchomię powyższy kod, to pomimo wczytywania prawidłowej wartości do zmiennej (sprawdzałem prawidłowość wczytanej wartości przez debugger i poprzez warunek IF), generowany ton jest dużo niższy niż gdybym uruchomił taki kod:

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


    Dlaczego tak się dzieje? Jaka może być tego przyczyna. W obu wypadkach do funkcji generujTon wchodzi jako pierwszy parametr liczba 660, a wyniki są różne w zależności od tego skąd ta liczba pochodzi (wpisana ręcznie czy odczytana z pamięci programu). Funkcja odegrajMelodie() jest wywoływana tylko raz. Nie dzieje się tak przy wyłączonych optymalizacjach kompilatora, ale wtedy znowu źle działają funkcje opóźniające _delay_**.

    Z góry serdecznie dziękuję za jakąś podpowiedź.
  • #2 9360258
    dondu
    Moderator na urlopie...
    Witaj,
    1. Pokaż jak masz zdefiniowane parametry w funkcji generujTon().
    2. Możesz wymusić na zmiennych unsigned ponieważ pgm_read_word() zwraca unsigned int ?
    3. Pokaż początek tablicy z danymi.
    4. Jaką masz włączoną optymalizację?
  • #3 9362514
    elektronik_hobbysta
    Poziom 11  
    Dzień dobry, dziękuję za zainteresowanie. Problem jest sporą zagadką dla mnie.
    Muszę się przyznać, że wprowadziłem niechcąco kolegów w błąd. Otóż - przy wyłączonych optymalizacjach jednak się tak nie dzieje, ale nie działają wtedy poprawnie procedury opóźniające _delay_** (co jest normalne).


    Odnośnie pkt. 1:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Odnośnie pkt. 2:
    co ciekawe, jeśli przestawie we wszystkich miejscach w programie "unsigned long int" na "unsigned int", to pomimo, że liczby nigdzie nie wychodzą poza 65535 (nie ma też liczb ujemnych) - wszystko się knoci jeszcze bardziej. A przecież odczytuje z tablicy WORD, czyli uint_16_t.

    Odnośnie pkt. 3:

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


    Odnośnie pkt. 4:
    Próbuję kompilować cyklicznie na różnych optymalizacjach (O1, O2, O3, Os) - muszę ich używać ze względu na korzystanie z procedur _delay_**.

    Cóż.. wygląda na to, że to wina optymalizacji - czy coś można poradzić? Może volatile?

    Dodano po 1 [godziny] 45 [minuty]:

    Problem rozwiązany. Użycie volatile w deklaracji zmiennych spowolniło program, ale zagwarantowało poprawne działanie. Prawdopodobnie, w ramach optymalizacji, gdy kompilator zauważył, że do zmiennej podstawiona jest stała wartość, wprowadzał ją we wszystkich miejscach jako rozwinięcie "inline", co przyspieszało znacząco obliczenia (umożliwiając obliczenie wyniku już w trakcie kompilacji) - stąd dźwięk był wyższy gdy wartość zmiennej wprowadzałem ręcznie, a inny gdy wartość pobierana była z pamięci programu (choć w obu przypadkach była to ta sama wartość).

    Tak jak napisałem, użycie volatile rozwiązuje problem. Stracone półtora dnia, ale czegoś się dowiedziałem przynajmniej.

    Chciałem jeszcze coś dodać, mniej lub bardziej oczywistego, mianowicie: należy pamiętać, aby zmienna podawana jako argument funkcji _delay_** NIE była volatile, ponieważ w przeciwnym wypadku cała funkcja _delay_** nie będzie optymalizowana, tak więc nie będzie poprawnie działała (optymalizacja jest konieczna do prawidłowego działania funkcji _delay_**).

    Pozdrawiam serdecznie.
  • #4 9363022
    dondu
    Moderator na urlopie...
    Hmm, mam wrażenie, że volatile nie rozwiązało prawidłowo Twojego problemu.
    Przekazujesz parametry poprzez argumenty funkcji i volatile nie jest Ci potrzebne, aczkolwiek nie znam zawartości funkcji generujTon().
    Na których zmiennych dałeś volatile?
  • #5 9363146
    elektronik_hobbysta
    Poziom 11  
    Witam,
    wydaje mi się, że problem został jednak rozwiązany. Modyfikator volatile postawiłem przy zmiennych frequency, duration, pause oraz w prototypie funkcji generujTon(). I wszystko "gra" - dosłownie :-) Nie zmienia to faktu, że bardzo nie lubię GCC.

    Pozdrawiam serdecznie,
  • Pomocny post
    #6 9363171
    dondu
    Moderator na urlopie...
    elektronik_hobbysta napisał:
    Modyfikator volatile postawiłem przy zmiennych frequency, duration, pause oraz w prototypie funkcji generujTon().

    Tak sądziłem. Moim zdaniem volatile w tym wypadku jest niepotrzebne.

    Spróbuj tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    a z definicji generujTon(...) usuń volatile.
  • #7 9363196
    elektronik_hobbysta
    Poziom 11  
    Usunąłem volatile, tak jak Pan sugerował. Działa. Nie bardzo rozumiem w czym tkwił prawdziwy błąd? Czy w deklarowanie zmiennych wewnątrz pętli absorbuje tutaj za każdym razem nowy obszar pamięci, nie zwalniając poprzedniego?
  • #8 9363206
    dondu
    Moderator na urlopie...
    elektronik_hobbysta napisał:
    Usunąłem volatile, tak jak Pan sugerował.

    Śmiało pisz per Ty - nawet jeżeli jestem dużo starszy :)

    elektronik_hobbysta napisał:
    Czy w deklarowanie zmiennych wewnątrz pętli absorbuje tutaj za każdym razem nowy obszar pamięci, nie zwalniając poprzedniego?

    Na 100% pewien nie jestem, ale tak właśnie sądzę.
  • #9 9363220
    elektronik_hobbysta
    Poziom 11  
    dondu napisał:
    Śmiało pisz per Ty - nawet jeżeli jestem dużo starszy :)

    OK :)

    Klikam "pomógł" i dziękuję Ci za czas.
REKLAMA