Execute in RAM after copying from Flash or ROM

Technical Note 11578

Arkitekturer:

Arm, Renesas Synergy

Komponent:

general

Uppdaterad:

2024-01-09 10:15

Introduction

This Technical Note describes how to run your application as much as possible from RAM.

The Note applies to Cortex-M devices from M3 and higher.

Use these guidelines if the method described in the IAR Development Guide for Arm in the section Running all code from RAM does not place your application in RAM to the extent that you expected.

Discussion

Follow the instructions in the user guide section Running all code from RAM

You will find this section in the IAR Development Guide for Arm. If your application is not sufficiently placed in RAM as a result, read the suggestions below.

Placing the maximum amount of code in RAM

The IAR tools can help you copy all or most of the code to RAM at program startup.

Do this:

  • Enable copying to RAM, by editing the .icf file.
  • Create and place a second vector table in RAM, by editing the low-level source code.
  • Set VTOR to point to the vector table in RAM, by editing the application source code.
  • [Optional] Add link-time protection of the vector table in RAM.

This is illustrated using a project for an STM32F103RB (Cortex-M3) device. STM32F103RB (Cortex-M3) example project IAR Embedded Workbench for ARM 9.20.1.

The example project contains low-level code written in assembler language. To cover also C, the examples in this text are written in C.

Enable copying to RAM, by editing the .icf file

  1. Make a copy of the .icf file that the project uses.
  2. Choose Project>Options>Linker>Config and specify that the copy you just made be used instead of the default file.

Make the change described in the section Running all code from RAM:

initialize by copy { readonly, readwrite } 
    except { 
        section .intvec, /* Don’t copy interrupt table */
        section .init_array }; /* Don’t copy C++ init table */

Make these changes to the .icf file:

  • Adjust the start of the RAM region so that the RAM vector table fits:
define symbol __ICFEDIT_region_RAM_start__ = 0x200000EC;
  • Add a symbol for the start address of the RAM vector table:
define symbol __RAM_intvec_start = 0x20000000;
  • Place the section that will hold the RAM vector table:
place at address mem: __RAM_intvec_start { section .intvec_RAM };

Create and place a second vector table in RAM

  1. Make a copy of the file that holds the vector table.
  2. Add that file to your project.

Make the following changes in the copy of the source file:

  • Rename the copied vector table to:
__vector_RAM_table
  • The vector table in RAM (__vector_RAM_table) will hold the references to the interrupt handlers. (Because the vector table in RAM is a copy of the original vector table, there is no need to edit the table itself.)
  • The RAM vector table should look like this in C:
__root const IntVector __vector_RAM_table[] =
   {__ptr = __sfe( ‘CSTACK’ ) },
   __iar_program_start,
   NMI_Handler,
   HardFault_Handler,
   . . .
  • Place the RAM vector table in the section .intvec_RAM.
  • Add the following #pragma line to the RAM vector table:
#pragma location = ".intvec_RAM"
__root const IntVector __vector_RAM_table[] =
. . .
  • The ROM vector table must be changed.
  • Don’t change __ptr = __sfe( ‘CSTACK’ ) or __iar_program_start.
  • All other table entries should reference a dummy handler named Empty_Handler.
  • The ROM vector table will look like this:
const IntVector __vector_table[] =
    {__ptr = __sfe( ‘CSTACK’ ) },
    __iar_program_start,
    Empty_Handler,
    Empty_Handler,
    Empty_Handler,
    Empty_Handler,
    . . .
  • Write source code for the dummy Empty_Handler, like this:
void Empty_Handler(void)
  {
    for(;;);
  }

Set VTOR to point to the vector table in RAM

If the application already includes source code that sets VTOR, then modify that code. Otherwise, add the following modification very early in the application source code (at least before interrupts are enabled).

  #pragma section = ".intvec_RAM"
  SCB->VTOR = (uint32_t)__section_begin(".intvec_RAM");

[Optional] Add link-time protection of the vector table in RAM

To make sure to that the RAM vector table is included in the linked output image:

  • Add these two lines of code immediately before the definition of the main() function:
  extern void * __vector_RAM_table [];
  #pragma required=__vector_RAM_table
  void main(void)

Note: If one or more of the non-optional instructions in this Technical Note is skipped, the ILINK linker will issue a Li005 error.

Use the .map file to inspect the effects of the modifications

Inspect these sections in the .map file:

  • PLACEMENT SUMMARY ­– inspect which memory objects are placed in
  • MODULE SUMMARY ­– inspect the placements of objects (r-o code vs r/w code)
  • ENTRY LIST ­– check the addresses of functions.

The MODULE SUMMARY shows the result of the changes:

Compare the MODULE SUMMARY in the original project:

  2'256 bytes of readonly  code memory
      0 bytes of readwrite code memory
     16 bytes of readonly  data memory
  2'052 bytes of readwrite data memory

with the MODULE SUMMARY in the modified project:

    804 bytes of readonly  code memory
  1'808 bytes of readwrite code memory
  1'253 bytes of readonly  data memory
  2'054 bytes of readwrite data memory

Note! Linker protection of startup code

The linker protects sections that are referenced from the startup code from being affected by an initialize by copy directive. This includes:

  • __low_level_init and all functions called and/or defined in the same compilation unit (.c file)
  • global (statically linked) C/C++ symbols

The linker ensures that only code that executes after copy initialization has been finished, will be copied to RAM. For this reason, it is safe to add readonly in the initialization command:

initialize by copy { readonly, readwrite };

Example of bootloader in RAM

The technical note 160822 give guidelines on how to create a bootloader, and that techincal note holds an example project.

At this link is that example project is modified so that a maxmimum of code is placed in RAM.

Conclusion

The suggestions in this Technical Note will minimize the amount of code still placed in and running from ROM.

All product names are trademarks or registered trademarks of their respective owners.

Det här innehållet finns tyvärr inte på svenska.

Vår webbplats finns främst på vårt koncernspråk engelska, förutom det innehåll för investerare som vi är lagstadgade att kommunicera på svenska. Vi rekommenderar att du besöker vår globala webbplats på engelska för att få en bättre upplevelse.

Vi stöder inte längre Internet Explorer. För att få bästa möjliga upplevelse av iar.com rekommenderar vi att du uppgraderar till en modern webbläsare som Chrome eller Edge.