HOWTO: Run a routine from RAM in S32 Design Studio

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

HOWTO: Run a routine from RAM in S32 Design Studio

HOWTO: Run a routine from RAM in S32 Design Studio

This document describes a way how to execute a selected function(s) out of RAM memory for a project running out of  Flash memory.

  • Create a custom linker section in the linker file (.ld) where a routine(s) should be placed into. This step is optional if you don't care where exactly in RAM the function should be placed. In such case default sections could be used instead.
    MEMORY
    {
     
        flash_rchw : org = 0x00FA0000,   len = 0x4
        cpu0_reset_vec : org = 0x00FA0000+0x10,   len = 0x4
        cpu1_reset_vec : org = 0x00FA0000+0x14,   len = 0x4
        cpu2_reset_vec : org = 0x00FA0000+0x04,   len = 0x4     
           
        m_my_flash :     org = 0x01000000, len = 4K       // optional - this is dedicated section for the RAM function rom image
        m_text :         org = 0x01001000, len = 5628K    // default section for code
     
        m_my_ram :       org = 0x40000000, len = 4K       // optional - specific section where a RAM routine(s) should be copied into
        m_data :         org = 0x40001000,  len = 764K    // default section for data/stack/heap
    }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
    • If it's intended to keep routine(s) that should be executed from RAM within a specific custom section:
SECTIONS
{
...
.MyRamCode : 
{
   MY_RAM_START = .;       // this symbol is optional 
   KEEP (*(.MyRamCode))    // KEEP - avoid dead stripping if an object is not referenced 
   MY_RAM_END = .;         // this symbol is optional
} > m_my_ram AT>m_my_flash // the section above is linked into m_my_ram and Rom image is stored into m_my_flash‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

  • Otherwise you can use the default memory areas for code/data if you don't care about the location of the routine(s):
SECTIONS
{
...
.MyRamCode  :
{
    MY_RAM_START = .;     // this symbol are optional
    KEEP (*(.MyRamCode))  // KEEP - avoid dead stripping if an object is not referenced
    MY_RAM_END = .;       // this symbol are optional
}  > m_data  AT>m_text    // the section is linked into default data memory area and its rom image is placed into the default code memory
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

  • add the __attribute__ statements to the RAM function prototypes. The function attribute "longcall" is required to be able to call this RAM function from flash.
__attribute__ ((section(".MyRamCode")))              // place the function below into .MyRamCode section
int test_RAM(int arg1) __attribute__ ((longcall));   // declare the function as "far"‍‍
  • Default S32DS project startup initializes just the default data sections. Therefore it's necessary to perform section copy-down manually if the functions are placed into a custom section. This must be done before a RAM routine gets called e.g. at the beginning of main() or in the startup routine.

      You can create some linker symbols (.MyRamCode RAM and ROM addresses and size) and import them to the module where copy-down is implemented.

__MY_RAM_ADR = ADDR (.MyRamCode);
__MY_RAM_SIZE = SIZEOF (.MyRamCode);
__MY_RAM_ROM_ADR = LOADADDR (.MyRamCode);‍‍‍

The final source file may look like this:

#include <string.h>
extern unsigned long __MY_RAM_ADR;
extern unsigned long __MY_RAM_ROM_ADR;
extern unsigned long __MY_RAM_SIZE;

__attribute__ ((section(".MyRamCode")))              // place the function below into .MyRamCode section
int test_RAM(int arg1) __attribute__ ((longcall));   // declare the function as "far"
...

void main(void)
{
   int counter = 0;
   memcpy(&__MY_RAM_ADR , &__MY_RAM_ROM_ADR, &__MY_RAM_SIZE);  // copy the function from flash to RAM
   counter = test_RAM(counter);                                // call the function
...
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope it helps!

Stan

Comments

hello, Stanislav Sliva 

I have tested it.but i find a problem which is it can run well in debug,when i take off the MULTILINK UNIVERSAL, and reset the board ,it cannot work normal,can you help me?  

i find that if the VMA is different from the LMA, it happens. when the VMA(in ram) is different form LMA(in rom),the s32 will show "Program received signal SIGTRAP, Trace/breakpoint trap.",and go on running by F8 is pressed. if the MULTILINK UNIVERSAL is removed,it can not run normal in run mode.

The facts are as follows:

The MCU is mpc5746c.the ide is S32 Design Studio for Power Architecture Version: 1.2

In debug mode, the problem is as follow figure:

pastedImage_2.png

when  the code which is " e_bl main" is run,it run _eabi first before into main.During the process , "program received  signal SIGTRAP..." happens.

The program can go on running ,when the "resume button " is pressed on.But if I take off the MULTILINK UNIVERSAL,and reset the board,the program

can not runinto main,it is suspendend maybe.  when the VMA is the same as LMA in the rom, the problem never happen.i think that the reason is se_illegal but how can i do to avoid it ? help me,help you ,thank you!

Hi,

I suspect this issue is caused by the fact you created a project in S32DS Power 1.x and imported the project into S32DS v1.2.

Please have a look here:

https://community.nxp.com/docs/DOC-335361 

And thanks for sharing the screenshot I've added it into the document!

Hope it helps.

Stan

hi,

i feel very happy for your reply.

I have looked at the "HOWTO: Migrate project created in S32DS Power v1.x into v1.2+ " earnestly.  i have  been awared of that.

what i want to say is that my test project is created in S32DS Power v1.2,and added the section of  ".MyRamCode" and others needed as you describe. and the problems happen.I try to modify the section as follows:

新建位图图像 (2).bmp

the  "se_illegal" never happen when  _init() is running,but the function that run a routine form ram in s32 can not be realized. so if you have time , you can test it in s32v1.2 .I think the problem will happen.If the lib has no problem, maybe the ld is needed to modify,but i have no idea.

waiting for your reply,thank you!

The same experienced using S32 Studio for powerpc v1.2; even easier way to reproduce:

- New project >> MPC5674F

- select library NewLib Nano

- added a ram function into main.c

- added .ramfuncs input section to .data section (will be copied by initialization)

main.c:
#include "derivative.h" /* include peripheral declarations */

extern void xcptn_xmpl(void);

int counter = 0;

#define RAMFUNC __attribute__ ((longcall, section(".ramfuncs")))
RAMFUNC void ramcall(void) {
   counter+=2;
}

int main(void) {
   xcptn_xmpl ();
   for(;;) {
      counter++;
      ramcall();
   }
}

56xx_flash.ld
....
.data :
{
*(.data)
*(.data.*)
*(.ramfuncs)
} > m_data AT>m_text
...

Generated disassembly on main entrypoint (main >> __eabi >> __init)

00004438 <__init>:
4438: 18 21 06 f0 e_stwu r1,-16(r1)
443c: 00 80 se_mflr r0
443e: 54 01 00 14 e_stw r0,20(r1)
4442: 00 00 se_illegal
4444: 79 ff fc ad e_bl 40f0 <frame_dummy>
4448: 79 ff fd b9 e_bl 4200 <__do_global_ctors_aux>
444c: 50 01 00 14 e_lwz r0,20(r1)
4450: 00 90 se_mtlr r0
4452: 20 f1 se_addi r1,16
4454: 00 04 se_blr
4456: 50 01 18 21 e_lwz r0,0(r1)

It seems that long call triggers a wrong alignment on the init trampoline; the problem happens both with Debug/Release (flash) targets (on Debug_RAM code is already in ram, the problem is not triggered).

I hope it helps.

Have you been solved it?Maybe what you think is right,what can we do to avoid it.

Hello All,

Thanks for reporting this problem!

I can confirm this is a e200 gcc linker defect (defect#: CMPE200GCC-181) which is currently investigated by the compiler team.

This works fine on ARM gcc (S32DS for ARM).

I'll keep you informed about the progress.

Thanks!

Stan

My workaround for this problem was tweaking file ELe200/src_gcc/libgcc/config/rs6000/eabivle-ci.S: in the __init function implementation I've added a se_nop to enforce 4byte padding which was is not implicit on vle (while it was with booke):

/* Head of __init function used for static constructors. */
#ifdef __VLE__
.section ".init","axv"
#else
.section ".init","ax"
#endif
.align 2
FUNC_START(__init)
#ifdef __VLE__
e_stwu 1,-16(1)
se_mflr 0
se_nop
e_stw 0,20(1)
#else
stwu 1,-16(1)
mflr 0
stw 0,20(1)
#endif

Unfortunately applying this workaround requires to rebuild compiler.

Regards,
Elker

Hello, Stanislav Sliva,

I did this according to your solution in S32DS for Power PC (MPC5744P).

But I encountered problem when I copy the code from flash to RAM.

In C source code, I declared the external variable created by .ld file:

__MY_RAM_ADR = ADDR (.MyRamCode);
__MY_RAM_SIZE = SIZEOF (.MyRamCode);
__MY_RAM_ROM_ADR = LOADADDR (.MyRamCode);

But these variables are actually strange values in my source code when I debug the code.

__MY_RAM_SIZE is correct. But __MY_RAM_ADR is zero and __MY_RAM_ROM_ADR is very strange value.

I checked the generated map file. All these three variables are correct value.

I don't understand  why it's wrong value in my C source code.

I  also tried to use them in assembly code in "Startup.S", just like the "DataCopy" for ".data" and ".sdata" section.

Both __MY_RAM_ADR  and __MY_RAM_ROM_ADR  are correct values.

Do you have any idea why I'm having this issue? Any additional settings for the compiler needed?

Best Regards,

Jason Yang

Hi,

I would like to copy all the functions in several files to RAM and execute. Is there an alternative for copying the object files to RAM instead of individual function. 

Many thanks in advance.

Best regards,

Sreekanth Challa

Hi,

My target processor is MPC5643L

To fix this problem I did try to modify the library file.

From the output.map file we can find what library file used as __init section.

like..

.init 0x000119c4 0xc c:/nxp/s32ds_power_v2017.r1/cross_tools/powerpc-eabivle-4_9/bin/../lib/gcc/powerpc-eabivle/4.9.4/e200z4/fp/ecrti.o
0x000119c4 __init

Find the library file (my case is ecrti.o)

and manually modify to find "18 21 06 F0 00 80 54 01 00 14 00 00 " - in my case, 2 of part exists. need to modify all of those.

To "18 21 06 F0 00 80 00 80 54 01 00 14"  - 00 80 inserted.

This is the part of

__init

 e_stwu r1,-16(r1)
 se_mflr r0
 e_stw r0,20(r1)
 se_illegal <---- 0x00, 0x00  

To

__init

 e_stwu r1,-16(r1)
 se_mflr r0
 se_mflr r0 <--- insert this repeated from just before, value = 0x00, 0x08
 e_stw r0,20(r1)  <--- 2byte shifted, value = 0x54010014

This modification works in my experiment. for Debug, Release both of object.

I hope it helps,

Regards,

I met the same issue, did you solve it?

Dear Duke!

Thank you very much. This seems to help! (using an MPC5745R)

Kind regards, Folkert

Hi Duke and Folkert,@Folkert Sikkema @Duke Lee

   I tried it but failed, just wonder should I modify both ecrti.o and ecrtn.o or only ecrti.o? Another question is should I also modify the <__fini>?

   btw because we use SPE, so what I modified is in e200z4/fp/spe.

   Appreciate if you guys can share more detail.

Best regard.

Dear Xiaoxi,

I only needed to change ecrti.o as shown in the picture

pastedImage_1.png

Although this work-around works, I still wonder what the root-cause is...

Regards, Folkert

As same with Folkert,

Only the ecrti.o was needed to modify. in my case.

If you can trace your code, you can find what part has the problem.

If that is not 4 bytes aligned code as I mentioned.

probably you can use the same way to fix your code.

Or, post the problem point in the disassembled code.

Good luck.

Dear Duke!

 

Thank you very much. This works fine on my MPC5746C board, I move the m_text to 0x00FE0400 and boot failure before.

cmpe200gcc-181‌ has been fixed in compiler that comes in S32 Design Studio for Power Architecture 2017.R1 - Update 2 available 

It's great!

We're waiting for the official patch of this problem.

Thank you for your update Alexander and NXP s32ds support team.

Duke‌ it's already there. You can install latest one https://community.nxp.com/docs/DOC-341653 - it's cumulative.

No ratings
Version history
Last update:
‎09-10-2020 02:21 AM
Updated by: