how to load function in flash while execute in ram

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

how to load function in flash while execute in ram

Jump to solution
4,189 Views
fugrace
Contributor III

Hi ,everyone,I'm using KL under KEIL environment.

I want to  load function in flash while execute in ram.Though I can place the code in ram ,But I don't

know where it loads in flash,and that's important for me.

So can you tell me how to arrange the scatter file to load the function at a absolute address(or session)

and meanwhile place its execute address in ram?

Thanks!

Labels (1)
1 Solution
2,610 Views
fugrace
Contributor III

sorry to disturb all of you.

It's my problem don't know much about scatter file.Now I tried as below,and succeed :

LR_IROM2  0x00007000   0X100

{

   ER_RAM  0x20000000  0x00000100

{

    Test.o

  }

}

View solution in original post

0 Kudos
Reply
8 Replies
2,610 Views
xiaodong_zhang
NXP Employee
NXP Employee

hi FU grace,

    The following example show how to load code in flash to ram and run it.

/************************************************************************

* NAME: ftfl_command_inram

*

* DESCRIPTION: Launch the command. It must be in RAM.

************************************************************************/

void ftfl_command_inram(volatile unsigned char *ftfe_fstat)

{

    *ftfe_fstat = MK_FTFL_FSTAT_CCIF_MASK;

    while (!(*ftfe_fstat & MK_FTFL_FSTAT_CCIF_MASK))

    {};

   

}

static void ftfl_command_32bit( unsigned char command, unsigned long *address, char *data )

{

    char *pdata = data;

  

   

    static void (*fnRAM_code)(volatile unsigned char *) = 0;

    /* Adequate space for the small program */

    #define PROG_SIZE (50)  

    if(!fnRAM_code)

    {

        int i = 0;

        unsigned char *pCodeStart = (unsigned char *)ftfl_command_inram;

        /* Make space for the routine on stack (this will have an even boundary) */

    #if defined(__IAR_SYSTEMS_ICC__) || defined(__IASMARM__)

        #pragma data_alignment=2

        volatile static unsigned char ProgRamSpace[PROG_SIZE];

    #else

        volatile static unsigned char ProgRamSpace[PROG_SIZE] __attribute__ ((aligned (2)));           

      #endif       

        /* Thumb 2 address */

        pCodeStart =  (unsigned char *)(((unsigned int)pCodeStart) & ~0x1); 

        /* Copy program to SRAM */

        while (i < PROG_SIZE)

        {                                    

            ProgRamSpace[i] = pCodeStart[i];

            i++;

           

        }

       

        /* Create a thumb 2 call */

                                                       

        fnRAM_code = (void(*)(volatile unsigned char *))(ProgRamSpace + 1);

    }

   

    

    DisableInterrupts;

   

    /* The CCIF flag must read 1 to verify that any previous command has

    * completed. If CCIF is zero, the previous command execution is still active, a new

    * command write sequence cannot be started, and all writes to the FCCOB registers are

    * ignored.

    */

    while (!(MK_FTFL_FSTAT & MK_FTFL_FSTAT_CCIF_MASK))    

    {};

   

    /* Ensure that the ACCERR and FPVIOL bits in the FSTAT register are cleared prior to

    *  starting the command write sequence.

    */

    MK_FTFL_FSTAT = (MK_FTFL_FSTAT_ACCERR_MASK | MK_FTFL_FSTAT_FPVIOL_MASK);          

   

    /* The FCCOB register group uses a big endian addressing convention. */

   

    /* Write a valid command to the FCCOB0 register. */

    MK_FTFL_FCCOB0 = command;

   

    /* Flash address.*/

    MK_FTFL_FCCOB1 = (uint8)(((uint32)address) >> 16);   /* Flash address [23:16] */

    MK_FTFL_FCCOB2 = (uint8)(((uint32)address) >> 8);    /* Flash address [15:8] */

    MK_FTFL_FCCOB3 = (uint8)((uint32)address);           /* Flash address [7:0] */

    /* Data.*/

    MK_FTFL_FCCOB4 = (uint8)(pdata[3]);    /* Data Byte 0.*/                      

    MK_FTFL_FCCOB5 = (uint8)(pdata[2]);    /* Data Byte 1.*/

    MK_FTFL_FCCOB6 = (uint8)(pdata[1]);    /* Data Byte 2.*/

    MK_FTFL_FCCOB7 = (uint8)(pdata[0]);    /* Data Byte 3.*/

   

    fnRAM_code(&MK_FTFL_FSTAT);

    EnableInterrupts;

}

2,610 Views
getsoubl
Contributor I

Hello,

In your example I could not understand why  the last significant bit should be 0 (   pCodeStart =  (unsigned char *)(((unsigned int)pCodeStart) & ~0x1). As I read the in cortex M processors for thump-2 instructions , the lsb bit for PC should be 1 ,right?? And then you use this instruction (void(*)(volatile unsigned char *))(ProgRamSpace + 1) to create thumb -2 call. Can you explain me the reason for this?

Thank you

Best regards

0 Kudos
Reply
2,610 Views
egoodii
Senior Contributor III

I would just like to add an 'application note' regarding this technique to get a 'small function' moved temporarily out to RAM.  The ARM architecture, and compilers, require 32-bit constants, like 'fixed' peripheral addresses (MK_FTFL_FSTAT, etc) to be loaded from program-space at a 'relative' offset to the program counter.  A compiler will place these numbers in program space at the end of an 'object' file, so 'following' the source code.  This means two things:  Firstly, that the 'routine' you are going to copy out to RAM MUST be at the 'end' of the associated source-file, AND that 'PROG_SIZE' must include not only the actual code, but ALSO these 'constants' off the end.

0 Kudos
Reply
2,610 Views
fugrace
Contributor III

Hi,xiaodong,Thank you very much .You've really got what I want to do.And the answer maybe a solution.But it's a little too complex for me,I can understand what your function wants to do ,that's copy function from flash to ram and protect the FCCOB  register.I guess it may be what the __main in KEIL completes which I don't know where its source code locates.

But I really want other more easy way to solve it,like using scatter file in KEIL to place the function in different load address and execute address.

Anyway,Thanks!

0 Kudos
Reply
2,610 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Please check below link about how to place function and data at dedicated address of Keil:

Linker User Guide: Placing functions and data at specific addresses


Wish it helps.

Best regards,
Ma Hui

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

2,610 Views
fugrace
Contributor III

Hi,Ma hui.

I've solved the problem,it's ok to do like my fist reply for this question.My later hard fault problem occured because the code  placed in that special

session has some illegal operation.

Thanks anyway!

0 Kudos
Reply
2,610 Views
fugrace
Contributor III

hi,Ma hui.

actually I had seen the link about how to place at specific address ,and I tried both place function at flash or ram.

But now my question is a little different.Not only do I want to place my function in flash ,but the most important,I want to

execute it in RAM,so it's a difference between load address and execute address.My upper reply gives my tried solution,

I thought it works,but these days I tried another more complex file(not only simple test file) to do as the test,and find it works not

stable.That' s sometimes it works ,but more often it runs to hard Fault.

Can you give me more hints?Thanks very much!

0 Kudos
Reply
2,611 Views
fugrace
Contributor III

sorry to disturb all of you.

It's my problem don't know much about scatter file.Now I tried as below,and succeed :

LR_IROM2  0x00007000   0X100

{

   ER_RAM  0x20000000  0x00000100

{

    Test.o

  }

}

0 Kudos
Reply