Keil Logo

ARM: executing code at a specific address in RAM


Information in this knowledgebase article applies to:

  • MDK-ARM

QUESTION

I want to run a routine in RAM. Unfortunately, it must be located in a place that is shared as data buffer. So the routine must be copied to RAM before the respective activity starts, because data may have overwritten the routine, if it would be loaded at startup of the application.

How could this be done?

ANSWER

With a scatter file, create a region at the exact address needed, and give it a name. Then place the code (or data) with attribute((section("name"))). This attribute works for functions and for variables. Alternatively #pragma arm section or for assembly code, use AREA.

There are three parts needed to set this up:

  1. The code, that should be copied on demand, and that data buffer get placed in a separate sections. With the help of that, we can put all the stuff for this task into a separate execution regions.

    This example places a function in a separate region:

    __attribute__( ( section ( "RAMCODESECTION" ) ) ) void run_in_ram( void )
    {
      __nop( ) ;
    }
    
    The code in RAM should not have any dependencies to code in flash, which might become inaccessible, while the code in RAM executes.

    This example places a variable in a separate region:

    __attribute__( ( section ( "TEMPDATASECTION" ), zero_init ) ) int foo ;
    
    Note, that this object also will not get initialized at startup, so it can specifically put in the ZI section.
  2. To prevent the linker from loading the code at startup and to share the area with other data, like the data buffer, the OVERLAY attribute is used on the execution regions of the ram code and for the other regions that share this space in the scatter file. This can then look like this:
    LR_IROM1 0x08000000 0x0007FF00  {    ; load region size_region
      ...
      ...
      ...
      RW_CODE 0x2000B000 OVERLAY 0x00001000  {  ; RW data
       *.o (RAMCODESECTION)
      }
      RW_TEMP 0x2000B000 OVERLAY 0x00001000  {  ; RW data
       *.o (TEMPDATASECTION)
      }
    }
    
  3. As there is no automatism to get the code in the RAM, this needs to be done manually. To know, what data needs to be copied from and to which addresses, the linker image symbols can be used. This makes the copying simple.
    extern char Image$$RW_CODE$$Base ;
    extern char Image$$RW_CODE$$Length ;
    extern char Load$$RW_CODE$$Base ;
    
    int load_ramcode( void )
    {
      memcpy( &Image$$RW_CODE$$Base,
              &Load$$RW_CODE$$Base,
              ( size_t )&Load$$RW_CODE$$Length ) ) ;
    }
    
  4. A full example is attached to review the suggested approach of this article in detail.

MORE INFORMATION

SEE ALSO

ATTACHED FILES

Request the files attached to this knowledgebase article.

FORUM THREADS

The following Discussion Forum threads may provide information related to this topic.

Last Reviewed: Friday, November 9, 2018


Did this article provide the answer you needed?
 
Yes
No
Not Sure
 
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.