Moving functions into SRAM is quick once you learn the tricks. Before you start make sure you are compiling with -mlong-calls.
All function placement is handled by the Target.ld file found in yourecosbuilddir/ecos-default-install/Target.ld To move functions you add directives to the file. Memory is allocated in the order the instruction appear in the file, so order is important.
The directions you will be working with are called SECTION DIRECTIVES You can read more about them on gnu's site basically you can move functions: *(.text.functionname) and sections of files: filename.o(COMMON) filename.o(.data.*).
Now that you've got the tools, how do you start: Look for a section already allocated in the memory you wish to use. You can find the section by looking at the Memory directives at the top of the Target.ld file
MEMORY
{
sram : ORIGIN = 0, LENGTH = 0x2000
ram : ORIGIN = 0x20000000, LENGTH = 0x40000
}
Now look for the sections directive it will look something like this:
SECTIONS
{
.debug_aranges 0x20000000 : { *(.debug_aranges) } .debug_pubnames ALIGN(0x4) : { *(.debug_pubnames) } .debug_info ALIGN(0x4) : { *(.debug_info) } .debug_abbrev ALIGN(0x4) : { *(.debug_abbrev) } .debug_line ALIGN(0x4) : { *(.debug_line) } .debug_frame ALIGN(0x4) : { *(.debug_frame) } .debug_str ALIGN(0x4) : { *(.debug_str) } .debug_loc ALIGN(0x4) : { *(.debug_loc) } .debug_macinfo ALIGN(0x4) : { *(.debug_macinfo) } .note.arm.ident ALIGN(0x4) : { KEEP (*(.note.arm.ident)) }
.fixed_vectors 0x20 : { . = .; KEEP (*(.fixed_vectors)) } > sram
...
}
This line is the one you are looking for:
.fixed_vectors 0x20 : { . = .; KEEP (*(.fixed_vectors)) } > sram
We are going to be moving synbols to this region. Pick a symbol to move. I'm going to begin with the ISR in gpl-gps. I write a section like this in the target.ld and I recompile: .fastmem ALIGN(0x4) { *(.text.accum_isr) }
If it works great add another symbol .fastmem ALIGN(0x4) { *(.text.accum_isr) *(.text.accum_dsr)}
If not there are some tools you can use to fix it.
Methods
#pragma long-calls
and#pragma long-calls-off
- function pointers
- other source level modifications.
If the function you are moving, will be called from outside the SRAM, and you can not or do not want to move the caller you can make it a long call function. Wrap the function in the .h and .c in #pragma long-calls
and #pragma long-calls-off
If the function you are moving calls a function outside the SRAM, you can call it with a function pointer, or you can make the outside function a long-call function using the above method.
const int (*print)(const char*, ...)=diag_printf;
print("INITIALIZE TRACKING: CHANNEL NOT OFF!\n\r");
If these techniques do not work, I will include more specific examples as I find them. For example division: The divide operator maps to a function call on platforms without a hardware divide. This function is provided in libgcc. To call in from within SRAM, the method I have found is this:
extern long __divsi3(long,long);
const long(*divsi3)(long,long)=__divsi3;
Now you have to replace all divide calls in the file with function calls to divsi3. You will have to define a function pointer for each type of divide you wish to use in the 8k.