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

[Rozwiązano] [AVR][C]{AtmelStudio] Stała w pamięci programu pod konkretnym adresem

INTEII 16 Lip 2018 13:31 1089 22
REKLAMA
  • #1 17331899
    INTEII
    Poziom 14  
    Witam,

    Mam pytanie, jak umieścić stałą w pamięci programu tuż za tablicą wektorów przerwań, tak, żeby zawsze znajdowała się pod tym samym adresem bez względu na inne stałe i teksty w programie? W WINAVR w "makefile", to było dość proste, a w AtmelStudio 6 nie potrafię sobie z tym poradzić.

    Dziękuję za pomoc.
    Pozdrawiam.
  • REKLAMA
  • Pomocny post
    #2 17331912
    tmf
    VIP Zasłużony dla elektroda
    Robisz to tak samo jak przy pomocy makefile - tyle, że w AS definiujesz nową sekcję i określasz jej adres. Następnie używasz atrybutów gcc, aby wskazać, żeby określona zmienna/funkcja się w tej sekcji znalazła. Resztę robi linker.
  • REKLAMA
  • Pomocny post
    #3 17332144
    Konto nie istnieje
    Konto nie istnieje  
  • #4 17333408
    INTEII
    Poziom 14  
    Dziękuje za odpowiedzi.

    Panowie, tak właśnie to robiłem, chyba, że gdzieś nie dostrzegam swojego błędu...

    Otwieram: AtmelStudio->Project->Properties->(otwiera się okno projektu)->Toolchain->AVR/GNU Linker->Miscellaneous i tu wpisuje:
    -Wl,-section-start=.test=0x50


    Próbowałem również: AtmelStudio->Project->Properties->(otwiera się okno projektu)->Toolchain->AVR/GNU Linker->Memory Settings->FLASH segment:


    W programie stałą deklaruję tak:
    const UInt16  stalaFlash __attribute__ ((section (".test"))) = 0xABCD; 


    Po kompilacji stała zawsze znajduje się w tym samym miejscu, tak jakbym nic nie zmienił.
    Proszę o pomoc.
  • #5 17333459
    tmf
    VIP Zasłużony dla elektroda
    Tam ma być --section-start. Jeśli nadal nie działa to pokaż linię wywołania linkera (to co pokazuje AS podczas kompilacji i wygenerowany plik MAP, w któym masz m.in. opis sekcji.
  • #6 17333471
    Konto nie istnieje
    Konto nie istnieje  
  • #7 17333532
    INTEII
    Poziom 14  
    Nie zauważyłem braku myślnika przy wklejaniu. Ogólnie było dobrze, tylko kombinowałem na różne sposoby.

    Linker:
    -Wl,-Map="Test.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mmcu=atmega32a -Wl,--section-start=.test=0x50


    MAP:
    Nie wklejam całego pliku, bo ma 2212 linii. Jedyne dwa wystąpienia słowa "test" w tym pliku to:
    
    
    .....................
    
    Memory Configuration
    
    Name             Origin             Length             Attributes
    text             0x00000000         0x00020000         xr
    data             0x00800060         0x0000ffa0         rw !x
    eeprom           0x00810000         0x00010000         rw !x
    fuse             0x00820000         0x00000400         rw !x
    lock             0x00830000         0x00000400         rw !x
    signature        0x00840000         0x00000400         rw !x
    user_signatures  0x00850000         0x00000400         rw !x
    *default*        0x00000000         0xffffffff
    
    Linker script and memory map
    
    LOAD .................
    LOAD ExternalLibraries/ADC.o
    LOAD ExternalLibraries/Conversion.o
    LOAD ExternalLibraries/CRC08.o
    LOAD ExternalLibraries/CRC16.o
    LOAD ExternalLibraries/Delay.o
    LOAD ExternalLibraries/DS18B20.o
    LOAD ExternalLibraries/Encoder.o
    LOAD ExternalLibraries/GraphicAlfanumeric.o
    LOAD ExternalLibraries/Menu.o
    LOAD ExternalLibraries/OneWire.o
    LOAD ExternalLibraries/PCF8563.o
    LOAD ExternalLibraries/HD44780.o
    LOAD ExternalLibraries/TWI.o
    LOAD Program.o
    START GROUP
    LOAD .................
    END GROUP
    Address of section .test set to 0x50
    START GROUP
    LOAD .................
    LOAD .................
    LOAD .................
    END GROUP
    
    .hash
     *(.hash)
    
    ........
    
    .debug_macro
     *(.debug_macro)
    OUTPUT(URH-B-04.elf elf32-avr)
    LOAD linker stubs
    
    .test           0x00000050        0x0
    -koniec pliku-
    


    W miejscach "LOAD ................." zamiast kropek są ścieżki do plików, ale nie da się ich dodać, bo strona generuje błąd.
    W miejscach "........................." nieistotne fragmenty pliku.
  • #8 17333563
    tmf
    VIP Zasłużony dla elektroda
    No i jest ok. W MAP masz segment .test rozpoczynający się od 0x50. Ponieważ przekazujesz do linkera gc-sections, więc sekcje nieużywane są usuwane, więc jeśli do zmiennej którą umieszczasz w tej sekcji nie ma referencji to całość jest usuwana. Pamiętaj też, że początek RAM w AVR ustawiony jest na 0x00800000, więc jeśli ta sekcja ma wylądować w RAM to adres powienien wynosić 0x00800050.
  • REKLAMA
  • Pomocny post
    #9 17333634
    Andrzej__S
    Poziom 28  
    tmf napisał:
    Ponieważ przekazujesz do linkera gc-sections, więc sekcje nieużywane są usuwane, więc jeśli do zmiennej którą umieszczasz w tej sekcji nie ma referencji to całość jest usuwana.

    Tylko jeśli do zmiennej będzie referencja i sekcja nie zostanie usunięta, to linker nie zgłosi konfliktu, że sekcje .test i .text się nakładają?
    Czy linker może zagnieździć sekcję .test wewnątrz sekcji .text (przy standardowych skryptach linkera)?
    Sekcja .text zaczyna się od 0x0000 i na pewno nie skończy się przed 0x50.
  • REKLAMA
  • #10 17333640
    INTEII
    Poziom 14  
    hahaha, dobra znalazłem problem:
    const UInt32 PROGMEM Flash_Application_Address_End __attribute__ ((section (".test"))) = 0x00000000;

    Wam dobrze pisałem, a w programie nie usunąłem "PROGMEM" :)

    Wszystkim bardzo dziękuję za pomoc.
    Pozdrawiam.

    Dodano po 7 [minuty]:

    Andrzej__S napisał:
    tmf napisał:
    Ponieważ przekazujesz do linkera gc-sections, więc sekcje nieużywane są usuwane, więc jeśli do zmiennej którą umieszczasz w tej sekcji nie ma referencji to całość jest usuwana.

    Tylko jeśli do zmiennej będzie referencja i sekcja nie zostanie usunięta, to linker nie zgłosi konfliktu, że sekcje .test i .text się nakładają?
    Czy linker może zagnieździć sekcję .test wewnątrz sekcji .text (przy standardowych skryptach linkera)?
    Sekcja .text zaczyna się od 0x0000 i na pewno nie skończy się przed 0x50.


    Tak, kolega "Andrzej__S" ma rację. Sekcja "Text" nie została pofragmentowana, a przesunięcie jej powoduje również przesunięcie wektorów przerwań.
  • #11 17333673
    Konto nie istnieje
    Konto nie istnieje  
  • #12 17333716
    INTEII
    Poziom 14  
    W stałej umieszczam adres końca programu, pod którym znajduje się CRC aplikacji - w ten sposób sprawdzam integralność oprogramowania. Często zdarza się, że wgrywając seryjnie duży program pod koniec wystąpi jakiś problem i nie zostanie on w całości załadowany. Wtedy w pośpiechu nie zawsze zauważy się w konsoli, że coś poszło nie tak, szczególnie, że program "działa". Dzięki takiemu prostemu mechanizmowi można wyeliminować ten problem.
  • #13 17333748
    Konto nie istnieje
    Konto nie istnieje  
  • #14 17333760
    INTEII
    Poziom 14  
    CRC umieszczam na końcu aplikacji z automatu za pomocą programu "srec_cat". Ten sam program we wskazanym przeze mnie miejscu (znanym jeszcze przed kompilacją), nadpisuje daną stałą adresem końca programu. Jest to bardzo wygodne rozwiązanie, bo adres takiej stałej wpisuje się tylko raz i działa ono niezależnie od dalszych zmian wprowadzanych w programie. Teraz oczywiście też to działa, ale np. zdefiniowanie nowego napisu lub choćby zmiana długości już istniejącego powoduje przesuniecie tej stałej w pamięci i trzeba znowu ręcznie korygować jej adres.
  • Pomocny post
    #15 17333773
    Konto nie istnieje
    Konto nie istnieje  
  • #16 17333795
    tmf
    VIP Zasłużony dla elektroda
    nowyARM napisał:
    AVR-GCC ma taka właściwość, że umieszcza stałe zaraz za obszarem wektorów przerwań.


    To nie jest żadna właściwość avr-gcc, lecz kwestia użytego skryptu linkera. Poza tym w zależności co się używa (progmem czy __flash), takie stałe mogą być na początku lub na końcu programu.
    nowyARM napisał:
    Kolejna właściwość, to ta, ze stała zadeklarowana jako pierwsza znajdzie się zaraz za wektorami przerwań. Na tym nie można juz tak na 100% polegać, bo może jakaś biblioteka używa stałych i nie ma gwarancji, że jakiś include nie spowoduje, że nasz stała zostanie umieszczona gdzieś dalej.


    Na tym zupełnienie można polegać. Nie chodzi o jakieś biblioteki, tylko o prostą właściwość linkera - umieszcza stałe po kolei (przynajmniej w obecnej wersji, ale to nie jest objęte standardem i ktoś dla fantazji może to zmienić), w zależności od kolejności linkowania plików. A ta kolejność może się zmieniać, więc i sposób rozmieszczenia stałych się zmieni.
    nowyARM napisał:
    Umieść CRC w EEPROM. Nad adresami w EEPROM łatwo zapanować używając struktury. EEPROM wgrywasz razem z FLASH używając plików ELF.


    Po co? Kol. @INTEII używa poprawnego rozwiązania - srec_cat i liczenia CRC przez program wywoływany z makefile. To rozwiązanie umożliwia pełną automatyzację. Użycie EEPROM to zbędna komplikacja, poza tym sens CRC jest taki, aby był on związany z plikiem z ktrórego jest liczony. Dzięki temu po wgraniu hexa mamy od razu wgrane powiązane z nim CRC, co jest rozwiązaniem idiotoodpornym. Mieszanie do tego EEPROM wymaga zaangażowania dwóch różnych plików, zwiększa też ryzyko, że zmienimy FLASH, bez odpowiedniej zmiany EEPROM i przede wszystkim utrudnia życie jeśli w EEPROM trzymane są inne dane (na etapie programowania, EEPROM byłby kasowany aby wprowadzić nowe CRC).
    Jedyne co można rozważyć, to w pewnych okolicznościach umieszczenie CRC na końcu pamięci FLASH MCU. Dzięki temu nie trzeba definiować dodatkowych sekcji, wystarczy wskaźnik w programie, a w hexie po prostu automatycznie dodany CRC na koniec FLASH.

    Dodano po 2 [minuty]:

    nowyARM napisał:
    Zadeklaruj jakiś ciąg znaków a za nim CRC, np "#CRC=$". Używałem takiego rozwiązania do odszukiwania nazwy, wersji programu i właśnie CRC. Program szukał ciągu znaków w obszarze od wektorów przerwań do np 0x1000.
    W przypadku CRC powstaje problem jak je tam umieścić i pominąć przy obliczaniu CRC? Zrobiłem proste CRC ADD na koniec negacja. Program sprawdzając CRC odejmował CRC odczytane z FLASH.


    Używasz niewłaściwych narzędzi, a potem dzielnie rozwiązujesz normalnie nieistniejące problemy...

    Dodano po 52 [sekundy]:

    nowyARM napisał:
    Co do wpisania CRC do FLASH, to nie wiedzę innej opcji jak wczytanie do edytora hex (np Hexplorer), zmodyfikowanie i zapisanie.


    Proponuję lepiej poznać dostępne narzędzia. Do manipulacji na hexach (i nie tylko) w toolchainie są odpowiednie narzędzia - srecord.
  • #17 17333861
    INTEII
    Poziom 14  
    Ja też uważam, że wykorzystanie EEPROM było by niepotrzebnym skomplikowaniem problemu, ale pomysł "nowyARM" niewątpliwie ciekawy.
    Tmf - w tej chwili właśnie tak rozwiązałem problem (tymczasowo), tzn. nie do końca, bo CRC zostawiłem na końcu programu, a tylko adres CRC umieszczam na końcu pamięci Flash.
  • Pomocny post
    #18 17334242
    tmf
    VIP Zasłużony dla elektroda
    Użyj sekcji .progmem.gcc - położona jest ona tuż za tablicą wektorów przerwań i standardowo nic w niej nie ma, a więc ma stały dla danego procesora adres początku.
  • Pomocny post
    #19 17334358
    Konto nie istnieje
    Konto nie istnieje  
  • #20 17334718
    INTEII
    Poziom 14  
    Nie wiem o co chodzi Koledze "Marek_Skalski", bo przecież interpretacja Kolegi "NowyARM" jest jak najbardziej poprawna. O tym samym pisał również Kolega "Tmf". Osobiście nie wiem, co jest umieszczane w tej sekcji, ale gdy zostaną tam kiedykolwiek dołączone jakieś dane, to stała w pamięci programu zostanie przesunięta względem początku sekcji ".progmem.gcc". To bardzo prosty dowód na to, że Kolega "NowyARM" ma rację.

    Wracając do tematu, jutro spróbuję zmodyfikować pliki linker-a w następujący sposób:
      /* Internal text space or external memory.  */
      .text   :
      {
        *(.vectors)
        KEEP(*(.vectors))
        *(.MOJA_SEKCJA)
        KEEP(*(.MOJA_SEKCJA))
        /* For data that needs to reside in the lower 64k of progmem.  */
        *(.progmem.gcc*)
        *(.progmem*)

    O ile się nie mylę, to powinno to działać na zasadzie "ukrytej" sekcji - jeżeli umieszczę w niej stałą, to zostanie ona dołączona tuż za wektorami przerwań; jeżeli nie, to zostanie ona zignorowana przez linker. Czy to poprawny tok rozumowania?
  • Pomocny post
    #21 17334886
    tmf
    VIP Zasłużony dla elektroda
    INTEII napisał:
    Nie wiem o co chodzi Koledze "Marek_Skalski", bo przecież interpretacja Kolegi "NowyARM" jest jak najbardziej poprawna. O tym samym pisał również Kolega "Tmf". Osobiście nie wiem, co jest umieszczane w tej sekcji, ale gdy zostaną tam kiedykolwiek dołączone jakieś dane, to stała w pamięci programu zostanie przesunięta względem początku sekcji ".progmem.gcc". To bardzo prosty dowód na to, że Kolega "NowyARM" ma rację.


    To jest pusta sekcja, niewykorzystywana przez bieżące avr-libc, bo nie ma ku temu powodu. Więc szansa, że coś nagle się tam pojawi przesuwając twoje dane jest marginalna. W każdym razie wymagałoby to zmiany AVR-libc lub skryptów linkera, więc sama od siebie się nie zrobi. W przeciwieństwie do kolejności linkowania plików obiektowych, która to kolejność zmieni się np. po dodaniu nowego pliku do projektu, lub nawet podczas kolejnych kompilacji (w zależności od sposobu linkowania określonego w makefile).
    Proste rozwiązanie już ci podałem, w dodatku całkiem poprawne - umieszczenie CRC na końcu pamięci FLASH. W niczym to nie przeszkadza, nie wymaga kombinowania z sekcjami, srec dokładnie wie , gdzie umieścić CRC, a aplikacja wie skąd je pobrać... Sprawę można jeszcze bardziej uprościć, zapewniając (np. przy pomocy srec), aby niewykorzystane obszary FLASH miały określoną wartość (np. 0xFF). W takiej sytuacji wystarczy umieścić wyliczone dla całego FLASH CRC na końcu, a w aplikacji olać info o wielkości zajętej pamięci i liczyć CRC dla całego FLASH. W takiej sytuacji można wykorzystać właściwość CRC polegającą na tym, ze tak wyliczone CRC dla bloku z CRC ma zawsze wartość 0 lub -1.
    INTEII napisał:
    O ile się nie mylę, to powinno to działać na zasadzie "ukrytej" sekcji - jeżeli umieszczę w niej stałą, to zostanie ona dołączona tuż za wektorami przerwań; jeżeli nie, to zostanie ona zignorowana przez linker. Czy to poprawny tok rozumowania?


    Zadziała. Tylko: osobiśnie nie lubię modyfikować skryptów linkera o ile nie jest to absolutnie niezbędne. Zmodyfikowany skrypt należy przegrać do katalogu projektu i ponieważ nie będzie on w domyślnej lokacji, należy przekazać do linkera jego położenie (dodatkowy parametr). To już IMHO lepiej z wywołania linkera dodać sekcję tak jak to robiłeś wcześniej i przesunąć początek sekcji .text robiąc miejsce na CRC. Tylko po co, skoro gotowe rozwiązanie już jest?
  • Pomocny post
    #22 17335317
    Konto nie istnieje
    Konto nie istnieje  
  • #23 17336952
    INTEII
    Poziom 14  
    Udało mi się rozwiązać problem w satysfakcjonujący dla mnie sposób - utworzenie własnej sekcji w skrypcie linker-a. Słowem wyjaśnienia dla "Tmf", obliczanie CRC z całej pamięci Flash wydaje mi się być nieeleganckim rozwiązaniem, zbędnie wydłużającym czas uruchomienia programu głównego. Oczywiście nie wszystkim może spodobać się przyjęta przeze mnie metoda, ale w moim konkretnym przypadku zalety przewyższają wady. Dla potomnych - w wielu przypadkach można wykorzystać sekcję " .progmem.gcc", o czym pisał Kolega "Tmf" kilka postów wyżej.

    Dziękuje wszystkim za zainteresowanie tematem i odpowiedzi.
    Pozdrawiam.
REKLAMA