SAM3S: Copy to RAM and run?

Discussion around product based on ARM Cortex M3 core.

Moderators: nferre, ncollot

cfranck
Posts: 18
Joined: Mon Mar 05, 2007 10:28 pm

SAM3S: Copy to RAM and run?

Wed Aug 11, 2010 2:52 pm

Hello,

I am trying to copy all of my code (including the interrupt vector table) to RAM during system startup and run it there. This is necessary since my code needs to write to the flash occasionally while remaining fully functional for the few ms it takes to write a flash page.

I am using IAR EWARM 5.50.5.

Has anyone done something like this before? The IAR C/C++ manual isn't very helpful, and the example given in it just leads to the vector table staying in the flash and still containing vectors to flash. Also, the IAR debugger does not appear to be aware that the code is actually running from RAM and sets breakpoints in the flash.

Right now, it seems that my only option is doing most of the initialization manually by adding code to __low_level_init() that copies the image from flash to RAM.
dfridley
Posts: 90
Joined: Thu Feb 25, 2010 5:02 pm

Re: SAM3S: Copy to RAM and run?

Wed Aug 11, 2010 4:20 pm

Hello -

No need to copy every thing to RAM...

Identify the couple of functions that are performing the Flash writing and set their locations to RAM.

This is how we do this (using Rowley CrossWorks):

We have one function that writes pages to flash so we use an attribute to tell the compiler/linker to place this function into RAM. The majority of the code executes out of Flash but when writing to the Flash only the functions that perform the work need to be executing out of RAM (just make sure you don't overwrite any program space inadvertently :shock: ).

E.g.
In the header...

Code: Select all

eFlashResult WritePage( U32 page_, FlashPage &data_ ) __attribute__((section(".fast")));
The section(".fast") attribute tells the compiler/linker to place this function into the .fast section which is located in RAM. Check your IAR documentation to see how to locate functions into RAM.

EDIT
FYI: It looks like IAR has a keyword for this...
"__ramfunc"

From the latest IAR C/C++ Development Guide p 30
http://iar.com/website1/1.0.1.0/78/1/
The __ramfunc keyword makes a function execute in RAM, or in other words places
the function in a section that has read/write attributes. The function is copied from ROM
to RAM at system startup just like any initialized variable, see System startup and
termination, page 72.
The keyword is specified before the return type:
__ramfunc void foo(void);
Regards,
Duane P. Fridley, IEEE CSDP
Viable Bytes, Inc.
cfranck
Posts: 18
Joined: Mon Mar 05, 2007 10:28 pm

Re: SAM3S: Copy to RAM and run?

Thu Aug 12, 2010 8:52 am

dfridley wrote:Hello -

No need to copy every thing to RAM...

Identify the couple of functions that are performing the Flash writing and set their locations to RAM.
Hello,

unfortunately, my application has a hard requirement to service two interrupts and their associated tasks at periods of 1ms and 2ms, respectively. Writes to flash including auto-erase may take up to 4.6ms, therefore waiting for the EFC to finish writing with everything else (IRQs/tasks/...) disabled is out of the question. Writing to flash must not change the real-time behavior of my application, which is why all of the code must reside in RAM while the application is running.

I am basically looking for a way to turn all of the code including the interrupt vector table into one big __ramfunc. The IAR C/C++ development guide states that the easiest way to do this modifying the linker command file, however, it is a bit scarce on examples on what exactly needs to be done.

This setup was fairly simple to do with a SAM7S due to its remap feature, but unfortunately the memory remap function was dropped in the SAM3S.

Edit:

I tried using the linker directive given in the example in the EWARM C/C++ development guide

Code: Select all

initialize by copy { readonly, readwrite };
... however, this only leads to some parts of the application ending up in RAM while others (e.g. the IRQ vectors) stay in flash.
cfranck
Posts: 18
Joined: Mon Mar 05, 2007 10:28 pm

Re: SAM3S: Copy to RAM and run?

Thu Aug 12, 2010 2:18 pm

Ok, I think my last attempt went a bit too far.

Code: Select all

initialize by copy with packing = none {	section .data,
											section .rodata,
											section CODE,
											section .text};	
do not initialize  { section .noinit };

place at address mem:__ICFEDIT_vector_start__ { readonly section .vectors };

place in RAM_region	{	section .data,
						section .rodata,
						section .bss,
						section CODE,
						section .text,
						block CSTACK};
place in ROM_region	{	section .iar.init_table,
						section .data_init,
						section .text_init,
						section .rodata_init};
in the linker control file does put everything in RAM except for the interrupt vector table (which is ok, I think I know how to deal with that). However, this really means everything - including the code that is necessary for system startup before the copy-to-ram can take place.

I believe if I add exceptions for these blocks/sections in the "place in RAM_Region" and "initalize by copy" lines, I might end up with the end result I am looking for.
dfridley
Posts: 90
Joined: Thu Feb 25, 2010 5:02 pm

Re: SAM3S: Copy to RAM and run?

Thu Aug 12, 2010 2:42 pm

Hello,

Sounds like you got the tiger by the tail now...

I believe the interrupt vectors are outside of the flash region so these should be ok (i.e. 0xE000E100+).

Regards,
Duane P. Fridley, IEEE CSDP
Viable Bytes, Inc.
cfranck
Posts: 18
Joined: Mon Mar 05, 2007 10:28 pm

Re: SAM3S: Copy to RAM and run?

Thu Aug 12, 2010 3:48 pm

dfridley wrote:Hello,

Sounds like you got the tiger by the tail now...
Well ... almost.

Right now, I have managed to move some of the code that runs before main() back to flash by putting it in a separate section (.mystartup) and placing that section in flash.

However, IAR places parts of its startup code in .text, which needs to be placed in flash instead of RAM because it contains the functions that do the actual copying. According the EWARM C/C++ development guide, this startup code should be in a section named ".cstartup" instead, but it ends up in .text instead.

I stepped through the startup process and identified the following functions/symbols:

Code: Select all

__iar_program_start
__cmain
__iar_data_init3
__iar_copy_init3
_call_main
Anyone have an idea how I can put those in a separate section to move them back to flash? (/edit: Looks like some of them are in a file called cstartup_m ...)

Once that is done, I think the only thing left to do is make a copy of the interrupt vector table in RAM and set VTOR accordingly. Then, the program should run exclusively out of RAM.
cfranck
Posts: 18
Joined: Mon Mar 05, 2007 10:28 pm

Re: SAM3S: Copy to RAM and run?

Thu Aug 12, 2010 5:18 pm

Almost there!

Code: Select all

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };

initialize by copy with packing = none	{	section .data,
											section .rodata,
											section CODE,
											section .text}
	except								{	object cstartup_M.o,
											object cmain.o,
											object data_init3.o,
											object copy_init3.o,
											object zero_init3.o};
do not initialize  						{ section .noinit };

place at start of RAM_data_region		{	block CSTACK	};

place in RAM_code_region				{	section CODE,
											section .text	}
	except								{	object cstartup_M.o,
											object cmain.o,
											object data_init3.o,
											object copy_init3.o,
											object zero_init3.o	};
place in RAM_data_region				{	section .data,
											section .rodata,
											section .bss};

place at address mem:__ICFEDIT_vector_start__ 	{	section .vectors	};					
place in ROM_region						{	section .iar.init_table,
											section .data_init,
											section .text_init,
											section .rodata_init,
											section .mystartup,
											object cstartup_M.o,
											object cmain.o,
											object data_init3.o,
											object copy_init3.o,
											object zero_init3.o	};
This keeps all of the startup code in flash while putting the rest of the application (minus the interrupt vector table) in RAM.

However, some things still do not as intended:

1. I tried putting the interrupt vector table in RAM and the section used to initialize it (".vectors_init") at 0x400000 in ROM. Which worked ... kind of. I did see a copy of the interrupt vector table at 0x400000, however, the CPU did not recognize the initial values for SP and PC and set PC to 0x00000000 instead. The memory at 0x400000 looks identical if I keep the interrupt vector table in flash as shown in the example above, which confuses me a little - from the point of the CPU there should be no difference if the memory at 0x400000 contains the same data?

2. The linker refuses to initialize any variables declared as const. It reserves space for them in the RAM, but does not initialize them during system startup. Now, I realize that variables declared as const may not change from the compilers point of view, but the linker shouldn't really care about that. The only solution I found was to change all const variable to regular ones, however, I'd rather not do that since it precludes any compiler optimizations with regard to constants.

Any suggestions?
dfridley
Posts: 90
Joined: Thu Feb 25, 2010 5:02 pm

Re: SAM3S: Copy to RAM and run?

Thu Aug 12, 2010 6:34 pm

1. I tried putting the interrupt vector table in RAM and the section used to initialize it (".vectors_init") at 0x400000 in ROM
Just poking at the data sheet... see 10.21.5 Vector Table Offset Register (page 170)
2. The linker refuses to initialize any variables declared as const. It reserves space for them in the RAM, but does not initialize them during system startup...
You may have to revert to the less optimized and type safe version... "#define".

From p 219.

"Static and global objects declared const are allocated in ROM."

Also, not sure if there is a compiler switch to generate these as inline (like #define). On previous IAR projects (not ARM) the optimization level would put const's inline.

Regards
Duane P. Fridley, IEEE CSDP
Viable Bytes, Inc.
cfranck
Posts: 18
Joined: Mon Mar 05, 2007 10:28 pm

Re: SAM3S: Copy to RAM and run?

Mon Aug 16, 2010 9:06 am

dfridley wrote:
1. I tried putting the interrupt vector table in RAM and the section used to initialize it (".vectors_init") at 0x400000 in ROM
Just poking at the data sheet... see 10.21.5 Vector Table Offset Register (page 170)
The problem occurs directly after reset at system startup, before the code has any opportunity to write to the VTOR. The CPU will read the values for SP and PC from addresses 0x00000000 and 0x00000004, respectively and then start executing instructions.

I can see in the debugger that the correct values are in the addresses, yet the CPU somehow fails to read them.
dfridley wrote:
2. The linker refuses to initialize any variables declared as const. It reserves space for them in the RAM, but does not initialize them during system startup...
You may have to revert to the less optimized and type safe version... "#define".

From p 219.

"Static and global objects declared const are allocated in ROM."
I'm not quite sure whether a compiler should actually be aware of the physical differences of various memory types. Isn't it the job of the linker to actually allocate memory for variables and objects?

How would the IAR compiler deal with hardware that simply doesn't have any ROM to speak of - e.g. a microcomputer-like setup where programs can be loaded, run and terminated during run-time? The linker would have to generate code to initialize all variables that need initialization, even those declared as const.
dfridley
Posts: 90
Joined: Thu Feb 25, 2010 5:02 pm

Re: SAM3S: Copy to RAM and run?

Tue Aug 17, 2010 2:32 pm

I'm not quite sure whether a compiler should actually be aware of the physical differences of various memory types. Isn't it the job of the linker to actually allocate memory for variables and objects?
Yes, but if declared as #define these will be compiled in the code as literals instead of reserved in memory with an address pointer in the code to the consts. It doesn't sound like the IAR tools are moving the defined consts over to RAM with the rest of the program so this would be one way to get around this issue.

Edit
Or you could use an external NV memory or switch to a different processor....

Regards,
Duane P. Fridley, IEEE CSDP
Viable Bytes, Inc.
cfranck
Posts: 18
Joined: Mon Mar 05, 2007 10:28 pm

Re: SAM3S: Copy to RAM and run?

Thu Aug 19, 2010 11:05 am

I finally managed to trick the linker into doing what I want it to do.

Yes, I wrote "trick". The linker apparently has some undocumented behavior that causes it to look for interrupt service routines and anything in their call tress, and refuse to initialize the object containing any such functions. In effect, the linker disregards the users linker control file without giving any indication, warning or error message.

The main part of the trick consisted of filling the interrupt vector table with dummy pointers, so the linker believes those dummy functions are the actual ISRs. At run-time, the program then changes the interrupt vectors to the actual ISRs.

I really hate it when development tools stubbornly try to be more clever than their user and/or save the user from him/herself. I know what I'm doing and I would like the freedom to shoot myself in the foot, thank you. :evil:
dfridley
Posts: 90
Joined: Thu Feb 25, 2010 5:02 pm

Re: SAM3S: Copy to RAM and run?

Thu Aug 19, 2010 4:41 pm

Foot shooting is allowed... :lol:

I'm missing my left foot as we speak...

I don't believe I said anything about your experience or otherwise, just trying to help by throwing out ideas.

Thank you for posting your solution. Hopefully it will help someone else in the future.

Best Regards,
Duane P. Fridley, IEEE CSDP
Viable Bytes, Inc.
cfranck
Posts: 18
Joined: Mon Mar 05, 2007 10:28 pm

Re: SAM3S: Copy to RAM and run?

Wed Aug 25, 2010 9:11 am

dfridley wrote:I don't believe I said anything about your experience or otherwise, just trying to help by throwing out ideas.
That vent was directed more at the compiler manufacturer than at anyone in the forum. :)

If I have to fool the tools to get them to perform a seemingly simple task, there's a problem with the tools, in my opinion.

Anyway, I have contacted IAR about this issue. Maybe they will issue a fix for the problem in the future.
gog
Posts: 5
Joined: Thu Jul 08, 2010 11:01 am

Re: SAM3S: Copy to RAM and run?

Thu Sep 09, 2010 3:00 pm

Hello

I am also currently stuck with exactly similar problem: to run my entire application from RAM and I am also using IAR EWARM 5.50 for my development.

Dear cfrank, can u please share the solution/tips/suggestions with me? <gopalbsk @ gmail . com>

Your help will be greatly appreciated.

Thanks,
Gog.
cfranck
Posts: 18
Joined: Mon Mar 05, 2007 10:28 pm

Re: SAM3S: Copy to RAM and run?

Mon Sep 13, 2010 9:33 am

gog wrote:Hello

I am also currently stuck with exactly similar problem: to run my entire application from RAM and I am also using IAR EWARM 5.50 for my development.

Dear cfrank, can u please share the solution/tips/suggestions with me?
I'll share them with everyone here.

After a bit of discussion with IAR support, they pointed out to me what I've been missing. It's in the EWARM development guide on p. 309:
EWARM development guide wrote:Anything reachable from the program entry label is considered needed for initialization
unless reached via a section fragment with a label starting with __iar_init$$done.
Any symbols that appear before the label __iar_init$$done are considered necessary for initalization and hence will not be initialized by the linker. With the default cstartup_M.s, this includes the symbol __vector_table.

After removing the line

Code: Select all

REQUIRE __vector_table
from a separate copy of cstartup_M.s that I included in my project, the vector table could be located in RAM and initialized there. However, in order for the processor to start correctly, it still needs to find values for SP and PC at address 0x00000000 after reset. I solved this by putting the (uncompressed) copy of __vector_table used for initalization at address 0x00400000 (Flash which is mapped to 0x00000000).

In my linker control file, I initialize all code and initialized data sections, using the except option to exclude anything that is used during initalization, e.g.

Code: Select all

initialize by copy with packing = none	{	section .data,
											section .rodata,
											section CODE,
											section .textrw,
											section .text,
											section .vectors }
	except								{	object cstartup_M.o,
											object cmain.o,
											object data_init3.o,
											object copy_init3.o,
											object zero_init3.o,
											object exceptions.o,
											object ABImemset48.o,
											object iarttio.o,
											object exit.o,
											object XShttio.o,
											object ABImemclr4.o};
do not initialize  						{	section .noinit,
											section .cstack	};

place at start of RAM_region			{	section .cstack	};

place in RAM_region						{	section CODE,
											section .text,
											section .rodata,
											section .data,
											section .bss,
											section .textrw,
											section .noinit,
											section .vectors }
	except								{	object cstartup_M.o,
											object cmain.o,
											object data_init3.o,
											object copy_init3.o,
											object zero_init3.o,
											object exceptions.o,
											object ABImemset48.o,
											object iarttio.o,
											object exit.o,
											object XShttio.o,
											object ABImemclr4.o};
											
place at address mem:__ICFEDIT_vector_start__ 	{	section .vectors_init	};	

place in ROM_region						{	section .iar.init_table,
											section CODE_init,
											section .data_init,
											section .text_init,
											section .textrw_init,
											section .rodata_init,
											section .mystartup,
											object cstartup_M.o,
											object cmain.o,
											object data_init3.o,
											object copy_init3.o,
											object zero_init3.o,
											object exceptions.o,
											object ABImemset48.o,
											object iarttio.o,
											object exit.o,
											object XShttio.o,
											object ABImemclr4.o};

One small bit of warning: Copying the code from flash to RAM will overwrite any currently set software breakpoints there. Hence, they need to be set again after the code has been copied to RAM.

Return to “SAM3 Cortex-M3 MCU”

Who is online

Users browsing this forum: No registered users and 3 guests