/var/www/restricted/ssh/stm32/www/stm32circle/ STM CircleOS forum / How to locate variable at fixed address?

Username:     
Password:     
             

Forum

# 1   2010-04-21 16:04:33 How to locate variable at fixed address?

iX3
Member
Registered: 2010-04-06
Posts: 11

How to locate variable at fixed address?

Hi,

In my application I am using one of the FLASH pages on the STM32F103 to store parameters (similar to the EEPROM emulation discussed in AN2594). Currently, this is implemented similar to the following:

Code:

#define PAGE_255            ((uint32_t)0x0807F800)

inline u16 flash_read( u32 addr )
{
    return *(__IO uint16_t*)addr;
}

inline void flash_write( u32 addr, u16 val )
{
    *(__IO uint16_t*)addr = val;
}

#define numVars 10
s16 ram_var[numVars];
void main()
{
    char c;

    //...

    for( c=0; c<numVars; c++ )
    {
        flash_write(PAGE_255+2*c, ram_var[c]);
        // ...
    }

    //...
}

First of all, I'm not sure how to guarantee that the compiler/linker does not attempt to use the same FLASH space that I am using for my data. Second, I think there should be a more readable way to implement this. With the RAISONANCE compiler for the STM8S I was able to use the "at" keyword when declaring variables, so I could do something like this:

Code:

s16 flash_var[10] at 0x0807F800;

flash_var[0] = ram_var[0];

What is the best way to do this with the STM32 family and gcc build tools?

Last edited by iX3 (2010-04-21 16:05:09)

Offline

 

# 2   2010-04-21 18:48:42 How to locate variable at fixed address?

iX3
Member
Registered: 2010-04-06
Posts: 11

Re: How to locate variable at fixed address?

OK, I found a work-around solution. It doesn't solve the reservation problem, but it does make the code easier to read.

Code:

#define flash_var    ((__IO uint16_t*)((uint32_t)0x0807F800))

Last edited by iX3 (2010-04-21 18:49:12)

Offline

 

# 3   2010-04-22 07:06:05 How to locate variable at fixed address?

yrt
Administrator
From: Grenoble-France
Registered: 2008-06-11
Posts: 520
Website

Re: How to locate variable at fixed address?

Hi,

Be carrefull, the STM8 code memory is EEPROM, and the STM32 one is FLASH. So, you have to erase it page by page before writing it.

To separate flash code memory and flash data memory, you can add a section into the linker script. For example, the CircleAPP.ld contains this  instructions :

MEMORY
{
  RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
  FLASHB1 (r) : ORIGIN = 0x8000000, LENGTH = 0x0006000
  FLASH (rx) : ORIGIN = 0x8006000, LENGTH = 8K
  EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
}

The FLASH section is reserved for the application code, and FLASHB1 for the CircleOS.
So, in your case, you can use this type of section to reserve data flash area :
FLASHB1 (rw) : ORIGIN = 0x807F800, LENGTH = xK

In the link script you have to add this section declaration ("flash_data_sect " for example) into the SECTIONS paragraph :

    /* This is for saving data area */
    .flash_data_sect :
    {
        *(.flash_data_sect)
    } >FLASH_B1

In your code you have to declare your variables with the correct attribute :
__attribute__ ((section("flash_data_sect")))
__IO uint16_t flash_var[10];

and the linker will put flash_var at @0x807F800.

Yves

Offline

 

# 4   2010-04-22 15:06:11 How to locate variable at fixed address?

iX3
Member
Registered: 2010-04-06
Posts: 11

Re: How to locate variable at fixed address?

Hi yrt,

Thank you for your recommendation. However, I am having trouble using a non-default linker script. I tried setting to "...\Ride\Lib\ARM\STM32F10x_COMMON.ld" but then I get an error at the end of the build:

Code:

Building C:\...\<my_project>.rapp 
 Running: LD 
 "C:\...\Ride\arm-gcc\bin\arm-none-eabi-gcc.exe" -mcpu=cortex-m3 -mthumb -Wl,-T -Xlinker "C:\...\<my_project>.elf.ld" -u _start -Wl,-static -Wl,--gc-sections -nostartfiles -Wl,-Map -Xlinker "C:\...\<my_project>.map" -Wl,--warn-once  
 C:\...\<my_project>.elf.ld:55: undefined symbol `_estack' referenced in expression  
 collect2: ld returned 1 exit status  
  
Build failed

When using the default linker script it works OK; I get the following instead:

Code:

Building C:\...\<my_project>.rapp 
 Running: LD 
 "C:\...\Ride\arm-gcc\bin\arm-none-eabi-gcc.exe" -mcpu=cortex-m3 -mthumb -Wl,-T -Xlinker "C:\...\<my_project>.elf.ld" -u _start -Wl,-static -Wl,--gc-sections -nostartfiles -Wl,-Map -Xlinker "C:\...\<my_project>.map" -Wl,--warn-once  
 "C:\...\Ride\arm-gcc\bin\arm-none-eabi-objcopy.exe" "C:\...\<my_project>.elf" --target=ihex "C:\...\<my_project>.hex" 
 "C:\...\Ride\Bin\rexrdr.exe" "C:\...\<my_project>.elf.sizetmp" 0 "C:\...\Ride\arm-gcc\bin\arm-none-eabi-size.exe" "C:\...\<my_project>.elf" 
 "C:\...\Ride\Bin\dwf2xml.exe" "C:\...\<my_project>.dbi" "C:\...\<my_project>-globals.Standard.xml" "C:\...\<my_project>.Standard.xml" ARM 
 DWF2XML 2.00.01 - Raisonance Dwarf information extractor  
 Copyright (c) Raisonance S.A.S. 2007-2009. All rights reserved.  
  
Build successful

It seems that this _estack parameter is not getting defined or something...could this be because there is a more specific linker script file that needs to get included somewhere? I noticed that there are some linker scripts generated automatically in my project folder too -- will these still be generated if I do not use the default link script?

Also, I need to ensure that the processor can keep running the critical code while the data area(s) of FLASH are being erased or programmed. Does the CPU stall during any FLASH access during programming or just access to page being erased/programmed? The documentation in PM0042 is vague about this. Do I need to execute from RAM during FLASH erasing/programming to avoid stalling?

PM0042 :

The main Flash memory can be programmed 16 bits at a time. The program operation is
started when the CPU writes a half-word into a main Flash memory address with the PG bit
of the FLASH_CR register set. Any attempt to write data that are not half-word long will
result in a bus error response from the FPEC. $1

Last edited by iX3 (2010-04-22 15:11:25)

Offline

 

# 5   2010-04-22 15:17:32 How to locate variable at fixed address?

VincentC
Administrator
Registered: 2007-11-08
Posts: 149

Re: How to locate variable at fixed address?

Hi,

"...\Ride\Lib\ARM\STM32F10x_COMMON.ld" is not the script used when you select "use default script".
It is one of its sub-scripts.

First, re-select the default script and build the application.
Then, edit ".\<application_name>.elf.ld" which has been generated by the IDE during the link.
It specifies the input files, and then it includes another script (main script) which was also generated during the link with the "default script" option, and is the one you should specify in the "custom linker script" option. (or a copy of it)


To do what you described in your first post, you should also correct Yves' code like this:

Code:

MEMORY
{
  RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
  FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 0x7F800
  FLASHB1 (r) : ORIGIN = 0x0807F800, LENGTH = 256
  EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
}

And if you want it to work in CircleOS, there will be other things to change: flash addresses are fixed at load time, not at compile time. you cannot force them and if you try it will either break the OS or just not work.

I hope it helps.

You will find more information on all this in the GettingStartedARM_Ride7 document and in the linker documentation from GCC.

Best Regards,

Vincent

Offline

 

# 6   2010-04-22 16:04:10 How to locate variable at fixed address?

iX3
Member
Registered: 2010-04-06
Posts: 11

Re: How to locate variable at fixed address?

The last two lines of <my_project>.elf.ld are:

Code:

INCLUDE "C:\<my_project_dir>\STM32F103_384K_64K_FLASH.ld"
OUTPUT("C:\<my_project_dir>\<my_project>.elf")

C:\<my_project_dir>\STM32F103_384K_64K_FLASH.ld:

Code:

/*
Default secondary/main linker script for STM32F103_384K_64K
Copyright RAISONANCE S.A.S. 2007-2010

!!! This file is automatically generated by Ride if the default linker script option is active !!!

Do not modify it if the option is set, as it will be erased at every link.
If you need to use your own script please configure your Ride7 project linker options to use your custom linker script
You can take this one as example for wrting your custom linker script
You can use, copy and distribute this file freely, but without any waranty.*/

/* include the common STMxxx sub-script */
INCLUDE "STM32F10x_COMMON.ld"

/* include the memory spaces definitions sub-script */
[b]INCLUDE "STM32F103_384K_64K_DEF.ld"[/b]

/* include the sections management sub-script for FLASH mode */
INCLUDE "sections_FLASH.ld"

STM32F103_384K_64K_DEF.ld:

Code:

/*
Linker subscript for STM32F103 definitions with 384K Flash and 64K RAM
Copyright RAISONANCE 2007-2009
!!! This file is automatically generated by Ride !!!
Do not modify it, as it will be erased at every link.
You can use, copy and distribute this file freely, but without any waranty.
*/

/* Memory Spaces Definitions */

MEMORY
{
  RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
  FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 384K
  STARTFLASH (rx) : ORIGIN = 0x0, LENGTH = 0x0
  CRPPATCH (r) : ORIGIN = 0x0, LENGTH = 0
  FLASHPATCH (r) : ORIGIN = 0x00000000, LENGTH = 0
  ENDFLASH (rx)  : ORIGIN = 0x00000000, LENGTH = 0
  FLASHB1  (rx)  : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB0 (rx)  : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB1 (rx)  : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB2 (rx)  : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB3 (rx)  : ORIGIN = 0x00000000, LENGTH = 0
}

/* higher address of the user mode stack */
_estack = 0x20010000;

So I am supposed to modify STM32F103_384K_64K_DEF.ld? Will it be overwritten? Do I choose "<my_project>.elf.ld" in Project Options for linker script?

Offline

 

# 7   2010-04-23 07:51:42 How to locate variable at fixed address?

VincentC
Administrator
Registered: 2007-11-08
Posts: 149

Re: How to locate variable at fixed address?

Hi,

The file to specify in the options is STM32F103_384K_64K_FLASH.ld.

Then you can modify it and its subscripts (STM32F103_384K_64K_DEF.ld in your case).

These files will be overwritten only if you link using the "use default script" option.
So if you deselect the option it's OK, but it's better to make copies, in case you select the option by accident.


Best Regards,

Vincent

Offline

 

# 8   2010-04-23 13:11:33 How to locate variable at fixed address?

iX3
Member
Registered: 2010-04-06
Posts: 11

Re: How to locate variable at fixed address?

Thank you for your help! I am very pleased with RAISONANCE support!

Offline

 

# 9   2010-04-23 16:43:57 How to locate variable at fixed address?

iX3
Member
Registered: 2010-04-06
Posts: 11

Re: How to locate variable at fixed address?

Can I also use __attribute__ ((section (".xxxxx"))) to locate functions? For example, I would like to load a function into RAM for running a customized bootloader.

Code:

#define INRAM    __attribute__ (( section (".data") ))

INRAM void test_ram_func(void)
{
     // Do something
}

Offline

 

# 10   2010-04-23 20:57:40 How to locate variable at fixed address?

iX3
Member
Registered: 2010-04-06
Posts: 11

Re: How to locate variable at fixed address?

OK, thanks again. I was able to answer my own question this time.
When the "Generate Long Calls" option is enabled in the RIDE7 project options the project builds OK.
(No changes to linker script files are needed since .data section already includes any sections named ".RAMtext")
The startup code copies the function from FLASH into RAM before calling main().

Code:

#define INRAM __attribute__ (( section (".RAMtext") ))

INRAM  void test_ram_func(void)
{
     // Do something
}

Offline

 

# 11   2010-08-13 16:58:16 How to locate variable at fixed address?

dimril
New member
Registered: 2010-07-01
Posts: 1

Re: How to locate variable at fixed address?

And how do you force fixed data on a specific address? I mean something like a constant - so that I have 00 at 0x08013000. My idea doesn't work, even though it compiles:

Code:

MEMORY
{
  RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
  FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
  FLASHPATCH (r) : ORIGIN = 0x00000000, LENGTH = 0
  ENDFLASH (rx)  : ORIGIN = 0x00000000, LENGTH = 0

  FLASHB1  (rw)  : ORIGIN = 0x08013000, LENGTH = 1K

  EXTMEMB0 (rx)  : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB1 (rx)  : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB2 (rx)  : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB3 (rx)  : ORIGIN = 0x00000000, LENGTH = 0
}

    .b1text :
    {
        *(.b1text)
    } >FLASHB1

And in my code:

Code:

__attribute__ ((section(".b1text"))) uint8 init_val1 = 0x00;

Offline

 

# 12   2010-08-17 07:12:38 How to locate variable at fixed address?

yrt
Administrator
From: Grenoble-France
Registered: 2008-06-11
Posts: 520
Website

Re: How to locate variable at fixed address?

I tested your code and it works.
What do you mean by "it doesn't work" ? Is the address false or is it the value ?
Are you sure that the section FLASHB1 is not already used ?

Offline

 

# 13   2010-10-14 09:11:57 How to locate variable at fixed address?

saradabakesh
New member
Registered: 2010-10-14
Posts: 4

Re: How to locate variable at fixed address?

Yes, I also have tested this code and also want to say that its working really very fine. As I knew only little bit about that but after watching this I came to know proper about that. I also want to say that it also increase my knowledge about that.

Offline

 

Board footer