www.elektronik.si
STM32 - FLASH pomnilnik

www.elektronik.si -> ARM arhitektura

Avtor: zazKraj: Ljubljana PrispevekObjavljeno: Sre Sep 12, 2018 12:41 pm    Naslov sporočila:  STM32 - FLASH pomnilnik
----------------------------------------------------------------------------
Pozdravljeni

ukvarjam se s SW za napravo (temelji na STM32F407VG), ki mora omogočati, da si uporabnik preko parametrov konfigurira napravo po svojih potrebah/željah. Teh parametrov bo približno 10 zagotovo pa ne več kot 15. Kot parameter si predstavljam 16-bitno spremenljivko v kateri bo shranjena neka vrednost.

Parametre želim shraniti v flash pomnilniku, saj se morajo parametri tudi po izklopu naprave ohraniti do naslednjega vklopa. V linker skripti sem dodal nov memory region CONFIG in ga lociral na zadnji 11. sektor FLASH pomnilnika, obstoječi FLASH memory region, pa sem zmanjšal za velikost sektorja 11 (128KB).

Original:
Koda:
/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 1024K
}


Modificiran memory region:
Koda:
/* Specify the memory areas */
MEMORY
{
RAM (xrw)         : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (rw)     : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 896K
CONFIG (rw)      : ORIGIN = 0x80E0000, LENGTH = 128K
}


Dodal sem memory section v CONFIG memory region.
Koda:
  .config :
  {
     *(.config.TEMP_MAX)
     *(.config*)
  } > CONFIG


V .c datoteki, kjer imam spremenljivke deklarirane sem eno od spremenljivk poskušal postaviti v novo ustvarjeni memory region s ukazom:
Koda:
__attribute__((section(".config.TEMP_MAX"))) uint16_t TEMP_MAX;


Projekt se po modifikaciji normalno prevede ampak Build Analyzer orodje, ki ga ponuja TrueSTUDIO IDE zazna nov memory region ampak je le ta prazen.

Lahko kdo pomaga z nasvetom kaj počnem narobe?

Dodatek:
Nastavitve želim postaviti v ločen FLASH sektor, ker bo vrednosti možno modificirati med delovanjem naprave in bom na tem sektorju izvedel kvazi emulacijo EEPROM pomnilnika.

Avtor: zazKraj: Ljubljana PrispevekObjavljeno: Čet Sep 13, 2018 8:47 am    Naslov sporočila:  
----------------------------------------------------------------------------
Težavo sem odpravil. Posredujem odgovor, če bo mogoče še kdo naletel na isto težavo.

Koraki objavljeni v predhodni objavi so pravilni.

V nadaljevanju je potrebno spremenljivko TEMP_MAX še dejansko vpisati v FLASH pomnilnik. Za uspešno vpisovanje spremenljivke v FLASH pomnilnik pa je potrebno flash najprej odkleniti:

Koda:
HAL_FLASH_Unlock()


Pobrisati vse zastavice:

Koda:
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR);


Sektor pobrisati:

Koda:
FLASH_Erase_Sector(FLASH_SECTOR_11, VOLTAGE_RANGE_3);


Spremenljivko postaviti v flash:

Koda:
HAL_FLASH_Program(TYPEPROGRAM_WORD, &TEMP_MAX, TEMP_MAX);


Če smo z vpisovanjem zaključili flash ponovno zaklenemo:

Koda:
HAL_FLASH_Lock();


Pri tem pa se mi poraja vprašanje kam dejansko se ob prevajanju programa shrani TEMP_MAX spremenljivka preden jo prepišemo v flash.

Avtor: tilz0RKraj: Črnomelj PrispevekObjavljeno: Ned Sep 23, 2018 12:26 pm    Naslov sporočila:  
----------------------------------------------------------------------------
zaz, delo s temi attribute-i pri tebi nima smisla, če hočeš dinamično spreminjati vsebino v flashu. Smiselno pa je, da sectione delaš pri RAM-u, če jih rabiš.

Če ti direktno odgovorim, kam se shrani, potem je odgovor "je del flash binary datoteke, in se ne shrani na določen flash naslov, kot si ti navedel v section".

Drugače pa je dobra praksa, da se naredi eno strukturo, ki se celotna shrani v flash.

Koda:
// Struktura za tvoj flash
typedef struct {
    /* Control section */
    uint32_t magic;
    uint32_t version;
    /* Data section */
    int temp_max;
    int temp_min;
} flash_str_t;


Pri tem pa:
- magic: Vsebuje znano konstantno, s katero preveriš, če so nastavitve v flashu veljavne ali ne
- version: Trenutna verzija formata tvojih nastavitev. Vsakič, ko spremeniš format strukture (dodaš field, recimo humidity_max), ali pa odstraniš kakšen field (recimo temp_min te ne zanima več), povečaš številko v tvojem flashu.

Nekje v headerju določiš vrednosti, ki jih pričakuješ kot default za magic in version:

Koda:
#define FLASH_SETTINGS_START_ADDR     0x08001000 /* Določiš naslov, kje v flashu bos imel stranjene nastavitve */

#define FLASH_MAGIC      0x12345678
#define FLASH_VERSION    4 //Vsakic, ko posodobis flash_str_t strukturo, takrat povecas stevilko za 1


V tvojem programu na začetku narediš spremenljivko tipa flash_str_t strukture.

Koda:
//Recimo main.c

flash_str_t flash_settings;

void flash_settings_read(void);
void flash_settings_write(void);

int main(void) {
    //Preberi nastavitve na začetku programa in jih skopiraj v RAM
    flash_settings_read();
}

void
flash_settings_read(void) {
    //Preberes vrednosti iz flasha direktno v strukturo locirano v RAM-u
    memcpy(&flash_settings, (void *)FLASH_SETTINGS_START_ADDR, sizeof(flash_settings));

    //Preveris, ce so podatki veljavni:
    if (flash_settings.magic != FLASH_MAGIC ||   /* Flash se ni bil nikoli vpisan s strani aplikacije */
        flash_settings.version != FLASH_VERSION) { /* Flash format struktura se je spremenila in moramo resetirati vrednosti */
        //Nastavi default vrednosti
        flash_settings.magic = FLASH_MAGIC;
        flash_settings.version = FLASH_VERSION;

        flash_settings.temp_max = 120; //Default max temperature by app
        flash_settings.temp_min = -10; //Default min temperature by app

        //Write data back to flash
        flash_settings_write();
    }
}

void
flash_settings_write(void) {
    const uint8_t* data = (const void *)&flash_settings;   //Pointer na podatke za v flash
    size_t len = sizeof(flash_settings); //Velikost strukture za zapisat v flash
    uint32_t addr = FLASH_SETTINGS_START_ADDR;

    //Odkleni flash
    HAL_FLASH_Unlock()
   
    //Zbriši flash sector, ki ustreza FLASH_SETTINGS_START_ADDR naslovu

    //Zapiši vse podatke, tukaj pričakujem, da ima struktura 4-byte alignment v velikosti
    len = len >> 2;
    while (len-- > 0) {
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr, data);
        addr += 4;
    }

    //Zakleni flash
    HAL_FLASH_Lock();
}


Kasneje, vedno, ko bo MCU hotel spremeniti nastavitve in jih straniti v flash, narediš to:

Koda:
flash_settings.temp_max = ...;
flash_settings_write();


Tako imaš sedaj nove vrednosti v RAM-u in takoj imaš tudi write-back v flashu. RAM ti tukaj služi kot kakšen cache.

Zelo preprost example.

Stran 1 od 1

Powered by phpBB © 2001,2002 phpBB Group