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.

How to configure TI Hercules board RM48L952ZWT to execute code and data out of external SDRAM but code are stored in Flash

Other Parts Discussed in Thread: HALCOGEN

Hello, we are using the HalCoGen RM48L952ZWT and I am currently running out of internal RAM to execute the code and data.

I stored the code in Flash and execute them out of Flash. The code use internal RAM for all variables, stack, global variables, etc. and I have a realtime OS to manage the code. All tasks were created and used internal RAM for its stack and data allocation.

I like to use external SDRAM for them now.

My question is how to configure the project to use external SDRAM including the linker, sys_link.cmd file, the linker option file, etc. and specify the size of SDRAM for linker, option file.

What are the methods that I have available to configure the project for this purpose? And what is the best option?

I have a realtime OS that I am using to create tasks and these tasks need stack space, and data space large enough to run them. Now I need to use external SDRAM for these tasks. Currently they are all using internal RAM and I am out of space for them to run.

It is urgent that I need a solution to utilize external SDRAM for the code and data to run but the code still need to be downloaded and stored in Flash first.

Thanks for giving me a solution.

Kenneth Lai

  • HI Kenneth,

     We don't have a SDRAM example for RM48 device but we have one for the RM57L device. So I will recommend you to reference the RM57L SDRAM example provided by HalCoGen. Please temporarily create a new  RM57L project in HalCoGen. Once the project is create you can go to Help->Help Topics->Examples->example_emif_sdram.c. You can follow the step by step instructions to configure the EMIF. You will need to configure the SDRAM timing. The HalCoGen provides SDRAM parameters for the SDRAM used in the HDK but you will need to adjust the parameters for the SDRAM of your choice. It will also configure the PINMUX. Even though this example is for RM57L but the steps to create the same for RM48 should be the same. The HalCoGen example will create the corresponding linker command file. I'm showing the snippet below. This example will run code out of SDRAM. Since  RM57L is a cache based device, execute code from SDRAM will not impact much performance. For RM48 I will suggest that you only use SDRAM for data storage but not code execution as it will be slow. The SDRAM region is memory mapped at 0x80000000. 

    /*----------------------------------------------------------------------------*/
    /* Linker Settings                                                            */
    
    --retain="*(.intvecs)"
    
    /* USER CODE BEGIN (1) */
    --retain="*(.blinky_section)"
    /* USER CODE END */
    
    /*----------------------------------------------------------------------------*/
    /* Memory Map                                                                 */
    
    MEMORY
    {
    /* USER CODE BEGIN (2) */
    /* USER CODE END */
        VECTORS (X)  : origin=0x00000000 length=0x00000020
        FLASH0  (RX) : origin=0x00000020 length=0x001FFFE0
        FLASH1  (RX) : origin=0x00200000 length=0x00200000
        STACKS  (RW) : origin=0x08000000 length=0x00001500
        RAM     (RW) : origin=0x08001500 length=0x0007EB00
    
    /* USER CODE BEGIN (3) */
    	SDRAM (RWX) : origin=0x80000000 length=0200000000
    /* USER CODE END */
    }
    
    /* USER CODE BEGIN (4) */
    /* USER CODE END */
    
    
    /*----------------------------------------------------------------------------*/
    /* Section Configuration                                                      */
    
    SECTIONS
    {
    /* USER CODE BEGIN (5) */
    /* USER CODE END */
        .intvecs : {} > VECTORS
        .text   align(8) : {} > FLASH0 | FLASH1
        .const  align(8) : {} > FLASH0 | FLASH1
        .cinit  align(8) : {} > FLASH0 | FLASH1
        .pinit  align(8) : {} > FLASH0 | FLASH1
        .bss     : {} > RAM
        .data    : {} > RAM
        .sysmem  : {} > RAM
    	
    
    /* USER CODE BEGIN (6) */
    	.blinky_section : RUN = SDRAM, LOAD = FLASH0 | FLASH1
    					  LOAD_START(BlinkyLoadStart), LOAD_END(BlinkyLoadEnd), LOAD_SIZE(BlinkySize),
    					  RUN_START(BlinkyStartAddr), RUN_END(BlinkyEndAddr)
    /* USER CODE END */
    }
    
    /* USER CODE BEGIN (7) */
    /* USER CODE END */
    
    
    /*----------------------------------------------------------------------------*/
    /* Misc                                                                       */
    
    /* USER CODE BEGIN (8) */
    /* USER CODE END */
    /*----------------------------------------------------------------------------*/

  • Hi Charles,

    Thank you for your reply. I tried to follow the steps in RM57L to configure the project for RM48 to use external SDRAM.

    The main() is called in the sys_startup.c of the Halcogen BSP and I like this main() and all of the code to be executed out of SDRAM. I noticed in the sys_link.cmd of the RM57L project we specified the code section name "blinky_section" and we put all this code into SDRAM and executed out of SDRAM at run-time. How do I do that for my project that start with main() function?

    Thanks in advance for your help.

    Kenneth Lai
  • Hi Kenneth,

     I don't understand what you meant by how to start your project from main() function? Doesn't your project also have the sys_startup.c where it will eventually call your main()?

    The application needs to copy the blinky routine from flash to SDRAM before you can execute code out of SDRAM.

    /* USER CODE BEGIN (2) */
    #pragma SET_CODE_SECTION(".blinky_section")
    void blinky()
    {
    	int i;
    	gioSetDirection(hetPORT1, 1);
    	while(1)
    	{
    		gioToggleBit(hetPORT1, 0);
    		for(i=0;i<1000000;i++);
    	}
    }
    #pragma SET_CODE_SECTION()
    
    extern uint32 BlinkyLoadStart;
    extern uint32 BlinkyLoadEnd;
    extern uint32 BlinkySize;
    extern uint32 BlinkyStartAddr;
    extern uint32 BlinkyEndAddr;
    /* USER CODE END */
    
    uint8	emacAddress[6U] = 	{0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU};
    uint32 	emacPhyAddress	=	1U;
    
    void main(void)
    {
    /* USER CODE BEGIN (3) */
    	int i;
        uint32 size=(uint32)&BlinkySize;
    
    	emif_SDRAMInit();
    
        for(i=0;i<size;i++)
        {
            ((char *)&BlinkyStartAddr)[i] =((char *)&BlinkyLoadStart)[i];
        }
    
    	blinky();
    	while(1);
    /* USER CODE END */
    }

    Are you at least able to have the example working for your device?

  • Hi Charles,

    Thank you for your help. What I meant was I like to put all my code starting from main() function to be executed out of external SDRAM at run-time. But all this code still be programmed into flash and stored into flash first.

    I have another question on the "blinky_section" code example. I noticed all these variables are declared as extern in the code and I could not find where it is defined and how to change these names to reflect my actual code section. I don't want to call it "Blinky".

    extern uint32 BlinkyLoadStart;

    extern uint32 BlinkyLoadEnd;

    extern uint32 BlinkySize;

    extern uint32 BlinkyStartAddr;

    extern uint32 BlinkyEndAddr;

    Please help and I thank you for your help.

    Kenneth
  • Hi Kenneth,
    The BlinkLoadStart and the rest of the extern variables come from the linker command file. See below in the command file.

    .blinky_section : RUN = SDRAM, LOAD = FLASH0 | FLASH1
    LOAD_START(BlinkyLoadStart), LOAD_END(BlinkyLoadEnd), LOAD_SIZE(BlinkySize),
    RUN_START(BlinkyStartAddr), RUN_END(BlinkyEndAddr)

    You can change their name to your liking.

    Please refer to 3.1.1 Load and Run addresses section in the arm assembly language tool userguide www.ti.com/.../spnu118o.pdf on how to use them for details.

    I don't know how large your main() is. As I said, there is a performance penalty when running code from SDRAM compared to internal flash or RAM.
  • Hi Charles,

    Thanks for your help.

    I tried to define and change the name to be ".main_section" and the extern variables defined in the sys_link.cmd file as follows:

    /*----------------------------------------------------------------------------*/
    /* sys_link.cmd */
    /* */
    /*
    * Copyright (C) 2009-2015 Texas Instruments Incorporated - www.ti.com
    *
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    *
    * Redistributions of source code must retain the above copyright
    * notice, this list of conditions and the following disclaimer.
    *
    * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the
    * documentation and/or other materials provided with the
    * distribution.
    *
    * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    */

    /* */
    /*----------------------------------------------------------------------------*/
    /* USER CODE BEGIN (0) */
    /* USER CODE END */


    /*----------------------------------------------------------------------------*/
    /* Linker Settings */

    --retain="*(.intvecs)"

    /* USER CODE BEGIN (1) */
    --retain="*(.main_section)"
    /* USER CODE END */

    /*----------------------------------------------------------------------------*/
    /* Memory Map */

    MEMORY
    {
    VECTORS (X) : origin=0x00000000 length=0x00000020
    FLASH0 (RX) : origin=0x00000020 length=0x0017FFE0
    FLASH1 (RX) : origin=0x00180000 length=0x00180000
    STACKS (RW) : origin=0x08000000 length=0x00000900
    RAM (RW) : origin=0x08000900 length=0x0003f700

    /* USER CODE BEGIN (2) */
    SDRAM (RWX) : origin=0x80000000 length=0x00200000
    /* USER CODE END */
    }

    /* USER CODE BEGIN (3) */
    --heap_size 0x00200000

    /* USER CODE END */


    /*----------------------------------------------------------------------------*/
    /* Section Configuration */

    SECTIONS
    {
    .intvecs : {} > VECTORS
    .text : {} > FLASH0 | FLASH1
    .const : {} > FLASH0 | FLASH1
    .cinit : {} > FLASH0 | FLASH1
    .pinit : {} > FLASH0 | FLASH1
    .bss : {} > RAM
    .data : {} > RAM
    .sysmem : {} > RAM

    FEE_TEXT_SECTION : {} > FLASH0 | FLASH1
    FEE_CONST_SECTION : {} > FLASH0 | FLASH1
    FEE_DATA_SECTION : {} > RAM

    /* USER CODE BEGIN (4) */
    //FEE_DATA_SECTION : {} > SDRAM
    // .sysmem : {} > SDRAM

    /* USER CODE END */
    }

    /* USER CODE BEGIN (5) */

    .main_section : RUN = SDRAM, LOAD = FLASH0 | FLASH1

    LOAD_START(mainLoadStart), LOAD_END(mainLoadEnd), LOAD_SIZE(mainSize),

    RUN_START(maintartAddr), RUN_END(mainEndAddr)


    /* USER CODE END */


    /*----------------------------------------------------------------------------*/
    /* Misc */

    /* USER CODE BEGIN (6) */
    /* USER CODE END */
    /*----------------------------------------------------------------------------*/

    I rebuilt the code and TI RM48 target processor and received this errors below:

    'Building target: BiolasePFB_ProductionBoard.out'
    'Invoking: ARM Linker'
    'Flags: -mv7R4 --code_state=32 --float_support=VFPv3D16 --abi=eabi -me -g --gcc --display_error_number --diag_warning=225 --diag_wrap=off --enum_type=packed --printf_support=nofloat -z -m"BiolasePFB_ProductionBoard.map" --heap_size=0x800 --stack_size=0x800 -i"C:/ti/ccsv6/tools/compiler/arm_5.1.6/lib" -i"C:/ti/ccsv6/tools/compiler/arm_5.1.6/include" --reread_libs --warn_sections --display_error_number --diag_wrap=off --xml_link_info="BiolasePFB_ProductionBoard_linkInfo.xml" --rom_model'
    "C:/ti/ccsv6/tools/compiler/arm_5.1.6/bin/armcl" -@"ccsLinker.opt" -o "BiolasePFB_ProductionBoard.out"
    <Linking>
    "../Drivers/HalCoGen/source/sys_link.cmd", line 102: error #10008-D: cannot
    find file ".main_section"
    "../Drivers/HalCoGen/source/sys_link.cmd", line 102: error #10021-D: expecting
    filename, option, MEMORY, or SECTIONS instead of ":"
    "../Drivers/HalCoGen/source/sys_link.cmd", line 104: error #10043-D: expecting
    "";"" instead of "LOAD_START"
    warning #10247-D: creating output section ".main_section" without a SECTIONS specification
    "../Drivers/HalCoGen/source/sys_link.cmd", line 102: error #10104: undefined symbol "SDRAM" used in expression
    "../Drivers/HalCoGen/source/sys_link.cmd", line 102: error #10104: undefined symbol "FLASH0" used in expression
    "../Drivers/HalCoGen/source/sys_link.cmd", line 102: error #10104: undefined symbol "FLASH1" used in expression
    error #10010: errors encountered during linking; "BiolasePFB_ProductionBoard.out" not built

    >> Compilation failure
    gmake: *** [BiolasePFB_ProductionBoard.out] Error 1
    gmake: Target `all' not remade because of errors.

    **** Build Finished ****

    Please review and let me know what I have done wrong here. Thanks for your help

    Kenneth Lai
  • Hi Kenneth,

     Perhaps not the best way to do it. Below is what I do and it works for me. For advance usage on using load_address and run_address I will suggest that you post a new question to the compiler team as I'm not an expert in this. 

     1. in the sys_startup.c file I did the below. See the highlighted in red right before main() is called.

    /* USER CODE BEGIN (1) */
    #include "HL_emif.h"
    /* USER CODE END */

    /* USER CODE BEGIN (2) */
    extern uint32 MainLoadStart;
    extern uint32 MainLoadEnd;
    extern uint32 MainSize;
    extern uint32 MainStartAddr;
    extern uint32 MainEndAddr;
    /* USER CODE END */

      code snipped 

    /* initialize global variable and constructors */
    __TI_auto_init();
    /* USER CODE BEGIN (26) */

    emif_SDRAMInit();

    int i;
    uint32 size=(uint32)&MainSize;

    for(i=0;i<size;i++)
    {
    ((char *)&MainStartAddr)[i] =((char *)&MainLoadStart)[i];
    }
    /* USER CODE END */

    /* call the application */
    /*SAFETYMCUSW 296 S MR:8.6 <APPROVED> "Startup code(library functions at block scope)" */
    /*SAFETYMCUSW 326 S MR:8.2 <APPROVED> "Startup code(Declaration for main in library)" */
    /*SAFETYMCUSW 60 D MR:8.8 <APPROVED> "Startup code(Declaration for main in library;Only doing an extern for the same)" */
    main();

    * USER CODE BEGIN (27) */
    /* USER CODE END */
    /*SAFETYMCUSW 122 S MR:20.11 <APPROVED> "Startup code(exit and abort need to be present)" */
    exit(0);

    And in the sys_main.c, I did below highlighted in red.

    #pragma SET_CODE_SECTION(".main_section")

    void main(void)
    {
    /* USER CODE BEGIN (3) */

    int i;
    gioSetDirection(hetPORT1, 1);
    while(1)
    {
    gioToggleBit(hetPORT1, 0);
    for(i=0;i<1000000;i++);
    }
    /* USER CODE END */
    }
    #pragma SET_CODE_SECTION()



  • Hello Charles,

    Thank you for your help. I am now able to compile, build, and execute the code at run-time out of external SDRAM.

    But I have another issue. As I double the stack size and variables of my code, the internal RAM size can no longer hold these initialized data. I need to relocate these initialized data, the .bss, and .data to be stored in external SDRAM. I did it and the code compiled, built, and linked fine.

    However here is the issue:

    If I use the JTAG USB programmer to download the code and execute it without power cycle the target, the code and the data stored in external SDRAM ran fine. But after I power cycle the board, the data stored into external SDRAM got loss, and the code stored in flash no longer run fine because the initialized data supposed to be available in external SDRAM is no longer there after I powered cycle the board.

    How do I solve this issue? I need help to store the initialized data in flash but at run-time copy that initialized data into external SDRAM because the internal RAM is not enough to store these initialized data when the code run.

    Please help and I thank you for your help.

    Kenneth Lai