Skip to main content
Lynn Linse
Associate III
December 29, 2016
Solved

Forcing static initialized arrays into FLASH (not in SRAM)

  • December 29, 2016
  • 5 replies
  • 1746 views
Posted on December 29, 2016 at 17:57

THIS ISN'T A QUESTION - IS A RESULT.

I was having issues getting some static arrays to stay in FLASH, not SRAM. Since they NEVER change, allowing them to load into SRAM just means the exist in both flash & SRAM (aka: init'd values copied to SRAM). Since I feel the full solution isn't trivially obvious, I'll record it here for others.

I am using AC6/STM System Workbench and STM32L152RE, so my solution might be specific to the CGG used and default linker scripts.

The simple array was easy - just adding the CONST caused &data_flags to be in the FLASH (0x080XXXXX range) instead of SRAM (0x200XXXXX range).

static const uint8_t data_flags[] = {

    (DS_FLAG_PROTECT),                                  // DB_COUNTERS_CTBOT

    (DS_FLAG_PROTECT),                                  // DB_COUNTERS_CTWDG

    (DS_FLAG_PROTECT | DS_FLAG_MIN),       // DB_COUNTERS_CTDLY

 ...

};

However, tables of strings proved more challenging. The working solution was this:

static const char const *data_tags[] __attribute__ ((section ('.rodata'))) = {

        'CT.BOT',                           // DB_COUNTERS_CTBOT

        'CT.WDG',                           // DB_COUNTERS_CTWDG

        'CT.DLY',                           // DB_COUNTERS_CTDLY

 ...

};

Despite the 2 x CONST, &data_tags continued to be in SRAM, as a table of FLASH pointers to constant strings. So &data_tag was in SRAM (0x200XXXXX range) while data_tag[0] was a pointer to flash (0x080XXXXX range). Adding the __attribute__ ((section ('.rodata'))) phrase moved data_tag itself into FLASH nicely.  '.rodata' is in my STM32L152RETx_FLASH.ld file as the name of a FLASH section. You might need to change this if your linker file uses different names.

#stm32l #flash-variable #static
This topic has been closed for replies.
Best answer by stm322399
Posted on December 30, 2016 at 10:55

IMHO, this is regular C semantic, this shall not be compiler specific.

In your example both const type qualifier applies to char (it is a degree of freedom permitted by the langage). When you want the array of pointers to be constant, the keyword must be next to the identifier.

Well the change is actually moving the 'const' around '*', to make it qualify the 'data_tags' identifier.

This method is better than naming explicitly the section, because the compiler might prevent your code to alter the array (which would lead to hard fault).

5 replies

stm322399
Senior
December 29, 2016
Posted on December 29, 2016 at 20:54

What if you declare your array the following way:

static const char * const data_tags[] = { ... }

Lynn Linse
Associate III
December 29, 2016
Posted on December 29, 2016 at 21:32

So move the '*' around the CONST?

I can try that. It's also possible this is a specific compiler (as-configured) issue.

stm322399
stm322399Best answer
Senior
December 30, 2016
Posted on December 30, 2016 at 10:55

IMHO, this is regular C semantic, this shall not be compiler specific.

In your example both const type qualifier applies to char (it is a degree of freedom permitted by the langage). When you want the array of pointers to be constant, the keyword must be next to the identifier.

Well the change is actually moving the 'const' around '*', to make it qualify the 'data_tags' identifier.

This method is better than naming explicitly the section, because the compiler might prevent your code to alter the array (which would lead to hard fault).