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][WinAVR][C] Alokacja zmiennej inicjalizowanej w pamięci EEPROM

INTEII 21 Cze 2012 00:04 5443 52
Najlepsze odpowiedzi

Jak zainicjalizować wybraną komórkę EEPROM pod konkretnym adresem, aby WinAVR wygenerował plik .eep?

Nie da się tego zrobić wprost pojedynczą deklaracją `EEMEM`; trzeba sterować rozmieszczeniem danych przez strukturę, tablicę albo własną sekcję linkera. Najprostszy wariant to zadeklarować jedną dużą tablicę EEPROM, np. `uint8_t ee[512] EEMEM`, i odwoływać się do komórek przez indeksy. Jeśli bootloader i program główny mają korzystać z tych samych adresów, najlepiej użyć współdzielonej struktury dołączanej do obu kompilacji, bo wtedy pola mają te same offsety. Trzecie rozwiązanie to ręcznie wydzielić osobną sekcję EEPROM, np. `.myeeprom`, i przypisać do niej wybrane zmienne pod konkretnym adresem [#11025615]
Wygenerowane przez model językowy.
REKLAMA
  • #1 11024737
    INTEII
    Poziom 14  
    Posty: 131
    Pomógł: 10
    Ocena: 18
    Witam,

    Mam następujący problem...

    Jeżeli chcę zainicjalizować zmienną w EEPROM robię to tak:
    unsigned char test EEMEM = 0x11     //generowany jest wtedy dodatkowy plik .eep z inicjalizacją pamięci EEPROM


    Powyższy kod posiada jedną wadę - kompilator zmienną "test" zapisuje w pierwszej wolnej komórce EEPROM-u, a mi zależy na tym, żeby "test" była zapisana np. pod adresem 0x0010.

    Stąd moje pytanie: Jak zainicjalizować dowolną komórkę pamięci tak, żeby kompilator wygenerował odpowiedni plik .eep?

    Dziękuję i pozdrawiam,
    INTEII.
  • REKLAMA
  • #2 11024787
    mirekk36
    Poziom 42  
    Posty: 9195
    Pomógł: 964
    Ocena: 2289
    W ogóle nie należy tak robić żeby inicjalizować komórki w pamięci EEPROM w taki bezpośredni sposób w języku C. Zdecydowanie najlepiej zrób to poprzez definiowanie zmiennych w strukturach a najlepiej jednej dużej. A jeśli chcesz pominąć np kilka pierwszych żeby tam nie lokować ważnych zmiennych dla programu to w takie strukturze jako pierwszą definiujesz np jakąś zmienną DUMMY np typu uint_64t - czyli masz już 8 bajtów z głowy ;)
  • #3 11024967
    INTEII
    Poziom 14  
    Posty: 131
    Pomógł: 10
    Ocena: 18
    Wszystko było by fajnie, gdyby jeden program wiedział coś o drugim.

    Mówiąc dokładniej bootloader w moim przypadku będzie korzystał z EEPROM-u i muszę mieć pewność, że program główny nie nadpisze jego danych, z których sam będzie mógł korzystać.
  • #4 11025011
    mirekk36
    Poziom 42  
    Posty: 9195
    Pomógł: 964
    Ocena: 2289
    No dobrze a z ciekawości jaką informację chcesz przekazywać między tymi programami ? pytam bo może da radę to spokojnie inaczej rozwiązać a ty tego nie widzisz być może ? Nie mówię że na pewno ale hmmm może coś udałoby się pomyśleć ;)
  • #5 11025208
    INTEII
    Poziom 14  
    Posty: 131
    Pomógł: 10
    Ocena: 18
    Z samym przekazaniem danych nie ma kłopotu, bo przecież mogę zapisywać i odczytywać je w dowolnych komórkach EEPROM-mu. Zależy mi na inicjalizacji dowolnej komórki pamięci, tak żeby wygenerować odpowiedni plik .eep.

    Zasada działania mojego programu jest bardzo prosta:
    1. w chwili wgrania bootloadera do uK w komórce pamięci EEPROM np. 0x0100 jest wartość 0x01 oznaczająca brak programu głównego - pg.
    2. w chwili poprawnego zaprogramowania pg do 0x0100 komórki pamięci EEPROM wpisywana jest wartość 0x00.
    3. jeżeli w trakcie działania pg zostanie wywołana procedura jego aktualizacji, to po raz kolejny komórka przyjmie wartość 0x01 - w razie przerwania wgrywania pg, bootloader wie, że program jest uszkodzony.
  • #6 11025226
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #7 11025272
    INTEII
    Poziom 14  
    Posty: 131
    Pomógł: 10
    Ocena: 18
    Niestety pamięci flash z poziomu pg nie mogę zmieniać.
  • #8 11025286
    Konto nie istnieje
    Konto nie istnieje  
  • #9 11025344
    LordBlick
    VIP Zasłużony dla elektroda
    Posty: 5438
    Pomógł: 549
    Ocena: 69
    INTEII napisał:
    jeżeli w trakcie działania pg zostanie wywołana procedura jego aktualizacji, to po raz kolejny komórka przyjmie wartość 0x01 - w razie przerwania wgrywania pg, bootloader wie, że program jest uszkodzony.
    Słabe. Suma kontrolna by się zdała(CRC-8/CRC-16)... ;)
  • #10 11025474
    mirekk36
    Poziom 42  
    Posty: 9195
    Pomógł: 964
    Ocena: 2289
    INTEII napisał:
    Z samym przekazaniem danych nie ma kłopotu, bo przecież mogę zapisywać i odczytywać je w dowolnych komórkach EEPROM-mu. Zależy mi na inicjalizacji dowolnej komórki pamięci, tak żeby wygenerować odpowiedni plik .eep.

    Zasada działania mojego programu jest bardzo prosta:
    1. w chwili wgrania bootloadera do uK w komórce pamięci EEPROM np. 0x0100 jest wartość 0x01 oznaczająca brak programu głównego - pg.
    2. w chwili poprawnego zaprogramowania pg do 0x0100 komórki pamięci EEPROM wpisywana jest wartość 0x00.
    3. jeżeli w trakcie działania pg zostanie wywołana procedura jego aktualizacji, to po raz kolejny komórka przyjmie wartość 0x01 - w razie przerwania wgrywania pg, bootloader wie, że program jest uszkodzony.


    No dobrze dobrze - tylko po co te całe zabiegi i jeszcze do tego dręczenie biednej pamięci EEPROM ;) co chcesz tym zyskać że np jak napisałeś

    A zabezpieczenie i sprawdzanie czy się dobrze wgrało ??? spójrz na to co wyżej pisze kolega - suma kontrolna CRC i po zawodach.

    "bootloader wie, że program jest uszkodzony" ;)

    a co da taka wiedza bootloaderowi ??? ;) zastanów się dobrze - bo moim zdaniem wymyślasz troszkę rozwiązania totalnie naokoło samemu sobie utrudniając życie.

    Jeśli program (wsad)/ firmware się źle wgrał to co to obchodzi bootloadera ??? Toż po najbliższym resecie ma on podjąć znowu swoje zadanie czyli sprawdzać czy przypadkiem nie wysyła ktoś nowego firmware. Jasne wiązać się to może z jakąś zwłoką i oczekiwaniem przez chwilę na dane ale można to uzależnić od jakiegoś stanu na pinie mikrokontrolera i żadnej zwłoki nie musisz wtedy robić.

    Tak więc jak się dobrze zastanowisz to szybko zrezygnujesz z tego pomysłu. Bootloader ma nie myśleć - ona ma tylko wykonywać ślepo to co ma do zrobienia ;) jak dobry żołnierz
  • #11 11025551
    INTEII
    Poziom 14  
    Posty: 131
    Pomógł: 10
    Ocena: 18
    Hmmm... napisałem na początku posta (może nie bezpośrednio), że chce zapanować nad tym, w której komórce EEPROM-u co się znajdzie. Potrzebne mi to do tego, żeby program główny, w którym będą tworzone dane w EEPROM nie nadpisał mi tych z bootloadera. EEPROM - bedzie służył do komunikacji bootloadera z pg i do sygnalizacji poprawnie wgranego oprogramowania.

    Poleceniami:
    eeprom_write_byte(ADDRESS_FLAG_EMPTY, LV_TRUE);
    eeprom_read_byte(ADDRESS_FLAG_EMPTY);
    


    Panuje nad tym, co gdzie się znajduje, ale nie potrafie zainicjalizować pamięci. Wartościami domyślnymi!

    Teraz zauważyłem odpowiedź kolegi "mirekk36":

    Ma to do tego, że program powinien bez względu na to czy uK został zresetowany, czy nie pozostać w bootloaderze (który uruchamiany jest z pg), aż do czasu poprawnego wgrania softu! Tzn. po resecie uruchamia sie bootloader sprawdza flagę w EEPROM jeśli 1 to czeka na wgranie programu jeśli 0 to przechodzi do pg. W chwili wywołania polecenia aktualizacji softu program robi jmp do pamieci programu bootloadera - flaga jest ustawiana na 1 i rozpoczyna sie wgrywanie softu. Jeśli np. podczas ładowania programu ktoś wyłączy zasilanie, flaga informuje bootloader o tym, że soft jest uszkodzony - czeka na ponowne wgranie softu!

    PS. nie wnikam już w sam sposób przesyłania pakietów - tak, suma CRC16 jest niezbędna!
  • REKLAMA
  • #12 11025615
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2203
    Możesz nad tym zapanować na kilka sposobów:
    1. Taki sobie. Definiujesz tablicę o wielkości EEPROM, np. uint8_t ee[512] EEMEM, do komórek odwołujesz się normalnie przez indeksy, wszystko jest ok, tyle, że kompilator nie alokuje automatycznie zmiennych.
    2. Robisz współdzieloną strukturę, która odzwierciedla pamięć EEPROM i co ważne, jest dołączana przy kompilowaniu zarówno bootloadera, jak i programu głównego - wtedy masz gwarancję, że pola o tej samej nazwie będą miały takie same offsety. Kompilator zajmuje się alokacją i działa ok. Tyle, że wszystkie zmienne w EEPROM muszą być znane na etapie kompilacji obu programów. No chyba, że pokomplikujesz.
    3. Robisz oddzielne sekcje w EEPROM, np. sekcja EEMEM1 zaczyna się od adresu 0, EEMEM2 od jakiegoś wyższego. Przydzielasz ręcznie zmienne do sekcji i sprawa załatwiona.
  • #13 11025649
    Konto nie istnieje
    Konto nie istnieje  
  • #15 11026972
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2203
    albertb napisał:
    To są rozwiązania dla tematu.
    Ale pomysł na bootloader to jednak kiepski ;-(
    Tak jak mirekk36 uważam, że rozwiązanie jest nieprzemyślane.

    Albert


    Niby dlaczego? To jeden z normalnych sposobów pisania bootloadera z sygnalizacją stanu wsadu. Można to zrobić inaczej, np. CRC dla aplikacji i sprawdzanie przez bootloader przed uruchomieniem aplikacji czy jest poprawne. Ale to trochę komplikuje narzędzia - m.in. trzeba się bawić srec i dodawać to CRC, w dodatku trzeba przesuwać sekcję .text żeby bootloader wiedział gdzie to CRC jest. Taka zabawa z flagą w EEPROM żeby wiedzieć w jakim stanie jest kod aplikacji jest jedną z opcji przedstawianych przez osoby, które uważam, ża guru w tym temacie. Oczywiście ma to wady, ale IMHO nie takie, żeby to rozwiązanie dyskwalifikować.

    Dodano po 3 [minuty]:

    mirekk36 napisał:
    INTEII napisał:
    Z samym przekazaniem danych nie ma kłopotu, bo przecież mogę zapisywać i odczytywać je w dowolnych komórkach EEPROM-mu. Zależy mi na inicjalizacji dowolnej komórki pamięci, tak żeby wygenerować odpowiedni plik .eep.

    Zasada działania mojego programu jest bardzo prosta:
    1. w chwili wgrania bootloadera do uK w komórce pamięci EEPROM np. 0x0100 jest wartość 0x01 oznaczająca brak programu głównego - pg.
    2. w chwili poprawnego zaprogramowania pg do 0x0100 komórki pamięci EEPROM wpisywana jest wartość 0x00.
    3. jeżeli w trakcie działania pg zostanie wywołana procedura jego aktualizacji, to po raz kolejny komórka przyjmie wartość 0x01 - w razie przerwania wgrywania pg, bootloader wie, że program jest uszkodzony.


    No dobrze dobrze - tylko po co te całe zabiegi i jeszcze do tego dręczenie biednej pamięci EEPROM ;) co chcesz tym zyskać że np jak napisałeś

    A zabezpieczenie i sprawdzanie czy się dobrze wgrało ??? spójrz na to co wyżej pisze kolega - suma kontrolna CRC i po zawodach.

    "bootloader wie, że program jest uszkodzony" ;)

    a co da taka wiedza bootloaderowi ??? ;) zastanów się dobrze - bo moim zdaniem wymyślasz troszkę rozwiązania totalnie naokoło samemu sobie utrudniając życie.

    Jeśli program (wsad)/ firmware się źle wgrał to co to obchodzi bootloadera ??? Toż po najbliższym resecie ma on podjąć znowu swoje zadanie czyli sprawdzać czy przypadkiem nie wysyła ktoś nowego firmware. Jasne wiązać się to może z jakąś zwłoką i oczekiwaniem przez chwilę na dane ale można to uzależnić od jakiegoś stanu na pinie mikrokontrolera i żadnej zwłoki nie musisz wtedy robić.

    Tak więc jak się dobrze zastanowisz to szybko zrezygnujesz z tego pomysłu. Bootloader ma nie myśleć - ona ma tylko wykonywać ślepo to co ma do zrobienia ;) jak dobry żołnierz


    Czyli proponujesz, żeby bootloader w ciemno uruchamiał przypadkowy kod? Ciekawa idea. Oczywiście możliwa do zaakceptowania w amatorskich konstrukcjach, ale nie spotkałem się z takim podejściem w profesjonalnych systemach. Zawsze po wgraniu nowego wsadu należy sprawdzić jego integralność, obojętnie czy przez CRC, czy innymi sposobami (np. flagi w EEPROM). Im mniej się zostawi przypadkowi tym lepiej.
  • #16 11027469
    Konto nie istnieje
    Konto nie istnieje  
  • #17 11027971
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2203
    A kto pisze, że aplikacja może wykrzaczyć bootloader? Odniosłem raczej wrażenie, że autorowi chodzi o to, aby bootloader nie uruchomił nieprawidłowo wgranej aplikacji.
  • #18 11028023
    Konto nie istnieje
    Konto nie istnieje  
  • #19 11028103
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2203
    Nie wiem czy wie, bo niby skąd? IMHO to właśnie po to ta komórka pamięci, żeby sygnalizować stan. Typu - aplikacja wczytana, aktualizacja przerwana itd. To, że aplikacja ma do tej komórki dostęp to w tym przypadku zaleta - można zrobić dodatkowe zabezpieczenie polegające na tym, że na pewnych etapach jej uruchomienia zmieniana jest wartość tej komórki, dzięki czemu bootloader wie, że wszystko jest ok. W sumie jaki sens byłoby pisać aplikację, która "oszukuje" bootloader? No może miałoby, ale, żeby się przed tym zabezpieczyć na platformie jaką jest AVR to jedyna możliwość to wprowadzenie szyfrowania i podpisów, dzięki czemu bootloader nie wczyta niezaufanej (w sensie nie podpisanej przez zaufanego wydawcę) aplikacji.
  • REKLAMA
  • #20 11028125
    Konto nie istnieje
    Konto nie istnieje  
  • #21 11028134
    tmf
    VIP Zasłużony dla elektroda
    Posty: 14318
    Pomógł: 2090
    Ocena: 2203
    Ale jak kto zapisze? Różnica jest taka, że aplikacja może nie mieć uprawnień do zapisu do FLASH. Więc te dwie metody nie są równoważne. Poza tym zapis do FLASH odbywa się stronami i wymaga kasowania strony. Do EEPROM można zapisywać bit po bicie. Po prostu różnica w wygodzie.
  • #22 11028227
    Konto nie istnieje
    Konto nie istnieje  
  • #23 11028275
    INTEII
    Poziom 14  
    Posty: 131
    Pomógł: 10
    Ocena: 18
    Witam,

    Widzę, że kolega "tmf" świetnie rozumie o co mi chodzi. Dziwny wydaje mi się fakt, że tak prosty problem może sprawiać kłopoty w jego zrozumieniu.

    "Albert" - jak Ty byś zabezpieczył się przed błędnym wgraniem aplikacji? Przypominam, że bootloader wykonywany jest po resecie (włączeniu zasilania) lub w chwili gdy np. z RS232 zostanie wydane takie polecenie. Przy czym włączenie zasilania należy traktować, jak zdarzenie losowe - urządzenie ma działać nieprzerwanie! Skąd bootloader np. po zaniku zasilania ma wiedzieć czy aplikacja została wgrana poprawnie?

    Pozdrawiam,
    Piotr.

    Po paru minutach...

    Najbardziej do gustu przypadło mi połączenie rozwiązań 2 i 3 kolegi "tmf"; w związku z tym mam natomiast następujący problem:

    Tworze sobie nową sekcję w EEPROM:
    ...
    
    LDFLAGS +=  -Wl,--section-start=.myeeprom=0x81000A
    
    ...
    
    %.eep: %.elf
    	@echo
    	@echo $(MSG_EEPROM) $@
    	-$(OBJCOPY) \
        -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 \
        -j .myeeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .myeeprom=0x000A \
        --no-change-warnings -O $(FORMAT) $< $@ || exit 0


    i tworze zmienne w pg:

    unsigned int test1 EEMEM = 0xAAAA;
    unsigned int test2 SECTION(".myeeprom") = 0xBBBB;


    W plikach .map i .eep widzę, że zmienne zostały poprawnie umieszczone - pod wybranymi adresami - jednak w podsumowaniu widoczna jest tylko ta w sekcji EEMEM:

    Size after:
    AVR Memory Usage
    ----------------
    Device: atmega32
    
    Program:     472 bytes (1.4% Full)
    (.text + .data + .bootloader)
    
    Data:          5 bytes (0.2% Full)
    (.data + .bss + .noinit)
    
    EEPROM:        2 bytes (0.2% Full)
    (.eeprom)


    Da się to jakoś naprawić?
  • #24 11028333
    Konto nie istnieje
    Konto nie istnieje  
  • #25 11028369
    INTEII
    Poziom 14  
    Posty: 131
    Pomógł: 10
    Ocena: 18
    W moim rozwiązaniu domyślnie przy wgraniu bootloadera zmienna w EEPROM przyjmie wartość np. 0x01. W chwili uruchomienia uK bootloader sprawdza flagę - jeżeli 0x01 to brak programu i czeka na wgranie nowego softu. Jeżeli soft został wgrany poprawnie, to zmienna w EEPROM przyjmuje np. wartość 0x00 i wykonywany jest JMP 0.

    Teraz w chwili np. zaniku zasilania, bootloadr "wie", że program działa poprawnie i od razu przechodzi do jego wykonywania.

    Po wysłaniu np. po RS232 polecenia flash-owania, uK NAJPIERW ustawia flagę w EEPROM na 0x01 - brak programu, a dopiero później wykonuje skok do bootloadera!

    W tej chwili rozpoczyna się wgrywanie aplikacji, które jeśli zostanie przerwane z jakiegokolwiek powodu, flaga zawsze ma wartość 0x01 - brak programu - program główny nigdy się nie wykona - a przynajmniej do czasu poprawnego wgrania softu!
  • #26 11028394
    Konto nie istnieje
    Konto nie istnieje  
  • #27 11028398
    Konto nie istnieje
    Poziom 1  
  • #28 11028414
    INTEII
    Poziom 14  
    Posty: 131
    Pomógł: 10
    Ocena: 18
    "albertb" - ustawia ją bootloader, bo tylko on "wie" czy wgrano poprawnie aplikację!

    "atom1477" - właśnie o to chodzi! Mechanizm samego wgrywania kodu to jedno, a drugie wiedzieć, czy w ogóle on tam jest!
  • #29 11028417
    Konto nie istnieje
    Konto nie istnieje  
  • #30 11028434
    INTEII
    Poziom 14  
    Posty: 131
    Pomógł: 10
    Ocena: 18
    "albertb" - załóżmy, że nie ma! więc wracamy do 1 posta (hahahaha), jak nie nadpisać EEPROM-u?

    Parę postów wyżej pokazałem jak tworzę nową sekcję w EEPROM-ie i problem z tym związany... Możecie mi pomóc?

Podsumowanie tematu

✨ Użytkownik ma problem z inicjalizacją zmiennej w pamięci EEPROM w mikrokontrolerach AVR, chcąc zapisać ją pod konkretnym adresem, a nie w pierwszej wolnej komórce. W odpowiedziach poruszane są różne metody zarządzania pamięcią EEPROM, w tym definiowanie struktur, tablic oraz sekcji pamięci. Istotnym zagadnieniem jest zapewnienie, że bootloader nie nadpisze danych aplikacji, co wymaga starannego planowania alokacji pamięci. Użytkownicy sugerują użycie sum kontrolnych (CRC) do weryfikacji poprawności wgrania aplikacji oraz rozważają, czy flagi w EEPROM są odpowiednim rozwiązaniem. Dyskusja dotyczy również kwestii zabezpieczeń i niezależności bootloadera od aplikacji.
Wygenerowane przez model językowy.
REKLAMA