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

AVR - AS4-AS6 - różnice w kolejności umieszczania danych w pamięci.

excray 22 Lip 2016 13:56 1269 13
  • #1 15823573
    excray
    Poziom 41  
    Witam. Jakiś czas temu pisałem o różnicy między AS4 oraz AS6 w sposobie zapisywania danych. Niemniej błędnie zinterpretowałem to jako różnice między zapisem Big Endian a Little Endian. Tym czasem natura tych różnic jest zupełnie inna. Okazało się, że te 2 środowiska umieszczają dane w innej kolejności. W przypadku AS4 dane zadeklarowane jako pierwsze dostają pierwsze pozycje w pamięci. W przypadku AS7 jest odwrotnie. Przykładowy program:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Skompilowany w AS4 i wgrany spowoduje to, że w EEPROM zostaną umieszczone dane w kolejności 0x01, 0x02, 0x03, 0x04. Ten sam program skompilowany w AS7 zapisze je już w kolejności: 0x04, 0x03, 0x02, 0x01. Czy spotkaliście się z taka sytuacją? Czy można wymusić określony sposób umieszczania danych w pamięci?
  • Pomocny post
    #2 15823678
    michalko12
    Specjalista - Mikrokontrolery
    To jak są dane umieszczane w pamięci to jest zasługa linkera.
    A nie możesz tych danych w strukturze umieścić? Wtedy kolejność się nie zmieni.
  • Pomocny post
    #3 15823698
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #4 15823717
    JacekCz
    Poziom 42  
    Nie wolno liczyć na kolejność zmiennych, może być taka lub inna. A nawet w mocnej optymalizacji zmienne mogą zniknąć (przynajmniej "zwykłe" zmienne, nie wiem jak z kwalifikatorem)

    Struktura, a do tego dyscyplina ułożenia od najdłuższych (64bit których raczej nie masz, 32 bit, 16bit, itd... jak 8 bitowe to nie stanie się krzywda, jak nieparzyste uzupełnisz do par, choćby nie używane w tej chwili) bo tzw allignment wewnątrz struktury może zadziałać i może wyjść inaczej.

    Taka struktura dalej jest nie do końca przenośna np w sytuacjach teletransmisji, ale to wyższa szkoła jazdy.
  • #5 15823725
    excray
    Poziom 41  
    Racja, to jest jakieś rozwiązanie. W zasadzie interesuje mnie po co została zmieniona ta kolejność? Czy jest jakieś wytłumaczenie które tłumaczy ewentualne tego zalety? Bo w końcu trochę bałaganu to wprowadza.
  • Pomocny post
    #6 15823738
    JacekCz
    Poziom 42  
    excray napisał:
    ... W zasadzie interesuje mnie po co została zmieniona ta kolejność? Czy jest na ten temat jakaś nota która tłumaczy ewentualne tego zalety? Bo w końcu trochę bałaganu to wprowadza.


    Standard C składa bardzo niewiele obietnic. Wszystko co jest poza zakresem specyfikacji jest "implementation dependent".
    Z nieco innej beczki: znasz może ze słyszenia że jakiś kod C "niby chodzi" ale na innej maszynie/systemie już nie. Język C jest pełen tzw "undefined behaviour" czyli UB.

    ...dlaczego... jakbym pisał cholernie ambitny kompilator, a rzeczywisty "przemysłowy" kompilator C jest ambitny, podejmował bym dziesiątki różnych decyzji (bo szybciej się wykonuje, łatwej, bo co inne wtedy wychodzi lepiej) i nikomu nic do tego, dopóki nie naruszam obowiązujących reguł.
    Reguła na pola w strukturze jest, na pola (zmienne) luzem nie ma. Na przykład kompilator z siódemki oceniam jako bardzo dobrze optymalizujący, a prawo optymalizacji to prawo do zmiany kolejności, nawet na zaskakującą dla człowieka.

    Jako programista bardzo sobie cenię kompilację jakimś innym kompilatorem niż codziennie używany w projekcie, to ważny test i pouczające doświadczenie.
  • Pomocny post
    #7 15823823
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #8 15823858
    grko
    Poziom 33  
    @Piotrus_999 Niby po co przerabać skrypt linkera? Można to zrobić na kilka sposobów bez tego.
  • #9 15823871
    JacekCz
    Poziom 42  
    GrzegorzKostka napisał:
    @Piotrus_999 Niby po co przerabać skrypt linkera? Można to zrobić na kilka sposobów bez tego.


    A po co w ogóle coś "mieszać" a nie "po bożemu" ?
  • #10 15823872
    excray
    Poziom 41  
    W takim razie jak zapewnić aby adres 0 w eeprom nie był używany? Skoro tak do końca nie mamy pewności, gdzie linker wrzuci nam dane?
    Swoją drogą zrobiłem coś takiego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Oczywiście nie działa do końca tak jak powinno. O ile dane z eeset2 są w eeprom to danych z eeset1 już nie ma, chociaż ilość zarezerwowanego miejsca w eeprom jest poprawna. Jak więc prawidłowo powinienem zbudować strukturę dla takich danych? Generalnie krótko mówiąc - jak to powinno być "zgodnie ze sztuką" zrobione?
  • Pomocny post
    #11 15823880
    grko
    Poziom 33  
    JacekCz napisał:
    GrzegorzKostka napisał:
    @Piotrus_999 Niby po co przerabać skrypt linkera? Można to zrobić na kilka sposobów bez tego.


    A po co w ogóle coś "mieszać" a nie "po bożemu" ?


    Co po bożemu? Modyfikacja skryptu linkera jest po bożemu?

    @excray
    Wymusić adres możesz np tak:

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


    Linker pozwoli wtedy tylko na jedna instancje struktury.

    Sposób numer 2. Nie twożysz żadnej zmiennej w z atrybutem EEMEM tylko wskaźnk:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #12 15823882
    JacekCz
    Poziom 42  
    Takie na kolanie (nie kompilowałem)

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


    A tak naprawdę to problem zmiennej pod adresem zero skąd się wziął?

    Dodano po 1 [minuty]:

    GrzegorzKostka napisał:
    JacekCz napisał:
    GrzegorzKostka napisał:
    @Piotrus_999 Niby po co przerabać skrypt linkera? Można to zrobić na kilka sposobów bez tego.


    A po co w ogóle coś "mieszać" a nie "po bożemu" ?


    Co po bożemu? Modyfikacjia skryptu linkera jest po bożemu?

    Nie. Napisanie tego normalnie od początku. Niech działanie wynika ze źródeł w języku.

    Poza standardem C w dialektach uP są zwykle jakieś rozszerzenia do deklarowania adresu. Może tym obskoczy komórkę zero. Nie jestem przygotowany co do platformy.
  • Pomocny post
    #13 15823944
    tmf
    VIP Zasłużony dla elektroda
    Problem z komórką zero zapewne wynika z tego, że szczególnie starsze ATmegi, przy niepewnym zasilaniu lubią nadpisywać tą komórkę - rejestr adresowy EEPROM zawiera zero, stąd ten problem. Ale rozwiązaniem jest raczej zabezpieczenie procka, przed działaniem przy napięciu spoza zakresu poprawnej pracy, czyli wykorzystanie układu BOD. Wtedy problem znika.
    BTW, jeśli problem byłby systemowy, to IMHO prościej zmodyfikować domyślny skrypt linkera. Jednorazowa zmiana adresu EEPROM i zapominamy o problemach we wszystkich projektach. W końcu do tego m.in. służy skrypt linkera. Zabawy w tworzenie struktur z nieużywanym polem są IMHO udziwnieniem. Ale jak piszę, to dotyczy stytuacji, w której problem z komórką 0 dotyczyłby każdego projektu.
  • #14 15823989
    excray
    Poziom 41  
    Dziękuję wszystkim za pomoc. Szczególnie kolegom @GrzegorzKostka i @JacekCz których przykłady otworzyły mi oczy. Pozostałym kolegom również dziękuję za odpowiedzi. Jak to mówią "miło mądrego posłuchać". Gdyby ktoś się zastanawiał co było źle w moim poprzednim listingu, to problem był w tym, że źle się odwoływałem do tych zmiennych a powinno być:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
    i tak dalej.
REKLAMA