cancel
Showing results for 
Search instead for 
Did you mean: 

How to place a structure in flash memory in read-only mode?

Alex Golubev
Associate II

I make a simple file system with 256 files. In the header I want to put data about the file system.

The data is presented as an array of structures:

typedef struct {
    const char name[20];
    const char textExtension[4];
    const uint32_t size;
    const uint32_t date;
    const uint32_t time;
    const uint32_t adrr;
    const uint32_t crc;
    const uint32_t reserve[5];
} headerFileList[256];

Well, everything seems to be just the address from where to get the data and the length, just in case crc. There will be files under the title.

The question is how you can place this array of structures strictly in flash memory. So that you can only read it, but modify it by writing commands to the flash.

I tried to do it like this:

headerFileList *HeaderFileList;

HeaderFileList = 0x08100000; // начало 2 банка флешь stm32h743

But I don’t know if all this is correct. I can't know how this can be done with attributes.

I work stm32cubeide.

9 REPLIES 9
KnarfB
Principal III

Not sure if I got your point.

headerFileList *const HeaderFileList = 0x08100000; // начало 2 банка флешь stm32h743

Tells the C compiler to treat your data read-only.

Because the data is in flash, it would not change, even if C code writes to it. A HardFault will happen. For writing you have to use the HAL flash API functions or equivalents.

hth

KnarfB

Alex Golubev
Associate II

Flash data will be modified by HAL flash API functions. The goal is to place the structure in ro so as not to waste RAM.

I see no difference between the files and the structure: just use the Flash API after the structure is filled and program it into the flash. Its only the pointer that exists in RAM. If this hurts, use a define instead of a variable.

Or: you can also put the variable in its own linker secion (which could be flash): https://stackoverflow.com/questions/4067811/how-to-place-a-variable-at-a-given-absolute-address-in-memory-with-gcc

Alex Golubev
Associate II

I added to .id

.mySegment 0x08100000: {KEEP (* (. MySection))}

defined the structure

.h file

typedef const struct {
    const char name[20];
    const char textExtension[4];
    const uint32_t size;
    const uint32_t date;
    const uint32_t time;
    const uint32_t adrr;
    const uint32_t crc;
    const uint32_t reserve[5];
} headerFileList[256];
 
extern headerFileList HeaderFileList[256];

.c file

headerFileList HeaderFileList[256] __attribute__((section(".mySection")));

looked the compiler placed the "headerFileList" structure in the rw area and increased the 'data' area. And I need a ro area

You must tell the linker in which region of the address space the mySection section should live.

The last 2k of 32kB Flash are used in this example:

MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 6K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 30K
  FLASH_VAR (rx)   : ORIGIN =ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 2K
}
 
...
 
.mySection:
{
      *(.mySection*);
} > FLASH_VAR

Alex Golubev
Associate II

I have a stm32h743 controller with 2 mbytes of flash memory. The controller has 2 memory banks of 1 MB each.

#define ADDR_FLASH_SECTOR_0_BANK1     ((uint32_t)0x08000000) /* Base @ of Sector 0, 128 Kbytes */
#define ADDR_FLASH_SECTOR_1_BANK1     ((uint32_t)0x08020000) /* Base @ of Sector 1, 128 Kbytes */
#define ADDR_FLASH_SECTOR_2_BANK1     ((uint32_t)0x08040000) /* Base @ of Sector 2, 128 Kbytes */
#define ADDR_FLASH_SECTOR_3_BANK1     ((uint32_t)0x08060000) /* Base @ of Sector 3, 128 Kbytes */
#define ADDR_FLASH_SECTOR_4_BANK1     ((uint32_t)0x08080000) /* Base @ of Sector 4, 128 Kbytes */
#define ADDR_FLASH_SECTOR_5_BANK1     ((uint32_t)0x080A0000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6_BANK1     ((uint32_t)0x080C0000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7_BANK1     ((uint32_t)0x080E0000) /* Base @ of Sector 7, 128 Kbytes */
 
/* Base address of the Flash sectors Bank 2 */
#define ADDR_FLASH_SECTOR_0_BANK2     ((uint32_t)0x08100000) /* Base @ of Sector 0, 128 Kbytes */
#define ADDR_FLASH_SECTOR_1_BANK2     ((uint32_t)0x08120000) /* Base @ of Sector 1, 128 Kbytes */
#define ADDR_FLASH_SECTOR_2_BANK2     ((uint32_t)0x08140000) /* Base @ of Sector 2, 128 Kbytes */
#define ADDR_FLASH_SECTOR_3_BANK2     ((uint32_t)0x08160000) /* Base @ of Sector 3, 128 Kbytes */
#define ADDR_FLASH_SECTOR_4_BANK2     ((uint32_t)0x08180000) /* Base @ of Sector 4, 128 Kbytes */
#define ADDR_FLASH_SECTOR_5_BANK2     ((uint32_t)0x081A0000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6_BANK2     ((uint32_t)0x081C0000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7_BANK2     ((uint32_t)0x081E0000) /* Base @ of Sector 7, 128 Kbytes */

The second bank of flash is used for the file system. There is a header at the beginning of the filesystem. The header consists of an array of structures of the form:

typedef const struct {
    const char name[20];
    const char textExtension[4];
    const uint32_t size;
    const uint32_t date;
    const uint32_t time;
    const uint32_t adrr;
    const uint32_t crc;
    const uint32_t reserve[5];
} headerFileList[256];

I want to place a plot in the flash area at address 0x08100000 in read-only mode. The files will be located below the header. The files must be accessible from the main program.

I need to place the structure at the beginning of the 2nd bank at 0x08100000 with a length of 16KB. Then extend the flash area.

MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 6K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 30K
  FLASH_VAR (rx)   : ORIGIN =ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 1K
 
  FLASH    (rx)    : ORIGIN(FLASH_VAR) + LENGTH(FLASH_VAR),   LENGTH = 1K  ///??????????????? 
}
 
...
 
.mySection:
{
      *(.mySection*);
} > FLASH_VAR

You may use absolute hex values if you prefer. https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html

Alex Golubev
Associate II

May I ask for an example?