Execute in RAM after copying from Flash or ROM
Technical Note 11578
Architectures:
ARM
Component:
general
Updated:
2022/7/12 12:41
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
- Make a copy of the
.icf
file that the project uses. - 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
- Make a copy of the file that holds the vector table.
- 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 inMODULE SUMMARY
– inspect the placements of objects (r-o code
vsr/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 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.