EmbDev.net

Forum: µC & Digital Electronics STM32F4xx: running code from ram


von Lauren (Guest)


Rate this post
useful
not useful
Greetings to all readers,

shortly ago I read, that the execution of binary code stored in the 
first section of the ram of an STM32F407xx is possible although the 
Cortex-M4F has an harvard architecture
(http://www.arm.com/files/downloads/Developing_Advanced_Signal_Processing_Software_on_the_Cortex-M4_Processor.pdf) 
.

Well, so far I began to introduce myself in the settings of the linker 
of the launchpad-gcc-toolchain until a single question start to circle 
around in my head: Does it really make sense to execute code from ram, 
if I just want to increase the speed of execution, for example for 
calculating an FFT?

If you want to program a bootloader I would agree, that it might be 
advantageous, but thats not the application I'm focusing.

Thanks, Lauren

von Thomas W. (diddl)


Rate this post
useful
not useful
executing in RAM is maybe a good idea for two reasons:

+ some JTAG (like JLINK) has small licences with no debug support in 
flash

+ flash can be written only 100.000 times. While developing it is 
nessecary to flash very often. So execution in RAM would be good for 
flash

von Martin Thomas (Guest)


Rate this post
useful
not useful
ST Microelectronics promotes the STM32F4 series with: "Based on CoreMark 
benchmark, the performance achieved thanks to the ART accelerator is 
equivalent to 0 wait state program execution from Flash memory at a CPU 
frequency up to 168 MHz." (Source: DM00037051.pdf/Datasheet, ART 
section). A "branche cache" is mentioned so zero wait-states (from the 
cache) should be possible for non-linear code execution to a certain 
level. It might be a good idea to ask in the forum at st.com but since 
only very small modifications are needed to place selected functions in 
Flash or in RAM, profiling both options should not be that difficult. 
Please post your results.

von Sam P. (Guest)


Rate this post
useful
not useful
> although the Cortex-M4F has an harvard architecture

If you look at the block diagram of the Cortex-M family, you will see 
that this is not a classic Harvard architecture. It is about as much 
Harvard as pretty much every Intel CPU since the Pentium is, which means 
that data and code have different buses for performance reasons only 
(think separate D-Cache/I-Cache in almost every desktop CPU today).

Really, people should stop calling it Harvard architecture, because 
while technically correct, for all practical purposes it isn't. Also, it 
only applies to the Cortex-M core itself, not to the MCU as a whole 
(most of which usually have a hierarchical von-Neumann architecture).

As for the original questions, I agree with what Martin Thomas wrote. 
Note also that external RAM tends to be much slower than Flash on these 
MCUs.


On a side note:
> flash can be written only 100.000 times.

Shouldn't that be "10.000"? Some flash MCUs even guarantee just 1.000 
write cycles. 100.000 is more typical for EEPROMs.

von Lauren (Guest)


Attached files:

Rate this post
useful
not useful
Thank you for answering!

Currently I try to set up an example to get a running linker-script:
In main.c intiates a gpio-port and catches the MC a loop:
1
while(1)
2
{
3
delay();
4
toggle_io();
5
}

The function "toggle_io" is in an different file for the code which 
should be executed from a ram-location. In my example the function just 
toggles the gpio-port.

My problem is the linker-script.

Normaly the script looks like this (in CooCox):
1
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
2
SEARCH_DIR(.)
3
INCLUDE "memory.ld"
4
5
/* Section Definitions */ 
6
SECTIONS 
7
{ 
8
       
9
    .text : 
10
    { 
11
        KEEP(*(.isr_vector .isr_vector.*)) 
12
        *(.text .text.* .gnu.linkonce.t.*)         
13
        *(.glue_7t) *(.glue_7)                    
14
        *(.rodata .rodata* .gnu.linkonce.r.*)                            
15
    } > rom */
16
    
17
  
18
    
19
    .ARM.extab : 
20
    { ...
21
22
...
23
...
24
}

In my first attemp I divided the .text section in two part (without any 
further changes) and inserted my .boot-section between the isr-vectors 
and the user-code-section .
Currently I havn't implemented a loader-function, I only wanted to see, 
if the MC jumps to a ram-location.
It didn't! The toggle-fuction was executed from a flash-location, so
the programm was able to run.

I assume, that the toggle-function is linked a second time in the second 
part of the .text-section, so I tried to link the other .o-files 
manually.
After that I got an elf-file with 32KB large .text-section, that is even 
not able to init the gpio-port.
Now I'm confused...
Whats wrong with this code?
1
SECTIONS 
2
{ 
3
.text : 
4
    { 
5
        KEEP(*(.isr_vector .isr_vector.*))  /* keep interrupt vector at default position */
6
    } >rom
7
         
8
     .boot : /* create boot-section between isr-vectors and user code*/
9
     AT (0x20000000)  /*  relocate to ram begin */
10
     {
11
      _sram_code = .  ;    /* save start adress of code */
12
        ..\obj\boot.o *(.text);  /* link code to ram-position*/
13
       _eram_code = . ;     /* save end adress of code*/
14
     }  > rom 
15
   
16
 /* first try */
17
 /*   .text : 
18
    {   
19
        *(.text .text.* .gnu.linkonce.t.*)         
20
        *(.glue_7t) *(.glue_7)                    
21
        *(.rodata .rodata* .gnu.linkonce.r.*)                          
22
    } > rom */
23
 /* end first try*/
24
25
/* second try: */  
26
    .text : 
27
   {   
28
        ..\obj\main.o *(.text);
29
        ..\obj\stm32f4xx_gpio.o *(.text);
30
        ..\obj\startup_stm32f4xx.o *(.text);  
31
        ..\obj\stm32f4xx_rcc.o *(.text); 
32
    ..\obj\system_stm32f4xx.o *(.text); 
33
            
34
        *(.glue_7t) *(.glue_7)                    
35
        *(.rodata .rodata* .gnu.linkonce.r.*)                          
36
    } > rom 
37
/* end second try*/    
38
    
39
    .ARM.extab : 
40
    {...
41
...

von Uwe Bonnes (Guest)


Rate this post
useful
not useful
Be sure to handle initialized Variable in a sensible way!

von Lauren (Guest)


Rate this post
useful
not useful
Sorry, I don't understand, what you mean...

von Lauren (Guest)


Rate this post
useful
not useful
The deeper I go, the less I understand...
I tried to read out a simple unsigned long int variable:
1
...
2
.text : 
3
    {    
4
        KEEP(*(.isr_vector .isr_vector.*)) 
5
      *(.text .text.* .gnu.linkonce.t.*)    
6
        *(.glue_7t) *(.glue_7)                    
7
        *(.rodata .rodata* .gnu.linkonce.r.*)
8
    } > rom       
9
              
10
    _stfunc = 0x00000100; /* just for reading out */
11
...

In my main.c I declared "extern unsigned long _stfunc" an read it out.
The result is not what I assigned to it in the linker-script.
If I rename it in the script, I got (the expected) error-message.
Are these linker-settings some kind of vodoo ???

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.