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

[AVR GCC] - Jak uniknąć zamazywania pamięci przy optymalizacji -Os?

djfarad02 23 Gru 2013 02:16 1638 6
REKLAMA
  • #1 13090461
    djfarad02
    Poziom 19  
    Witam,

    Od dłuższego czasu próbuję rozwiązać problem przy pewnym projekcie gdzie bardzo uporczywie dają mi się we znaki błędy powodujące kompletnie nieprzewidywalne efekty.
    Dodałem do kodu funkcję zwracającą ilość wolnej pamięci na podstawie książki M. Kardasia.
    Metodą prób i błędów udało mi się doprowadzić do sytuacji, w której pamięć zapełnia mi konkretny fragment programu.
    Za drugim obrotem pętli while, według funkcji getFreeMem(), coś zabiera nagle 483 bajty (z 486 spada na 3). Możliwe też, że zostaje nadpisany 1 bajt za obszarem zmiennych ale przed stosem (funkcja M. Kardasia szuka pierwszego bajtu niezgodnego ze wzorcem i na tej podstawie określa wielkość stosu)
    framestart=0 i while z takim warunkiem jest celowe. while(1) maskowało błędy.

    Błędy są przy optymalizacji -Os, ALE przy -O0 również, z tym że zamazywany jest inny adres w pamięci. Co ciekawe dopisanie w pewnych miejscach jakiejś instrukcji np. cnt=2; powoduje, że adres zamazanych komórek zmienia się o 2 bajty. Tyle co zajmuje we flashu ten dopisany fragment kodu. Tak jakby miało to związek z licznikiem adresu.
    We fragmencie poniżej nie ma tablic w RAMie

    edit:
    Przeprowadziłem dalsze próby i okazało się, tak jak podejrzewałem, że stos jest w normie tylko zamazywane są dwie komórki pamięci znajdujące się zaraz za zmiennymi. Dalsza cześć, aż do stosu jest nieruszona. W pewnych okolicznościach zamazywanie dotyczy już obszaru zmiennych i wtedy program się krzaczy.

    Za drugim obrotem pętli stos jest większy o 2 bajty czyli wszytko w normie.
    Zamazane są jednak 2 komórki RAMu, kilka bajtów za adresem __heap_start

    Zwracam się z prośbą o przedstawienie możliwych przyczyn zamazania pamięci nie będących:
    -niewłaściwym indeksowaniem tablic
    -przepełnianiem stosu
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 13090671
    excray
    Poziom 41  
    Załączyłeś mnóstwo kodu poza tym właściwym. Gdzie jest funkcja getFreeMem()?
  • REKLAMA
  • #3 13092221
    djfarad02
    Poziom 19  
    Proszę bardzo, oto te funkcje, o które prosiłeś:

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


    Problemy były przed ich dodaniem, one miały mi pomoć w lokalizacji przyczyny.
    Zaznaczam, że jedyne wykonywane przerwanie to timer2, na potrzeby testów wyłączyłem uart. W poprzednim poście załączyłem tyle kodu, aby był widoczny cały wkonywany podczas dziwnego zachowania kod.

    Dodano po 5 [godziny] 45 [minuty]:

    Przeprowadziłem dalsze próby i okazało się, tak jak podejrzewałem, że stos jest w normie tylko zamazywane są dwie komórki pamięci znajdujące się zaraz za zmiennymi. Dalsza cześć, aż do stosu jest nieruszona. W pewnych okolicznościach zamazywanie dotyczy już obszaru zmiennych i wtedy program się krzaczy.

    Za drugim obrotem pętli stos jest większy o 2 bajty czyli wszytko w normie.
    Zamazane są jednak 2 komórki RAMu, kilka bajtów za adresem __heap_start

    Zwracam się z prośbą o przedstawienie możliwych przyczyn zamazania pamięci nie będących:
    -niewłaściwym indeksowaniem tablic
    -przepełnianiem stosu
  • REKLAMA
  • #4 13093941
    djfarad02
    Poziom 19  
    Męczę problem dalej - ostatnie wieści z placu boju:

    Wyłączyłem odczyt jakichkolwiek portów by uniezależnić pracę programu od sygnałów z zewnątrz. Następnie uruchomiłem program na sprzęcie oraz w symulatorze w AVR Studio.

    W symulatorze program działa normalnie, a na sprzęcie idzie w krzaki, zawsze w tym samym momencie, za drugim obrotem pętli testowej while(framestart..., w której jest funkcja getFreeMem().

    Jakieś pomysły?
  • #5 13094101
    BlueDraco
    Specjalista - Mikrokontrolery
    Najpierw skróć kod czterokrotnie, a potem poszukaj błędu w indeksowaniu tablic, który powoduje ten efekt, o którym piszesz.

    Czy używasz w tym programie jakichś funkcji bibliotecznych? - printf, obliczenia zmiennpozycyjne itp.
  • REKLAMA
  • #6 13094698
    djfarad02
    Poziom 19  
    Skróciłem program do minimum, które powoduje występowanie błędu. Timer i nieużywane tablice musiały pozostać, żeby błąd się ujawniał.
    W obecnej postaci jest tak:

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


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


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


    Jak widać, w main wynik funkcji getFreeMem() wysyłam sobie uartem. Za pierwszym razem otrzymuję poprawną wartość 570 (zgodną z symulatorem), a za drugim obrotem pętli już nie - wartość 99. W symulatorze cały czas jest 570.

    Wystarczy, że w zapychacz.h zwiększę tablicę o bajt to zamiat 99 otrzymam 101. Wnioskuję z tego, że problem ma bezpośredni związek z licznikiem adresów i zajętością flasha. tablicy z pliku zapychacz.h wogóle nie używam.
    uC ATmega16A avr studio 4.13 528 gcc opt. -Os

    Co Wy na to?
    Siedzę nad tym 3 dzień, dzisiaj Wigilia a to nie daje mi spokoju
  • #7 13096020
    djfarad02
    Poziom 19  
    Problem rozwiązany - przyczyną była nazwa (!!!!) zmiennej div.

    Opisałem to w nowym temacie:
    https://www.elektroda.pl/rtvforum/topic2717623.html
REKLAMA