cancel
Showing results for 
Search instead for 
Did you mean: 

How to allocate variable in Flash to desired address?

msvarc9
Associate
Posted on May 24, 2012 at 10:11

Please, could you help me? with STM32F4xx.

But I think it's general problem with GNU linker.

I'm working on SW for colour graphical display application.

It works fine.

But I need to store some data to Flash after the program start.

I want allocate for this data all 16K Sector 1 in Flash area.

I have tried different ways but unsuccessfully.

My variable is 

const unsigned

short

int

FlashArray[8192].

I have tried this: 

const unsigned short

int

FlashArray[8192] __attribute__ ((at((uint32_t)0x08004000)));

This doesn't work in GNU.

I have tried also this:

const

unsigned

short

int

FlashArray[8192]

__attribute__

((section(

''.flash_data_array''

))); 

+

change in  stm32_flash.ld:

/* Specify the memory areas */

MEMORY

{

FLASH0 (rx) : ORIGIN = 0x08000000, LENGTH = 16K

FLASH1 (rx) : ORIGIN = 0x08004000, LENGTH = 16K

FLASH2 (rx) : ORIGIN = 0x08008000, LENGTH = 992K

RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K

MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K

}

/* Define output sections */

SECTIONS

{

/* The startup code goes first into FLASH */

.isr_vector :

{

. = ALIGN(4);

KEEP(*(.isr_vector)) /* Startup code */

. = ALIGN(4);

} >FLASH0

/* My new eeprom area in FLASH */

.flash_data_array :

{

*(.rodata) /* .rodata sections (constants, strings, etc.) */

*(.rodata*) /* .rodata* sections (constants, strings, etc.) */

. = ALIGN(4);

KEEP (*(.init))

KEEP (*(.fini))

. = ALIGN(4);

} >FLASH1

?

/* The program code and other data goes into FLASH */

.text :

{

. = ALIGN(4);

*(.text) /* .text sections (code) */

*(.text*) /* .text* sections (code) */

*(.rodata) /* .rodata sections (constants, strings, etc.) */

*(.rodata*) /* .rodata* sections (constants, strings, etc.) */

*(.glue_7) /* glue arm to thumb code */

*(.glue_7t) /* glue thumb to arm code */

*(.eh_frame)

KEEP (*(.init))

KEEP (*(.fini))

. = ALIGN(4);

_etext = .; /* define a global symbols at end of code */

} >FLASH2

...

But this doesn't work too.

I don't know what's wrong.

I have tried to found out it on internet, but without success.

Here I found out this problem has more people.

Can you help me how to allocate variable array to Sector1 in Flash

and how to prohibit this sector to other flash data?

#linker
31 REPLIES 31
alok472
Associate II
Posted on May 24, 2012 at 15:52

No idea for GNU. However on IAR it works like this...

#pragma location=0xFF2002

__no_init const int beta;

ColdWeather
Senior
Posted on May 25, 2012 at 10:19

const int myarray[mysize] __attribute__((section(''mysectionname''), used));

Note: used  is important to say the linker to keep the variable (not to optimize it away) if there is no reference to it in the program.

msvarc9
Associate
Posted on May 28, 2012 at 08:53

Hi,

I tried it, but it still doesn't work.

When I look at map file after compiling, I can see allocated memory for new Flash sector

''.flash_data_array'', but there is no allocation for my flash variable FlashArray[].Also in debug mode (in Atollic studio) I can't see initialization values for this varaiable despite definition:

const unsigned short int FlashArray[8192] __attribute__ ((section(''.flash_data_array''),used)) ={0x0000,0x1111,0x2222,0x3333,0x4444,0x5555,0x6666,0x7777,0x8888,0x9999,0xaaaa,0xbbbb,0xcccc,0xdddd,0xeeee};

It looks like linker doesn't assign flash variable to new created Flash sector, but there is no error alert after compiling.

frankmeyer9
Associate II
Posted on May 28, 2012 at 12:45

I found this:

http://www.keil.com/support/docs/2829.htm

I'm not sure if it is applicable for your problem,but this source, is a little pessimistic regarding your idea, it says:

''With the GNU GCC Compiler you may use only pointer definitions to access absolute memory locations.''

ColdWeather
Senior
Posted on May 29, 2012 at 11:10

> const unsigned short int FlashArray[8192]..

Either unsigned short or int but not both.
jihlein
Associate II
Posted on August 07, 2012 at 21:54

I'm trying to do the same thing, reserve FLASH sector 1 for EEPROM emulation use, using the CodeBench Lite tools.  Did you ever get this resolved/working?

Thanks in advance!

Posted on August 07, 2012 at 22:47

Surely a pretty trivial linker script exercise?

.C usage

__attribute__((__section__(''.eeprom''))) const short eeprom_junk[8192];

.LD used with Yagarto GNU/GCC 4.6.2

/*
Linker script for STM32F40x Chip Specific - sourcer32@gmail.com
*/
/* include the common STM32F40x sub-script */
INCLUDE ''STM32F4_COMMON.ld''
/* Memory Spaces Definitions */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 112K
AUX (xrw) : ORIGIN = 0x2001C000, LENGTH = 16K
VECTOR (rx) : ORIGIN = 0x8000000, LENGTH = 16K
EEPROM (rx) : ORIGIN = 0x8004000, LENGTH = 16K
FLASH (rx) : ORIGIN = 0x8008000, LENGTH = 1M-32K
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K /* also change _estack below */
}
/* highest address of the user mode stack */
_estack = 0x10010000;
/* Sections Definitions */
SECTIONS
{
/* for Cortex devices, the beginning of the startup code is stored in the .isr_vector section, which goes to FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >VECTOR
.eeprom :
{
. = ALIGN(4);
*(.eeprom)
. = ALIGN(4);
} >EEPROM
/* the program code is stored in the .text section, which goes to Flash */
.text :
{
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
_etext = .;
/* This is used by the startup in order to initialize the .data secion */
_sidata = _etext;
} >FLASH
/* This is the initialized data section
The program executes knowing that the data is in the RAM
but the loader puts the initial values in the FLASH (inidata).
It is one task of the startup to copy the initial values from FLASH to RAM. */
.data : AT ( _sidata )
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_sdata = . ;
*(.data)
*(.data.*)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_edata = . ;
} >RAM
/* This is the uninitialized data section */
.bss :
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_ebss = . ;
} >RAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
/* This is the user stack section
This is just to check that there is enough RAM left for the User mode stack
It should generate an error if it's full.
*/
._usrstack :
{
. = ALIGN(4);
_susrstack = . ;
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
_eusrstack = . ;
} >CCM
__exidx_start = .;
__exidx_end = .;
/* after that it's only debugging information. */
/* remove the debugging information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

.MAP fragment, demonstrating placement

.isr_vector 0x08000000 0x188
0x08000000 . = ALIGN (0x4)
*(.isr_vector)
.isr_vector 0x08000000 0x188 out/startup_stm32f4xx.o
0x08000000 g_pfnVectors
0x08000188 . = ALIGN (0x4)
.eeprom 0x08004000 0x4000
0x08004000 . = ALIGN (0x4)
*(.eeprom)
.eeprom 0x08004000 0x4000 out/app.o
0x08004000 eeprom_junk
0x08008000 . = ALIGN (0x4)
.text 0x08008000 0x38f8
0x08008000 . = ALIGN (0x4)

Now personally, I'd be building the boot loader to live at 0x08000000, and the application at 0x08008000, but to each there own.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on August 07, 2012 at 23:00

You could also back fill, space permitting, the VECTOR section

.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
*(.text.SD*)
*(.text.*Handler)
} >VECTOR

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
jihlein
Associate II
Posted on August 08, 2012 at 04:54

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6WY&d=%2Fa%2F0X0000000bpu%2FE1gpiTBl7k9sKcqMh0U0jdq.NaCjW59NsOfebXmn6u8&asPdf=false