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

Jak poprawnie umieścić funkcję w RAMie podczas aktualizacji firmware?

13 Mar 2010 15:53 5020 44
Najlepsze odpowiedzi

Jak umieścić funkcję w RAM-ie na ARM7/GCC, żeby mogła działać podczas kasowania i programowania FLASH-a?

Trzeba oznaczyć funkcję atrybutem `section(".fastrun")` oraz `long_call` zarówno w deklaracji, jak i w definicji, a w skrypcie linkera dodać nową sekcję `.fastrun` wewnątrz obszaru RAM/data, np. `*(.fastrun)`, zamiast próbować wkładać kod bezpośrednio do `.data` [#7825418][#7825460][#7828091][#7828883] Samo użycie `.data` dla kodu daje ostrzeżenie `ignoring changed section attributes for .data`, więc poprawnym rozwiązaniem jest osobna sekcja dla funkcji, tylko mapowana do RAM [#7824306][#7828295] Jeśli wywołanie jest dalekie od RAM-u, `long_call` albo opcja kompilacji `-mlong-calls` jest potrzebna; bez niej linker może tworzyć veneer, ale z nią wywołanie zadziała poprawnie [#7826136][#7828091] Weryfikować trzeba to w `.lss` albo `.dmp`, bo w `.map` nie zawsze widać takie funkcje; w działającym przykładzie funkcja pojawia się pod adresem `0x40000000` [#7828091][#7828883] Przy aktualizacji przez IAP trzeba też zostawić wolne ostatnie 32 bajty RAM, bo procedury programowania FLASH-a z nich korzystają [#7826888]
Wygenerowane przez model językowy.
REKLAMA
  • #1 7823658
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • Pomocny post
    #2 7824306
    Zbych_
    Poziom 25  
    Posty: 456
    Pomógł: 81
    Ocena: 6
    Na początek odszukaj nazwy funkcji w pliku *.map (dodaj opcję -Map=$blabla.map,--cref do linkowania jeśli jej nie masz), żeby się upewnić, że adresy są z zakresu zajmowanego przez RAM. Na zrzutach ekranowych widać ostrzeżenie, że kompilator ignoruje atrybut z sekcją.
    Miałem podobny problem, dlatego zamiast umieszczać funkcje w sekcji data, stworzyłem nową sekcję specjalnie dla funkcji. Wymaga to oczywiście grzebnięcia w skrypcie linkera i pliku crt. Skrótowo opisałem to tutaj:

    http://groups.google.com/group/pl.comp.lang.c/msg/a7c53621c9865cd2

    PS. masz strasznie dużo warningów. Łatwo w tym gąszczu przegapić ważne rzeczy.
  • #3 7824338
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #4 7824526
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #5 7824724
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #6 7825215
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Zastanawiam się co masz w skrypcie linkera. Definiujesz funkcje w ramie, a RAM jakie atrybuty ma?
    Nie wiem na ile to jest aktualne, ale sprawdź jak to się robi Link

    Ważny jest chyba atrybut long_call ponieważ standardowy skok B, BL ma zakres ±32MB a RAM jest "trochę" dalej (1GB)
  • #7 7825258
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #8 7825418
    Zbych_
    Poziom 25  
    Posty: 456
    Pomógł: 81
    Ocena: 6
    Przykład od michalko12, robi to co ci na początku napisałem. Tworzona jest dodatkowa sekcja fastrun (w skrypcie linkera) i w tej sekcji są umieszczane funkcje. Sprytne jest umieszczenie tej sekcji wewnątrz sekcji data, co pozwala na pominięcie modyfikacji pliku crt.
  • Pomocny post
    #9 7825443
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • Pomocny post
    #10 7825460
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Zrobiłem test na przykładzie z innego wątku i to działa
    void __attribute__ ((long_call, section (".data"))) Delay1(unsigned int del_time);
    
    void __attribute__ ((long_call, section (".data"))) Delay1(unsigned int del_time)
    {
       for(unsigned int abc=0;abc<del_time;abc++);
       IO1PIN   ^=(1<<17);
    }
    Załączniki:
    • tmp.zip (26.21 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • Pomocny post
    #11 7825478
    Zbych_
    Poziom 25  
    Posty: 456
    Pomógł: 81
    Ocena: 6
    michalko12 napisał:
    Zrobiłem test na przykładzie z innego wątku i to działa


    A spróbuj dodać pod spodem drugą funkcję umieszczoną w RAMie.
  • #12 7825513
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #13 7825529
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Zbych_ napisał:
    michalko12 napisał:
    Zrobiłem test na przykładzie z innego wątku i to działa


    A spróbuj dodać pod spodem drugą funkcję umieszczoną w RAMie.


    Działa, ale z warningiem assemblera. Warning występuje w pierwszym i drugim przypadku.


    #include "LPC214x.h"
    
    void Timer0Handler (void) __attribute__((interrupt("IRQ")));
    void InitTimer0(void);
    void __attribute__ ((long_call, section (".data"))) Delay1(unsigned int del_time);
    void __attribute__ ((long_call, section (".data"))) Delay2(unsigned int del_time);
    
    void __attribute__ ((long_call, section (".data"))) Delay1(unsigned int del_time)
    {
       for(unsigned int abc=0;abc<del_time;abc++);
       IO1PIN   ^=(1<<17);
    }
    
    
    int main(void)
    {
        IO1DIR = (1<<16) |(1<<17) | (1<<18);
        InitTimer0();
        while (1);
    }
    
    void Timer0Handler(void)
    {
    
       IO1PIN   ^=(1<<16);
       Delay1 (200);
       Delay2 (1000);
       T0IR = 1;
        VICVectAddr = 0;
    }
    
    void InitTimer0(void)
    {
       T0PR = 0;   //Prescale Register
       T0MCR = 3;   //Match Control Register
       T0MR0 = 60000000;
       T0TCR = 2;   //Counter Reset
       T0TCR = 1;   //Counter Enable
       VICVectAddr0 = (unsigned int)Timer0Handler;
       VICVectCntl0 = (1<<5)|4 ;
       VICIntEnable |= (1<<4);
    }
    void __attribute__ ((long_call, section (".data"))) Delay2(unsigned int del_time)
    {
       for(unsigned int abc=0;abc<del_time;abc++);
       IO1PIN   ^=(1<<18);
    }


    Cytat:

    > "make" all
    arm-none-eabi-gcc -M -Wall -std=gnu99 -Os -mcpu=arm7tdmi-s -gstabs main.c > main.dep.$$; \ sed 's,\(main\)\.o[ :]*,\1.o main.dep : ,g' < main.dep.$$ > main.dep; \
    rm -f main.dep.$$
    Compiling C...
    arm-none-eabi-gcc -c -Wall -std=gnu99 -Os -mcpu=arm7tdmi-s -gstabs -Wa,-adhlns=main.lst main.c -o main.o
    C:\DOCUME~1\MK0917~1\USTAWI~1\Temp\ccnhP2vE.s: Assembler messages:
    C:\DOCUME~1\MK0917~1\USTAWI~1\Temp\ccnhP2vE.s:31: Warning: ignoring changed section attributes for .data

    Linking...
    arm-none-eabi-c++ -Wall -Os -mcpu=arm7tdmi-s -gstabs main.o startup.o -o test.elf -nostartfiles -Tlpc2142-rom.ld -Wl,-Map=test.map,--cref
    Converting to hex...
    arm-none-eabi-objcopy -O ihex -S test.elf test.hex
    Create extended listing...
    arm-none-eabi-objdump -h -S test.elf > test.lss

    > Process Exit Code: 0
    > Time Taken: 00:00
  • REKLAMA
  • Pomocny post
    #14 7825532
    Zbych_
    Poziom 25  
    Posty: 456
    Pomógł: 81
    Ocena: 6
    atom1477 napisał:
    No będzie ciężko. Bo podane przez Zbycha parametry mam podane, ale mimo to do pliki map nie trafia informacja o umieszczeniu funkcji.


    Ech, czytaj ze zrozumieniem. Nie chodzi o plik map, tylko o stworzenie sekcji specjalnie dla funkcji.
  • #15 7825548
    Konto nie istnieje
    Poziom 1  
  • #16 7825578
    Zbych_
    Poziom 25  
    Posty: 456
    Pomógł: 81
    Ocena: 6
    atom1477 napisał:
    Czytam ze zrozumieniem. Chodzi mi o to:
    albertb napisał:
    Czy tam trafia sprawdź. Zbych podał Ci jak.


    Sorry, masz rację.
  • #17 7825601
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #18 7826036
    Konto nie istnieje
    Konto nie istnieje  
  • #19 7826068
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #20 7826136
    Konto nie istnieje
    Konto nie istnieje  
  • #21 7826193
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #22 7826220
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    atom1477 napisał:
    Jeszcze przed założeniem tematu próbowałem bez static. Bez skutku.
    Bez static wywala błąd nawet przy jednokrotnym wywołaniu funkcji.
    Ja już skończyłem odchudzać program. Może zaraz go wrzucę.

    Spróbowałem ze static i jest tak jak mówi albertb. Po funkcjach ani śladu.
  • #23 7826275
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #24 7826888
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Może trochę zmienię temat, ale błędy tego typu:

    main.c:1834: error: conflicting types for 'Pisz_32x32_transparent_ram' 
    main.c:89: error: previous declaration of 'Pisz_32x32_transparent_ram' was here


    świadczą nie o tym, że funkcja jest we flashu zamiast w RAM, tylko o tym, że w dwóch różnych miejscach są zdefiniowane w różny sposób...

    Dalej idąc - to że IAP używa RAMu jest tutaj kluczową sprawą. IAP jest w swojej głupocie tak głupie, że wcale nie używają jednego kawałka:

    Cytat:
    5.2.9 RAM used by IAP command handler
    Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack
    usage in the user allocated stack space is 128 bytes and it grows downwards.


    O nie-używanie (albo dowolne inne zabezpieczenie, np skopiowanie i przywrócenie) tych obszarów trzeba zadbać...

    Kolejną ważną sprawą jest słynny w ARM7 nieużywany wektor przerwań, który służy do zabezpieczania przez wykonywaniem syfu. Jeśli nie znajdzie się tam poprawna wartość (szczegóły w manualu), to po resecie taki program nie będzie działać - po prostu bootloader (ten oryginalny) go nie uruchomi. Żaden kompilator nie generuje automatycznie tej wartości...

    4\/3!!
  • #25 7827174
    Konto nie istnieje
    Poziom 1  
  • #26 7827281
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Freddie Chopin napisał:
    Kolejną ważną sprawą jest słynny w ARM7 nieużywany wektor przerwań, który służy do zabezpieczania przez wykonywaniem syfu. Jeśli nie znajdzie się tam poprawna wartość (szczegóły w manualu), to po resecie taki program nie będzie działać - po prostu bootloader (ten oryginalny) go nie uruchomi. Żaden kompilator nie generuje automatycznie tej wartości...

    4\/3!!



    No właśnie, a jak zmusić OCD żeby ten wektor uzupełniał właściwą wartością przy zapisie za pomocą write_image. W komendzie "flash bank" jest calc_checksum, ale efekt jest tylko taki że OCD wywala warninga o niezgodnych tych wartościach.
  • Pomocny post
    #27 7827458
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Przeczytaj tego warninga całego. Mówi on, że jakbyś zrobił weryfikację, to będzie ona błędna, bo OpenOCD zmieniło wartość dla tego właśnie wektora na "odpowiednią".

    4\/3!!
  • #28 7827632
    michalko12
    Specjalista - Mikrokontrolery
    Posty: 3394
    Pomógł: 462
    Ocena: 321
    Freddie Chopin napisał:
    Przeczytaj tego warninga całego. Mówi on, że jakbyś zrobił weryfikację, to będzie ona błędna, bo OpenOCD zmieniło wartość dla tego właśnie wektora na "odpowiednią".

    4\/3!!

    Dzięki. Rzeczywiści, nie dokładnie zrozumiałem tego warninga, ale i tak nie zmienia to faktu, że program załadowany za pomocą OCD nie działa w odróżnieniu od programu załadowanego za pomocą FlashMagica, ale to w razie czego temat na inny wątek.
  • #29 7828056
    Konto nie istnieje
    Poziom 1  
  • #30 7828091
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Nie wiedzieć czemu, opcja long_call musi być dodana zarówno w deklaracji jak i w definicji, więc "na górze" zostaw jak masz, a na dole dostaw kompletny zestaw "__attribute__ ((...))" między "void" a nazwę funkcji.

    Dodam też, że w pliku *.map nie ma wylistowanych w takim przypadku funkcji umieszczonych w RAM, za to będą widoczne w pliku *.dmp. Widać też po dezassemblacji, że funkcja jest wywoływana w specjalny sposób (przez ldr, mov, bx) z adresów w RAM. (ciekawostka - opcja bez "long_call" zajmuje w tym pzypadku mniej)

    Niemniej jednak, BEZ "long_call" funkcja też zostanie wywołana prawidłowo, przez tzw. veneer, więc problem nie leży tutaj.

    4\/3!!

Podsumowanie tematu

✨ Użytkownik ma problem z umieszczaniem funkcji w pamięci RAM podczas aktualizacji firmware w systemie opartym na ARM7-TDMI. W trakcie dyskusji poruszono kwestie związane z linkowaniem funkcji do odpowiednich sekcji pamięci, a także z błędami kompilacji, które występują przy próbie użycia atrybutu long_call. Użytkownicy sugerują, aby stworzyć nową sekcję w skrypcie linkera dla funkcji, które mają być umieszczone w RAMie, co pozwala na uniknięcie problemów z umieszczaniem ich w sekcji .data. Wskazano również na konieczność wyłączenia przerwań oraz na znaczenie poprawnego ustawienia wektorów przerwań. Ostatecznie, po dodaniu sekcji fastrun, funkcje zaczęły być poprawnie umieszczane w RAMie, co rozwiązało problem.
Wygenerowane przez model językowy.
REKLAMA