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.

RTOS/F28M35H52C: Code execution in external SRAM using EPI

Part Number: F28M35H52C
Other Parts Discussed in Thread: CONTROLSUITE

Tool/software: TI-RTOS

Hi,

I have a question concerning the execution of code in external SRAM.

Configuration:
Target F28M35H52C1 (Cortex-M3 + C2000 DSP)    CCS Version: 5.5.0.00077    Compiler TI v5.1.1    IPC 3.10.1.11     SYS/BIOS 6.35.04.50    TI RTOS 1.20.0.28
Hardware is a custom board with F28M35H52C1 processor, 2 Mbyte external SRAM (Alliance Memory AS6C1616-55TIN) and LCD controller (EPSON S1D13742) on EPI bus.

I already use this external SRAM to store GUI images (1Mbyte) and the display buffer (768 Kbytes), and some other sections.

The external SRAM I am using is composed of 1,048,576 words of 16 bits. I configured it using EPI 16-Bit Host Bus (HB-16) Mode, without Byte Selects.
This means that I cannot read or write individual bytes.

Our project is filling the entire space in internal RAM and Flash. The original idea was to put the.bss section in the external SRAM to free some space, which is impossible as we cannot read/write individual bytes but only words of 16 bits. (Original thread: https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/683155)

So an other idea is to load code (from SD card for example) in external RAM to execute it. As the instructions are 16bits we would not need access to individual bytes, so it could work.

First, is this doable ?
Then, what would be the steps to implement this solution ?

Thank you in advance for your help.
Yours Sincerely,
Paul Noalhyt

  • Paul,

    Yes, you should be able to execute C28x instructions out of your 16b-fixed EPI RAM because the C28x is 16b-addressable.  I suppose you should be able to execute M3 code out of 16b-fixed EPI RAM as well because the instructions are either 16b or 32b.

    You would just need to initialize the EPI RAM as you normally would and copy the code from SD to EPI RAM.  Then you can use function pointers to execute out of EPI memory space.  However, I expect that function pointers will get messy quickly so another option would be to instruct the linker command file to use its load and run from different addresses feature.  You can store the LOAD image into SD at build-time and restore the functions to EPI RAM at run-time before executing out of EPI.

    Keep in mind that the EPI interface has slower throughput than the internal RAMs so you will have some performance degradation.

    -Tommy

  • Hi Tommy,

    Thank you for your answer. The second option sounds very promising. The thing is that load and run from different addresses feature expects the code to be in flash first and then be loaded into RAM.

    Moreover, I read that there is an automatic copy of the ramfuncs from flash to RAM, which uses .binit section:

     .TI.ramfunc : {} load=FLASH, run=RAM, table(BINIT)
     .binit : {} > FLASH

    So everything seems to be handled by the compiler and linker file.

    So my question are:

    1. How can I implement my own copy function from SD to external RAM ? Where would I call this function ?
    2. How do I tell the linker to only RUN from external memory but not load from Flash ?
    3. How do I get the file containing only the ramfuncs, to place it on the SD card ? Can CCS generate 2 .out files: one for internal Flash, and one for ramfuncs ?

    Thank you.
    Bests,
    Paul

  • Paul,

    I'm going to move this thread into the compiler forum because I honestly don't know enough about the topic. Below are my best guesses.  There may be an easier way to approach this.

    The "FLASH" and "RAM" labels are just memory sections that are defined in the .cmd file. It does not need to be strictly located in FLASH or RAM. If you forego the BINIT table, the compiler should not try to copy the functions automatically.

    The reason for using Load/Run is so that the compiler will pack the code into a block for you and report the starting address and size through the variables specified in the .cmd file.  Otherwise, you would need to figure this out on your own.  For the controlSUITE examples, they are the RamfuncsRunStart, RamfuncsLoadStart, and RamfuncsLoadSize variables. 

    Paul Noalhyt said:
    How can I implement my own copy function from SD to external RAM ? Where would I call this function ?


    You would need to create your own function to copy code from SD to EPI RAM. It would ultimately behave like the memcpy performed in the controlSUITE examples:

    // The  RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart
    // symbols are created by the linker. Refer to the device .cmd file.
        memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);

    Paul Noalhyt said:
    How do I tell the linker to only RUN from external memory but not load from Flash ?

    You can specify any memory section for LOAD and RUN.  See the Assembly Language User's Guide.

    Paul Noalhyt said:
    How do I get the file containing only the ramfuncs, to place it on the SD card ? Can CCS generate 2 .out files: one for internal Flash, and one for ramfuncs ?


    For your situation, you would need two steps to load the program.

    For example, assuming that you have enough EPI RAM capacity, you can set both the LOAD and RUN locations to EPI RAM.  Build the project and load the program.  Record the generated Ramfuncs* variable values.

    With the data retained in EPI RAM, use a second project (that does not use the LOAD EPI RAM sections) to copy the EPI RAM code into your SD card using the RamfuncsLoadStart and RamfuncsLoadSize variable values.  When your application runs, it can restore the ramfuncs from SD to EPI RAM using the RamfuncsRunStart and RamfuncsLoadSize variable values.

    -Tommy

  • I think it is most helpful if I comment on only one thing.  And even then, to comment on it in a general way, rather than being specific to this situation.

    There is some confusion about the purpose of copy tables.  Copy tables are a more convenient way to do this ...

     ramfuncs : LOAD = FLASHD,
                RUN = RAML0,
                LOAD_START(_RamfuncsLoadStart),
                LOAD_END(_RamfuncsLoadEnd),
                RUN_START(_RamfuncsRunStart)

    Yes, that is copied from Load at One Address, Run from a Different Address, which was referenced earlier in this thread.  Here is one way to do the same thing, but with a copy table.  

    ramfuncs : LOAD = FLASHD, RUN = RAML0, table(ramfuncs_copy_table)
    /* several lines later */
    .ovly > FLASHD

    The allocation for load and run is the same.  Instead of creating all those symbols, that same information is in a copy table with the name ramfuncs_copy_table.  The copy table itself is in an output section named .ovly, which is allocated to FLASHD.  Note this does not cause ramfuncs to actually be copied at runtime.  Before any call to a function in ramfuncs occurs, this must execute ...

    #include <cpy_tbl.h>
    /* many lines later */
        copy_in(&ramfuncs_copy_table);

    This is similar to the memcpy call shown earlier in this thread.  The function copy_in is from the compiler RTS library.  It knows the format of the auto-generated linker copy tables.  It uses the copy table entry to copy the ramfuncs from FLASHD to RAML0.

    Further details, and an extended example, are in the application note Advanced Linker Techniques for Convenient and Efficient Memory Usage.  The example is for a C6000 system, so you can't use it directly.  But it is still a good way to learn about copy tables.

    One variant on copy tables to consider ... Instead of a user specified copy table, you can use the special operand BINIT ...

    ramfuncs : LOAD = FLASHD, RUN = RAML0, table(BINIT)

    This causes the copy table to be added to those that are automatically detected and processed by the startup code in the compiler RTS library.

    Thanks and regards,

    -George

  • Paul,

    It has been over two weeks since your last update. I assume that you were able to resolve your issue. If this isn’t the case, please reject this resolution and reply to this thread. If this thread is locked, please make a new thread describing the current status of your issue.

    -Tommy