Skip to main content
msvarc9
Associate
May 24, 2012
Question

How to allocate variable in Flash to desired address?

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
    This topic has been closed for replies.

    31 replies

    Tesla DeLorean
    Guru
    June 18, 2014
    Posted on June 18, 2014 at 19:53

    With my own startup/link script examples I didn't see the problem. Based on RIDE GNU/GCC implementation

    I was able to duplicate the issues by creating an equivalent startup.s and customizing it for the STM32F4 I used Chuck's framework here which seemed compatible with your script as a starting point.

    http://robotics.mcmanis.com/src/arm-blink/cm4_startup_code.html

    In order to get the vectors to emit properly I changed the following:

    .section .isr_vector,''a'',%progbits

    ________________

    Attachments :

    startup.s : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1A4&d=%2Fa%2F0X0000000bj9%2FT2Deo4eXg7nASQTRKqPSWSfvMTlIMjL6MILEek0t3U8&asPdf=false
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    zzdz2
    Associate
    June 19, 2014
    Posted on June 19, 2014 at 10:45

    Sorry I forgot to include it, now is in attachment.

     

    Do you have '.isr_vector' section defined in your startup?

    I can only see '.isr' int he attached elf.

    You can try to rename it to '.isr' in the linker script or '.isr_vector' section in startup file.

    Tesla DeLorean
    Guru
    June 19, 2014
    Posted on June 19, 2014 at 14:33

    I don't have his startup.s, and it's different to the RIDE one, but when I made an equivalent it had

        .section .isr_vector

    which wasn't sufficient to keep the vectors. This was using Yagarto 4.7.2
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    kkawula
    Associate II
    June 24, 2014
    Posted on June 24, 2014 at 11:09

    I include start-up file in attachment. It has declaration of section '.isr_vector'. Please look at it. Basicly it's code taken from samples which comes with ARM GCC compiler. I have just edited the contents of the isr table to adapted it to STM32 family.

    I don't think that is a start-up problem because like I mention before when i add

    *(.text.SD*)

    *(.text.*Handler)

    Program runs ok and isr table is allocated in right place.

    Any ideas what can by wrong?

    ________________

    Attachments :

    startup_STM32F40XX.S : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I19z&d=%2Fa%2F0X0000000bjA%2FBSI9Du93f3U8ToQNSls1mMv0GrlI4n.fVxmSQhcUyks&asPdf=false
    zzdz2
    Associate
    June 25, 2014
    Posted on June 25, 2014 at 10:50

    As Clive mentioned you need to change this line in your startup:

    .section .isr_vector

    to

    .section .isr_vector,''a'',%progbits

    kkawula
    Associate II
    June 25, 2014
    Posted on June 25, 2014 at 17:12

    Ok after adding ''.section  .isr_vector,''a'',%progbits '' instead of ''.section .isr_vector'' in my startup file everything works perfectly. Sorry Civil that I missed  Your clue.
    rajpaged
    Associate II
    February 14, 2015
    Posted on February 14, 2015 at 01:49

    I'm trying to get this sort of thing to work. SofarI have:

    in a .c file

    __attribute__((__section__(
    ''.user_data''
    ))) 
    const
    int32_t userConfig[32];

    and inan .lds file:

    ENTRY(Reset_Handler) 
    MEMORY 
    { 
    FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 1022k 
    DATA (RX) : ORIGIN = 0x080FF7FF, LENGTH = 2k 
    SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 112K 
    SRAM2 (RWX) : ORIGIN = 0x2001c000, LENGTH = 16K 
    CCM (RWX) : ORIGIN = 0x10000000, LENGTH = 64K 
    BACKUP_SRAM (RWX) : ORIGIN = 0x40024000, LENGTH = 4K 
    } 
    _estack = 0x2001c000; 
    SECTIONS 
    { 
    .isr_vector : 
    { 
    . = ALIGN(4); 
    KEEP(*(.isr_vector)) 
    . = ALIGN(4); 
    } > FLASH 
    .user_data : 
    { 
    . = ALIGN(4); 
    *(.user_data) 
    . = ALIGN(4); 
    } > DATA 
    .text : 
    { 
    . = ALIGN(4); 
    _stext = .; 
    *(.text) 
    *(.text*) 
    *(.rodata) 
    *(.rodata*) 
    *(.glue_7) 
    *(.glue_7t) 
    KEEP(*(.init)) 
    KEEP(*(.fini)) 
    . = ALIGN(4); 
    _etext = .; 
    } > FLASH 
    .ARM.extab : 
    { 
    . = ALIGN(4); 
    *(.ARM.extab) 
    *(.gnu.linkonce.armextab.*) 
    . = ALIGN(4); 
    } > FLASH 
    .exidx : 
    { 
    . = ALIGN(4); 
    PROVIDE(__exidx_start = .); 
    *(.ARM.exidx*) 
    . = ALIGN(4); 
    PROVIDE(__exidx_end = .); 
    } > FLASH 
    .ARM.attributes : 
    { 
    *(.ARM.attributes) 
    } > FLASH 
    .preinit_array : 
    { 
    PROVIDE(__preinit_array_start = .); 
    KEEP(*(.preinit_array*)) 
    PROVIDE(__preinit_array_end = .); 
    } > FLASH 
    .init_array : 
    { 
    PROVIDE(__init_array_start = .); 
    KEEP(*(SORT(.init_array.*))) 
    KEEP(*(.init_array*)) 
    PROVIDE(__init_array_end = .); 
    } > FLASH 
    .fini_array : 
    { 
    PROVIDE(__fini_array_start = .); 
    KEEP(*(.fini_array*)) 
    KEEP(*(SORT(.fini_array.*))) 
    PROVIDE(__fini_array_end = .); 
    } > FLASH 
    . = ALIGN(4); 
    _sidata = .; 
    .data : AT(_sidata) 
    { 
    . = ALIGN(4); 
    _sdata = .; 
    PROVIDE(__data_start__ = _sdata); 
    *(.data) 
    *(.data*) 
    . = ALIGN(4); 
    _edata = .; 
    PROVIDE(__data_end__ = _edata); 
    } > SRAM 
    .bss : 
    { 
    . = ALIGN(4); 
    _sbss = .; 
    PROVIDE(__bss_start__ = _sbss); 
    *(.bss) 
    *(.bss*) 
    *(COMMON) 
    . = ALIGN(4); 
    _ebss = .; 
    PROVIDE(__bss_end__ = _ebss); 
    } > SRAM 
    PROVIDE(end = .); 
    }

    I can't seem to be able to read back the correct value after writing to this location with

    HAL_FLASH_Program(TYPEPROGRAM_WORD, &userConfig[0], somedata);

    Tesla DeLorean
    Guru
    February 14, 2015
    Posted on February 14, 2015 at 04:02

    Surely 0x080FF800 ? Although the flash block up there is 128KB in size, so you'd want to watch what the erase does, and what address you're actually using.

    Can't help you with the HAL stuff. You could trying dumping the memory area in question, and checking what's there before/after you do things. ie dumpdata(0x800, (void *)0x080FF800);

    Check also the error/status returns for the flash functions, or query the flash peripheral directly.
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    rajpaged
    Associate II
    February 14, 2015
    Posted on February 14, 2015 at 12:00

    sorry, 80FF800 is correct. Turns out that I hadn't been erasing the sector before writing (nothing mentioned in the hal library about this) This code works now:

    __attribute__((__section__(
    ''.userdata''
    ))) 
    const
    int32_t userConfig[32]; 
    ... 
    ... 
    HAL_FLASH_Unlock(); 
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR); 
    FLASH_Erase_Sector(FLASH_SECTOR_11, VOLTAGE_RANGE_3); 
    HAL_FLASH_Program(TYPEPROGRAM_WORD, &userConfig[MAGICNUMBER_LOC], MAGICNUMBER); 
    HAL_FLASH_Lock();

    My ld file is now set as so:

    MEMORY 
    { 
    FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 1M-128K 
    DATA (RWX) : ORIGIN = 0x080E0000, LENGTH = 128k 
    SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 112K 
    SRAM2 (RWX) : ORIGIN = 0x2001c000, LENGTH = 16K 
    CCM (RWX) : ORIGIN = 0x10000000, LENGTH = 64K 
    BACKUP_SRAM (RWX) : ORIGIN = 0x40024000, LENGTH = 4K 
    }

    Now I want to move the DATA to sector 0 as I don't need the 128k space and would benefit from faster erase speeds. If I try

    MEMORY 
    { 
    FLASH (RX) : ORIGIN = 0x08004000, LENGTH = 1M-16K 
    DATA (RWX) : ORIGIN = 0x08000000, LENGTH = 16k 
    SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 112K 
    SRAM2 (RWX) : ORIGIN = 0x2001c000, LENGTH = 16K 
    CCM (RWX) : ORIGIN = 0x10000000, LENGTH = 64K 
    BACKUP_SRAM (RWX) : ORIGIN = 0x40024000, LENGTH = 4K 
    }

    The application wont even start anymore. I get errors in the upload processing saying ''could not write to 0x8000000 at offset 0x4000'' and various other things. Why can I use sector 11 and not sector 0? Also what do the suffuses (RX), (RWX) mean?
    Rahimi.Meysam
    Associate III
    September 15, 2015
    Posted on September 15, 2015 at 17:17

    Hi. I have a question.

    How can we set  value and use the value from beta variable?

    thank you.