Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[GCC ARM] Zmienna pod stalym adresem

TvWidget 09 Cze 2018 09:28 372 19
  • #1 09 Cze 2018 09:28
    TvWidget
    Poziom 32  

    Potrzebuję zagwarantować, że w kolejnych wersjach projektu jedna zmienna (uint32) zawsze zostanie umieszczona pod stałym adresem. Nie jest istotne jaki będzie to adres. Ważne jest jedynie aby się on już nie zmienił. W jaki sposób to uzyskać ?
    Czy mam dodać specjalną sekcję do pliku *.ld ?

    0 19
  • Pomocny post
    #2 09 Cze 2018 11:08
    michcior
    Poziom 30  

    Można przez sekcję w linkerze, ale można też taki banał:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Można też w linker skrypcie dopisać sobie co się chce: adres, stałą ...
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Kod: c
    Zaloguj się, aby zobaczyć kod




    I w kodzie użyć tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #3 09 Cze 2018 16:12
    TvWidget
    Poziom 32  

    Chodzi o wymianę firmware. Tą zmienną używa kod bootladera. W przyszłych wersjach programu kompilator nie może pod adresem tej zmiennej nic umieścić. Wskazanie w kodzie na sztywno jakiegoś wybranego adresu w pamięci RAM tego nie zapewni.

    0
  • #4 09 Cze 2018 16:27
    michcior
    Poziom 30  

    Chyba więc podałem przypadkiem dobry przykład. Sekcja .debug rezerwuje miejsce w pamięci, daje to pewność że inna zmienna nie dostanie tego adresu. Adres tego miejsca możesz ustawić na sztywno w inker skrypcie. "NOLOAD" gwarantuje że kompilator nie będzie tego inicjował. Zresztą, nie wiem jak u ciebie ale ja mam zawsze swój kod inicjalizacji zmiennych, więc mądrze napisany linker skrypt zapewni Ci stały adres i zabezpieczenie przed nadpisaniem zmiennej.
    Masz wszystko co potrzebujesz.

    0
  • #5 09 Cze 2018 19:16
    TvWidget
    Poziom 32  

    Zmodyfikowałam plik ld przesuwając w nim sekcję RAM o 4 bajty. Mam więc zarezerwowane na początku pamięci 4 bajty, których kompilator nie użyje.
    W kodzie wpisałem to co podałeś ale powoduje to "Syntax error".

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #7 09 Cze 2018 20:45
    TvWidget
    Poziom 32  

    Masz rację. Trochę się rozpędziłem.

    Załóżmy, że w kodzie wpiszę coś takiego:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Rozumiem, że mogę tego używać jak klasycznej zmiennej czyli np.:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Czy &FIXEDLOCVAR to wartość 0x10000000 ?

    0
  • #9 10 Cze 2018 07:20
    TvWidget
    Poziom 32  

    Pojawił się kolejny problem związany z tym o co pytałem się na początku. Kompilator umieszcza kod wybranych funkcji w pamięci RAM. Czy można jakoś zagwarantować, że będą one pod stałymi adresami ?

    0
  • #10 10 Cze 2018 08:16
    michcior
    Poziom 30  

    Tak oczywiście.
    Linker skrypt trzeba odpowiednio zmodyfikować, dbając o to by nie nałożyć na siebie sekcji, choć i tak kompilator tego nie zaakceptuje.
    np taka sekcja.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    i deklaracja funkcji:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Spowoduje umieszczenie tej funkcji w miejscu (plik wynikowy linkera, "mapfile"):

    Kod: c
    Zaloguj się, aby zobaczyć kod



    Inny przypadek:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Spowoduje umieszczenie wszystkich funkcji z pliku main.c w sekcji "mojalokalizacja". Używanie * jest konieczne, bo linker w tym miejscu porównuje pełną ścieżkę.

    0
  • #11 10 Cze 2018 10:42
    TvWidget
    Poziom 32  

    michcior napisał:
    Można przez sekcję w linkerze, ale można też taki banał:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Problem mogę rozwiązać bez modyfikacji pliku ld. Wystarczy, że przekażę do bootloadera aktualne wskaźniki do potrzebnych funkcji.
    Załóżmy, że chcę aby zmienna FIXEDLOCVAR to był wskaźnik do funkcji: int xyz(int a, int b);
    Jak ją mam zdefiniować ?
    #define FIXEDLOCVAR ...

    0
  • #12 10 Cze 2018 21:14
    michcior
    Poziom 30  

    Nie wiem co dokładnie chcesz zrobić, ale nie wchodząc w szczegóły, wskaźnik to wskaźnik, jak pilnujesz co wo nim jest to można używać typu void*, wstawiasz to zamiast "unsgined int" i po sprawie. Możesz zrobić też zdefiniować typ zmiennej będący wskaźnikiem na odpowiedni prototyp funkcji, co by było bardziej profesjonalnie.

    0
  • #13 24 Cze 2018 12:22
    3156217
    Użytkownik usunął konto  
  • #14 24 Cze 2018 19:14
    JacekCz
    Poziom 36  

    TvWidget napisał:
    Zmodyfikowałam plik ld przesuwając w nim sekcję RAM o 4 bajty. Mam więc zarezerwowane na początku pamięci 4 bajty, których kompilator nie użyje.
    W kodzie wpisałem to co podałeś ale powoduje to "Syntax error".

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Masz rację, daje syntax error.
    Nie da sie w standardowym klasycznym zakres języka zapewnić placement
    czytam coś, czego zamiarem by było "placement'", ale uzyskujemy najwyższy wskaźnik do naszego upragnionego morisca.

    dobrze grzebione fragmenty libnkera upchnie gdzie che.

    0
  • #15 24 Cze 2018 20:14
    TvWidget
    Poziom 32  

    Bootloader u mniej odpowiedzialny jest jedynie za wymianę właściwej aplikacji. Ma on tylko jedną funkcję widzianą na zewnątrz umieszczoną pod stały adresem w zarezerwowanej części Flash. Poprzednia aplikacja musi pobrać nowy firmware i wywołać tą funkcję. Jako jej parametr przekazuję tablicę wskaźników do funkcji jakie kompilator umieścił w pamięci RAM przy okazji tworzenia właściwej aplikacji. Nie wiem czy rozwiązanie jest zgodne ze sztuką programowania ale działa.

    0
  • #16 24 Cze 2018 22:42
    3156217
    Użytkownik usunął konto  
  • #17 24 Cze 2018 23:15
    michcior
    Poziom 30  

    Zależy jak bardzo nam zależy.
    Zwykle powinny być dostępne dwie wersje firmware-u do wymiany, nowa i stara. Musi być jakiś sposób na zaznaczenie która jest dobra i aktywna, np w EEPROM.
    I teraz tak, po załadowaniu nowej wersji, sprawdzeniu sumy kontrolnej (CRC, HASH etc.) zaznaczamy informację dla bootloadera że nowy firmware jest gotowy do uruchomienia. Bootloader przed uruchomieniem nowej wersji, kasuje ten znacznik, a na dobre ustawia go ponownie nowy firmware jak już ruszy na dobre.
    Robiłem takie rzeczy w STB i nikt nie mógł sobie pozwolić na to, że przez głupi błąd tysiące boxów zamienią się w cegłę. Tyle że tam sam bootloader ściągał firmware. Wszystko mogło nie działać ale re-flashing musiał być na 200%
    Generalnie, mechanizm musi być odporny na błędne dane, na to że nowy image nie działa, na to że podczas jakiegokolwiek etapu odłączone zostanie zasilanie. Jeśli dodamy do tego odporność na ataki (podmiana firmware, downgrade etc) to mamy niezłą "kobyłę", ale to się robi.

    0
  • #18 24 Cze 2018 23:34
    3156217
    Użytkownik usunął konto  
  • #19 25 Cze 2018 09:02
    TvWidget
    Poziom 32  

    1. Niestety mam mało pamięci Flash. Zmieści się w nim na styk tylko aktualna aplikacja i nowy firmware.
    2. Przesyłanie nowego firmware jest dość skomplikowane i może obywać się jedynie przez działającą aplikację. Nie da się dodać do bootloadera funkcji pobierania oprogramowania z powodu ograniczenia z p.1.
    3. Bootloader oczywiście sprawdza spójność firmware przed jego wymianą.
    4. Urządzenia jest zasilane bateryjnie. Najwięcej prądu pobiera w czasie przesyłania firmware. Jest mało prawdopodobne aby bateria padła akurat podczas kilku sekund programowania pamięci flash.
    5. Urządzenia nie są na tyle drogie aby utrata jakiegoś z nich była poważnym problemem.

    0
  • #20 25 Cze 2018 11:24
    3156217
    Użytkownik usunął konto  
  Szukaj w 5mln produktów