This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2541: Run code from ram

Part Number: CC2541

Hi,

I've tried run code from ram. My code is

#pragma segment="RAMCODE"
#pragma segment="ROMCODE"

/*******************************************************************************
* LOCAL FUNCTIONS
*/
/* place the next function in RAMCODE */
#pragma location="RAMCODE"
void LedOnFunc(void)
{
    LED_ON        
}

/* enable IAR extensions, this is necessary to get __sfb and
__sfe, it is of course possible to write this function in
assembler instead */
#pragma language=extended
void init_ram_code()
{
    void * ram_start = __sfb("RAMCODE"); /* start of RAMCODE */
    void * ram_end = __sfe("RAMCODE"); /* end of RAMCODE */
    void * rom_start = __sfb("ROMCODE"); /* start of ROMCODE */
    /* compute the number of bytes to copy */
    unsigned long size = (unsigned long)(ram_end) - (unsigned long)(ram_start);
    /* copy the contents of ROMCODE to RAMCODE */
    memcpy( ram_start, rom_start, size );
}
/* restore the previous mode */
#pragma language=default

/*******************************************************************************
* @fn          main
*
* @brief       Main program
*
* @param       void
*
* @return      int (does not return)
*/
int main(void) 
{        
    /* Initialize Clock Source (32 Mhz Xtal),
    *  global interrupt (EA=1),  I/O ports and pheripherals(LCD). */
    halBoardInit();
    
    init_ram_code(); 
    
    MEMCTR |= 0x08;    
    
    LedOnFunc();    
   
    for(;;)
}

I've add

-QRAMCODE=ROMCODE
-Z(DATA)RAMCODE=0x1E00-0x1F00
-Z(CODE)ROMCODE=0x4000-0x7FFF

to linker file.

The function LedOnFunc() works but from address 0x4000 checked by debugger. If I comment init_ram_code() LedOnFunc() works whatever. So how I can check the function run from RAM?

  • Hi Alex,

    Assigning an expert to comment.

    Thanks, 
    Elin 

  • Hello Alex,

    Please refer to section "2.2.5 Memory Arbiter" in the User's Guide (SWRU191):

    MEMCTR.XMAP must be set to enable program execution from RAM.

    XDATA map to code. When this bit is set, the SRAM XDATA region, from 0x0000
    through (SRAM_SIZE – 1), is mapped into the CODE region from 0x8000 through
    (0x8000 + SRAM_SIZE – 1). This enables execution of program code from RAM.

    Then you can observe the Program Counter (PC) register to observe where the code is running from.

    I drafted an UNTESTED function below. I am not sure if it will run based on XDATA function pointer type or if has to be converted to a code pointer according the the mapping described above.Feel free to test and correct me.

    typedef void (*VFPTR)(void);
    
    /* Where in RAM the function to be run will reside. Must be big enough! */
    static uint16 __xdata ramFuncAddr[RAM_BUF_SIZE];
    
    /*******************************************************************************
    * @fn          runFunctionFromRam
    *
    * @brief       Copies another function from flash to RAM and executes the
    *              function. Does check whether the space provided in RAM is enough,
    *              this must be done prior to the call.
    *
    * @param       void (*func)(void) - address of function to be run from RAM.
    *              uint8 __xdata *ramAddr - adress of function location in RAM.
    *              uint16 funcLength - size of buffer to place function in [bytes].
    *
    * @return      void
    *******************************************************************************/
    void runFunctionFromRam(void (*func)(void), uint16 __xdata *ramAddr,
    						uint16 funcLength)
    {
        /* flashFuncAddr is a pointer to where in flash the function is. */
        uint16 __code *flashFuncAddr = (uint16 __code *)(uint16)func;
    
        /* f is a function pointer to the address in RAM where the function will be
         * placed.
         */
        VFPTR f = (VFPTR)(uint16)ramAddr;
    
        /* Copy the function from flash to RAM. */
        uint16 i;
        for (i = 0; i < funcLength; i++)
        {
            ramAddr[i] = flashFuncAddr[i];
        }
        
        MEMCTR |= XMAP;
    
        /* Run function from RAM. */
        (*f)();
    
        MEMCTR |= XMAP;
    
        return;
    }
    
    
    /* Copy the flash write function to RAM and execute it. */
    runFunctionFromRam(funcion2RunFromRam, ramFuncAddr, sizeof ramFuncAddr);

  • Also refer to "2.2.1 Memory Map" section in the User's Guide (SWRU191) for more details.