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.

[STM32][CodeSourcery]Deklaracja struktury w pamięci flash.

markosik20 08 Lis 2009 12:18 6941 21
  • #1 08 Lis 2009 12:18
    markosik20
    Poziom 33  

    Z racji że STM32 ma liniową pamięć oraz możliwość zapisu do flasha danych z poziomu aplikacji postanowiłem wykorzystać go do symulacji eeprom.
    Zapis danych do flash działa OK.
    Natomiast mam problem z zainicjowaniem struktury pod konkretnym adresem.

    Code:
    const D DFLASH __attribute__ ((section(".variables"))) =
    
       {
          {{40,20},26},
          {{0,0},10}
       };


    w makefile dodaje

    Code:
    LDFLAGS += -Wl,--section-start=.variables=0x08007C00


    mój STM32 ma 128kB flash'a.

    i niestety w tym miejscu pamięci są same 0xFF.. :(.
    Jeżeli w kodzie umieszczę

    Code:
    adr = (u32*)&DFLASH; 


    to podczas wgrywania w consoli wyskakuje

    Code:
    load
    
    Loading section .text, size 0x5c14 lma 0x8000000
    Loading section .data, size 0x4c lma 0x8005c14
    Loading section .variables, size 0x6 lma 0x8007c00
    Error finishing flash operation <<<<-----
    monitor soft_reset_halt


    jeżeli nie to kompilator gdzieś tworzy strukturę (bo dane są prawidłowe) ale na pewno nie w miejscu z sekcji variables.

    Czy w ogóle możliwe jest uzyskanie takich założeń?

    0 21
  • #2 08 Lis 2009 12:27
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Zamiast tworzyć sekcję poprzez makefile, stwórz ją normalnie w skrypcie linkera tak samo jak jest stworzona sekcja .text. Ewentualnie (jeśli koniecznie potrzebujesz mieć ją w konkretnym miejscu), to dodaj nowy region pamięci (tam gdzie zadeklarowany jest ram i rom), a swoją sekcję umieść właśnie tam.

    Problemem może też być to, że kompilator (a w zasadzie linker) może usuwać nieużywane zmienne.

    P.S. naprawdę nie należy używać soft_reset_halt jeśli nie jest ABSOLUTNIE potrzebne. I na STM32 naprawdę nie jest absolutnie potrzebne jeśli nie pomieszałeś czegoś z resetami.

    4\/3!!

    0
  • #3 08 Lis 2009 12:43
    markosik20
    Poziom 33  

    A więc wykasowałem to z makefila, w pliku .ld dodałem

    Code:
    MEMORY
    
    {
      SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K  /* also change _estack below */
      FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
      VAR   (rx) : ORIGIN = 0x0800FC00, LENGTH = 400
    }


    i w SECTIONS

    Code:
    .variables :
    
        {
            KEEP(*(.variables))
            *(.variables*)
         } > VAR


    Niestety mam dalej
    Code:
    Loading section .variables, size 0x6 lma 0x8007c00
    
    Error finishing flash operation

    0
  • Pomocny post
    #4 08 Lis 2009 13:49
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Przydałoby się jeszcze 2 rzeczy:
    1. zmniejszyć FLASH o odpowiednią wartość, tak aby na siebie nie najeżdżały - możesz od LENGTH odjąć ile tam potrzeba ... LENGTH = 128k - XXX

    2. Dodać profilaktycznie } > VAR AT > VAR

    Tym sposobem skrypt linkera będzie w 100% poprawny. Jeśli nadal będą jakieś błędy, to już nie po stronie linkera. Jeśli dalej coś nie będzie chodzić, to możesz spróbować wgrać plik hex (albo elf) bezpośrednio za pomocą OpenOCD (flash write_image erase ...) i zobaczyć co wtedy będzie się działo.

    4\/3!!

    0
  • #5 08 Lis 2009 16:09
    markosik20
    Poziom 33  

    Wielkie dzięki.
    Instrukcja load niestety nie działa w tego typu zastosowaniu.
    Wystarczy zmienić na

    Code:
    monitor flash write_image  erase main.bin 0x08000000


    Reasumując
    Gdyby ktoś kiedyś chciał zaimplementować używanie flasha jako eeprom:
    Można tak:

    Zainicjować sobie strukturę obojętnie jaką w sekcji variables.
    Code:

    #define FLASH_PAGE_SIZE    ((u16)0x400)
    const  D DFLASH __attribute__ ((section(".variables")))  =
       {
          {{40,20},29},         //contrast max,min,dat
          {{0x44,0x55},0x66},
          {{0x44,0x55},{0x66}},
          {{0x44,0x55},{0x66}}
       };


    gdzie

    Code:
    //------------------------------------------------------------
    
    typedef union _dd
    {
       signed long l;
       float f;
       signed short s;
       struct
       {
          unsigned char b0;
          unsigned char b1;
          unsigned char b2;
          unsigned char b3;
       }b;
    }dd;

    typedef struct
    {
       float max;
       float min;
    }r_float;

    typedef struct
    {
       unsigned char max;
       unsigned char min;
    }r_u8;

    typedef struct
    {
        r_float  range;
       dd    dat;
    }Flash_Date_u32;


    typedef struct
    {
        r_u8 range;
       unsigned char    dat;
    }Flash_Date_u8;

    typedef struct _D{
       Flash_Date_u8 Contrast;
       Flash_Date_u8 dd;
       Flash_Date_u32 cc;
       Flash_Date_u32 ee;

    }D;



    w skrypcie linkera dopisać
    Code:
    MEMORY
    
    {
      SRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K 
      FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 32K - 1024
      VAR   (rx) : ORIGIN = 0x08007C00, LENGTH = 1024
    }

    /* Section Definitions */
    SECTIONS
    {
       .variables :
        {
            KEEP(*(.variables))




            *(.variables*)
       } >VAR AT > VAR
    .......



    oraz kod zapisu do flasha
    Code:
    void Save_To_Flash (u8 *ptr_flash,u8 *ptr_ram,u8 size)
    
    {
       u32 i=0,j;
       u8 tab[FLASH_PAGE_SIZE];
       u8 *ptr_tab = (u8*)&DFLASH;

       do{
          if(ptr_flash == ptr_tab)
          {
             j = i+size;
             for(;i<j;i++)
             {
                tab[i] = *ptr_ram;
                ptr_ram++;
                ptr_tab++;
             }
          }
          else
          {
             tab[i] = *ptr_tab;
             ptr_tab++;
             i++;
          }

       }while(i<FLASH_PAGE_SIZE);

       /* Unlock the Flash Program Erase controller */
       FLASH_Unlock();
       /* Clear All pending flags */
       FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
       /* Erase the FLASH pages */
       FLASH_ErasePage((u32)&DFLASH);
       ptr_flash = (u8*)&DFLASH;
       i =0;
       do{
           j = tab[i+3];j<<=8;
           j |= tab[i+2];j<<=8;
           j |= tab[i+1];j<<=8;
           j |= tab[i];
          FLASH_ProgramWord((u32)ptr_flash, j);
           ptr_flash +=4;
           i+=4;

       }while(i<FLASH_PAGE_SIZE);

    }


    Używanie:

    Jeżeli chcemy odczytać używamy jak każdą inną zmienną,

    Code:
    setContrast_NK(DFLASH.Contrast.dat);


    jeżeli chcemy zapisać tworzymy zmienną taką jaką chcemy zapisać po czym wywołujemy funkcję jako:

    Code:
    Save_To_Flash((u8*)&DFLASH.Contrast.dat,(u8*)&D8.dat,sizeof(D8.dat));
    
    //DFLASH.Contrast.dat oryginalna zmienna w flash
    //D8.dat zmienna w której jest nowa wartość, gdzie D8  jest identyczną zmienną jak DFLASH.Contrast tylkoumieszczona w RAM
    //wielkość nowej zmiennej

    0
  • #6 08 Lis 2009 18:26
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Zamiast rzutować na u8 cały czas, prościej zrobić funkcję przyjmującą wskaźnik amorficzny - void* - wtedy funkcja "łyka" wszystko co jest wskaźnikiem.

    Wynik sizeof() technicznie jest typu size_t, a nie u8 (w końcu rozmiar może być większy niż 256 bajtów.

    Po skasowaniu strony nie musisz jej całej zapisywać, wystarczy zapisać tyle ile chcesz, a reszty nie ruszać.

    To KEEP() w skrypcie linkera też jest zbędne - jak zmienna będzie użyta, to linker jej nie wywali.

    Reszta kodu jest tak zakręcona, że w ogóle nie wiem o co chodzi.

    ST ma ciekawą notę na temat emulacji EEPROMu, która dodatkowo balansuje zużycie komórek pamięci -
    http://www.st.com/mcu/download2.php?file=1371...com/stonline/products/literature/an/13718.pdf
    http://www.st.com/mcu/download2.php?file=an25...nline/products/support/micro/files/an2594.zip

    Kod oczywiście korzysta z tej tępej biblioteki ST, a sam jest również wyjątkowo tępy, ale pokazuje ciekawą ideę. Jakby ktoś kiedyś chciał to mam zrobiony podobny algorytm, tyle że można zapisywać dane o dowolnej długości (mniejsze niż 1 strona pamięci of course [; )

    4\/3!!

    0
  • #7 08 Lis 2009 22:01
    markosik20
    Poziom 33  

    Z tym rzutowaniem to wolę jednak "ręcznie" to robić....jakoś tak wydaje mi się bezpieczniej.
    U mnie akurat sizeof zawsze będzie mniejsze niż 256 gdyż jest to po prostu ilość bajtów do zapisania jednej zmiennej/tablicy/struktury i nie zamierzam robić większych :wink:.
    Biblioteki z ST są zakręcone..niestety.
    Zaletą mojego pomysłu jest to że struktura ze zmiennymi jest jakby zrzutowana na pamięć więc dostęp do niej nie wymaga użycia żadnych dodatkowych funkcji. Poprostu używa się jej jakby była normalnie zadeklarowana we flash (oczywiście zmienna znajduje się w strukturze).
    Nie trzeba nic kopiować ani odczytywać a zapis to nic innego jak podanie odpowiednich wskaźników i ilości bajtów do zapisania.

    0
  • #8 08 Lis 2009 23:08
    Freddie Chopin
    Specjalista - Mikrokontrolery

    markosik20 napisał:
    Biblioteki z ST są zakręcone..niestety.

    Czy ja wiem? Są po prostu beznadziejne <: A jak się spojrzy na kod, to "OMG" <:

    Cytat:
    Zaletą mojego pomysłu jest to że struktura ze zmiennymi jest jakby zrzutowana na pamięć więc dostęp do niej nie wymaga użycia żadnych dodatkowych funkcji.

    W istocie, w tej emulacji EEPROMu o której pisałem powyżej dostęp faktycznie wymaga dodatkowych funkcji, ale po znalezieniu wskaźnika (zakładając, że nie będzie zapisu do EEPROMu w między czasie) można z niego od razu korzystać, a nie zawsze poprzez funkcje wyszukującą. Coś za coś - dzięki temu algorytmowi nie niszczy się tak pamięć <:

    4\/3!!

    0
  • #9 03 Gru 2009 13:36
    ddokupil
    Poziom 15  

    A bawił się ktoś z Was tymi gotowcami od ST? Nie mogę tego uruchomić za bardzo. Na jednym małym projekcie działa ale jak chcę to dorzucić do FreeRTOS to już nie bardzo. Mam Taki kod:

    Code:

    static void prvSetupHardware(void) {
       /* Start with the clocks in their expected state. */
       RCC_DeInit();

       /* Flash 0 wait state */
       //FLASH_SetLatency(FLASH_Latency_2);

       /* Enable HSE (high speed external clock). */
       RCC_HSEConfig(RCC_HSE_ON);

       HSEStartUpStatus = RCC_WaitForHSEStartUp();
       /* Wait till HSE is ready. */

       if (HSEStartUpStatus == SUCCESS) {
          /* Enable Prefetch Buffer */
          //FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

          /* Flash 0 wait state */
          FLASH_SetLatency(FLASH_Latency_2);

          /* 2 wait states required on the flash. */
          //*((unsigned portLONG *) 0x40022000) = 0x02;

          /* HCLK = SYSCLK */
          RCC_HCLKConfig(RCC_SYSCLK_Div1);

          /* PCLK2 = HCLK */
          RCC_PCLK2Config(RCC_HCLK_Div1);

          /* PCLK1 = HCLK/2 */
          RCC_PCLK1Config(RCC_HCLK_Div2);

          /* PLLCLK = 8MHz * 9 = 72 MHz. */
          RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

          /* Enable PLL. */
          RCC_PLLCmd(ENABLE);

          /* Wait till PLL is ready. */
          while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
          }

          /* Select PLL as system clock source. */
          RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

          /* Wait till PLL is used as system clock source. */
          while (RCC_GetSYSCLKSource() != 0x08) {
          }
       }


    i

    Code:

       /* Setup the hardware */
       prvSetupHardware();

       /* Setup the USART1 */
       prvSetupUSART();

       /* Unlock the Flash Program Erase controller */
       FLASH_Unlock();
       //FLASH->KEYR = 0x45670123;
       //FLASH->KEYR = 0xCDEF89AB;

       /* EEPROM Init */
       EE_Init();


    Program wiesza się na EE_Init();
    Jeśli zakomentuję FLASH_Unlock(); to EE_Init(); wykonuje się i zwraca prawidłowy wynik no ale oczywiście nic nie zmienia w pamięci i zapis zwraca błąd a odczytana wartość to jest zawsze 0 (logiczne).

    Możliwe, że mam to tak ustawione, że EE_Init(); zmienia coś gdzieś gdzie mam kod programu i dlatego się wiesza?
    Procesor to STM32F103VET6 (512kB) a program po skompilowaniu ma ≈130kB
    Emulację chcę wsadzić do dema FreeRTOS: Link

    0
  • #10 03 Gru 2009 22:44
    ddokupil
    Poziom 15  

    Poprzedni post już nie jest ważny. Dla potomnych tylko napiszę, że początek pamięci pod emulację był nastawiony od 64kB a program zajmuje 130kB. Przestawienie go na 256kB rozwiązało problem i wszystko śmiga. Trzeba zedytować pierwszą wartość #define w pliku eeprom.h. Bodajże z 8010000 na 8040000. (Nie mam kodu teraz pod ręką)

    0
  • #11 09 Lut 2010 20:50
    ciastek4
    Poziom 13  

    Hej,
    Podpinam się pod posta. Próbowałem wrzucić funkcję pod wskazanym adresem, ale mi się nie udało :). Postanowiłem wrzucić zatem jakąś zmienną pod wskazany adres no i z podobnym rezultatem. Tak jak w poście postępuję:

    Code:
    MEMORY
    
    {
       rom (rx)   : org = 0x08000000, len = 128k - 18k
       BOOT(rx)   : org = 0x0801B800, len = 18k
       ram (rwx)   : org = 0x20000000, len = 48k
    }

    Code:
    .boot :
    
       {
          KEEP(*(.boot))
          *(.boot*)
          
       } > BOOT AT > BOOT

    oraz
    Code:
    typedef struct {
    
       int i,j,k,l;
    }test2;

    const test2 test_pamieci __attribute__ ((section(".boot"))) = {0x01,0x2,0x3,0x4 };


    Makefile oraz linkier script jest od "Freddie Chopin".
    W pliku *.map znajduję tą sekcję, ale pod debuggerem mam zmienne i,j,k,l są 0xFFFFFF czyli -1 (U2). W pliku *.hex widzę, że niby ten adres powinien być zapisany ponieważ:
    Code:
    :10B80000010000000200000003000000040000002E

    jednak nie jest on wrzucany do flasha. Jakieś pomysły co może być nie tak?

    0
  • #12 09 Lut 2010 21:37
    markosik20
    Poziom 33  

    Jeżeli u siebie wykorzystuję komendę

    Code:
     load
    do wgrywania programu to nie działa (load z tego co wiem korzysta z pliku elf).
    Muszę wgrać plik bin poprzez
    Code:
    monitor flash write_image  erase main.bin 0x08000000 bin

    0
  • #13 11 Lut 2010 19:42
    ciastek4
    Poziom 13  

    Mógłbyś mnie jeszcze nakierować co mogę robić nie tak, ponieważ nie chce mi się wgrywać nawet plik bin czy hex(zmieniam końcówkę na ihex). Flash nie jest zmieniana;/. Nawet nie jest kasowana, ponieważ jest stary program.


    [STM32][CodeSourcery]Deklaracja struktury w pamięci flash.

    jeżeli ostatnią linijkę zastąpię load to flash jest podmieniana.

    BTW. Nie wiem również jak można wytłumaczyć zachowanie procesora w chwili wgrania nowego oprogramowania ( load ). Po zatrzymaniu na pierwszej instrukcji kolejna powoduje skok do obsługi przerwania HardFault. Zatrzymanie i ponowne wejście do debuggera ( bez komendy load) uruchamia procesor w trybie dbg z nowym programem.
    Po wgraniu komendą load dostaję :

    [STM32][CodeSourcery]Deklaracja struktury w pamięci flash.

    Jakieś pomysły ?

    0
  • #14 11 Lut 2010 20:04
    markosik20
    Poziom 33  

    Code:
    target remote localhost:3333
    
    monitor reset halt
    #load
    monitor flash write_image  erase main.bin 0x08000000 bin


    Pokaż co masz w konsoli.

    0
  • #15 11 Lut 2010 20:33
    ciastek4
    Poziom 13  

    Code:
    Info : device id = 0x10016418
    
    Info : flash size = 128kbytes
    Info : JTAG tap: stm32.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3)
    Info : JTAG Tap/device matched
    Info : JTAG tap: stm32.bs tap/device found: 0x06418041 (mfg: 0x020, part: 0x6418, ver: 0x0)
    Info : JTAG Tap/device matched
    target state: halted
    target halted due to debug-request, current mode: Thread
    xPSR: 0x01000000 pc: 0x080001e4
    auto erase enabled
    Error: couldn't open stm32_proj.bin



    [STM32][CodeSourcery]Deklaracja struktury w pamięci flash.

    Jak powiedzieć gdb, gdzie jest plik do wgrania?

    0
  • #17 11 Lut 2010 20:56
    ciastek4
    Poziom 13  

    Dalej to samo nie wiadać pliku;/ Gdzie mógłbym jeszcze coś sknocić;/

    0
  • #18 11 Lut 2010 22:46
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Po co masz "klikniętą" opcję Halt w debuggerze? Wyłącz to koniecznie, bo ona jest zbędna, a może szkodzić.

    W OpenOCD 0.3.1 jest bug, który polega na tym, że pierwszy "load" po włączeniu zasilania STM32 się nie udaje (przynajmniej na JTAGu na USB, choć pewnie na innych też, bo to nie kwestia JTAGa raczej). Drugi i kolejne już jest OK. Nie powinno to dotyczyć jednak wgrywania poprzez write_image.

    Trochę więcej info o tym bugu - https://lists.berlios.de/pipermail/openocd-development/2010-January/014222.html

    Tak czy siak uważam, że rozwiązywanie problemów poprzez "zamień load na write_image" jest rozwiązaniem w stylu voodoo - u mnie ZAWSZE load działa - cokolwiek by to nie było - program w asm, w c, w c++ z wyjątkami, cokolwiek.

    Co do pytania "gdzie coś sknociłeś" - OpenOCD ma coś takiego jak "Working directory" i to właśnie tam szuka tego pliku, skoro nie podałeś całej ścieżki. Założę się teraz, że ten working directory nie jest wcale katalogiem projektu...

    Jak kto woli kombinować, to proszę, ale wg mnie load działa ZAWSZE, a jak ktoś ma z tym problemy (i nie jest to bug o którym piszę powyżej), to problem leży gdzie indziej i pewnie kiedyś tam pojawi się w jeszcze innej postaci.

    Aha - już chyba w 100 tematach pisałem, że pomiędzy "reset" + "halt" a "reset halt" jest bardzo duża różnica. Polega ona w skrócie na tym, że procesor pomiędzy "reset" a "halt" może sobie zrobić co chce - np zablokować zapis do flasha, wyłączyć JTAGa, przestawić zegary , zawiesić się itp. Zaś po "reset halt" procesor nic nie może zrobić (mówmy tylko o STM32) i jest wtedy zatrzymany natychmiast po zresetowaniu - tak jak być powinno.

    4\/3!!

    0
  • #19 12 Lut 2010 09:18
    markosik20
    Poziom 33  

    Freddie Chopin napisał:

    Tak czy siak uważam, że rozwiązywanie problemów poprzez "zamień load na write_image" jest rozwiązaniem w stylu voodoo - u mnie ZAWSZE load działa


    Hmm, jeszcze raz sprawdzę, ale u mnie w konsoli (komenda load) podczas wgrywania flasha nie wyskakuje sekcja .variables (znajduje się ona pod koniec flasha). Nie wiem czy to możliwe ale wygląda to tak jakby flash został załadowany tylko programem użytkowym.
    Nie wiem dlaczego sądzisz że rozwiązanie zaczerpnięte z dokumentacji OpenOCD są "egzotyczne" ?.....skoro są zaimplementowane to chyba do czegoś zostały stworzone (no chyba że to kompatybilność wsteczna :wink:).

    0
  • #20 12 Lut 2010 09:21
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Nie mówię, że używanie write_image to bezsens, ale używanie go zamiast load, jeśli tak czy siak używasz gdb...

    W Twojej sytuacji jeszcze powiedzmy sprawa jest do zrozumienia - masz dodatkową - niestandardową - sekcję, którą chcesz załadować. Niemniej jednak nie jest to rozwiązanie każdego problemu, zwłaszcza w standardowych sytuacjach.

    4\/3!!

    0
  • #21 13 Lut 2010 10:14
    ciastek4
    Poziom 13  

    Dziękuję za wyczerpujące wyjaśnienie. Rozwiązało mi to problem w paru rzeczach, z którymi się borykałem. Co do wpisywania struktury w pamięć wreszcie udało mi się to zrobić tak jak opisuje ten temat. Funkcja load co prawda przypisuje tej zmiennej zadeklarowany adres, ale już nie wpisuje tam wartości przypisanych w definicji zmiennej.
    Wpisanie do flasha *.bin lub *.hex rozwiązuje sprawę ( tak jak mówił markosik20).

    Dziękuję jeszcze raz

    0
  • #22 13 Lut 2010 15:11
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Tak BTW to przez write_image można ładować też pliki .elf - to bez różnicy.

    4\/3!!

    0