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.

CC2652PSIP: Execution functions from RAM and binary file for firmware upgrade

Part Number: CC2652PSIP

Hello,

In order to implement firmware upgrade feature for CC2652PSIP, some functions must be executed from RAM. The .map-file shows that function is located in RAM, but size of binary file is more than 0x20,000,000, the expected size of binary file is 0x58,000. It looks like functions located in RAM are included in binary file.

Functions are declared by:

__attribute__((section(".TI.ramfunc"))) u32 crcImageCheck(void);

Sections in the .cmd - file look like:

SECTIONS
{
.intvecs : > FLASH_START
.text : >> FLASH | FLASH_LAST_PAGE
.const : >> FLASH | FLASH_LAST_PAGE
.constdata : >> FLASH | FLASH_LAST_PAGE
.rodata : >> FLASH | FLASH_LAST_PAGE
.cinit : > FLASH | FLASH_LAST_PAGE
.pinit : >> FLASH | FLASH_LAST_PAGE
.init_array : > FLASH | FLASH_LAST_PAGE
.emb_text : >> FLASH | FLASH_LAST_PAGE
.ccfg : > FLASH_LAST_PAGE (HIGH)

GROUP > SRAM
{
.data
#ifndef CACHE_AS_RAM
.bss
#endif /* CACHE_AS_RAM */
.vtable
.vtable_ram
vtable_ram
.sysmem
.TI.ramfunc
.nonretenvar
/*This keeps ll.o objects out of GPRAM, if no ll.o would be placed here
the warning #10068 is supressed.*/
#ifdef CACHE_AS_RAM
ll_bss
{
--library=*ll_*.a<ll.o> (.bss)
--library=*ll_*.a<ll_ae.o> (.bss)
}
#endif /* CACHE_AS_RAM */
} LOAD_END(heapStart)

.stack : > SRAM (HIGH) LOAD_START(heapEnd)


#ifdef CACHE_AS_RAM

.bss :
{
*(.bss)
} > GPRAM
#endif /* CACHE_AS_RAM */
}

The post_build step looks like:

"${CCS_INSTALL_ROOT}/utils/tiobj2bin/tiobj2bin" "${BuildArtifactFileName}" "${BuildArtifactFileBaseName}.bin" "${CG_TOOL_ROOT}/bin/tiarmofd" "${CG_TOOL_ROOT}/bin/tiarmhex" "${CCS_INSTALL_ROOT}/utils/tiobj2bin/mkhex4bin"

What should be done to have 0x58,000 byte binary file for project that runs functions from RAM? The FLASH image should include these functions and copy them into RAM on modem's start-up.

Thanks,

Alex  

  • Hello Alex,

    The disparity between your .map file evaluation and binary file size is that binary file holes, i.e. gaps between initialized sections 0x58000 to 0x20000000, are filled by the tiobj2bin tool. Since holes have to be represented by being filled, workarounds include creating two separate bin files or using different file outputs.  Here are some relevant E2E threads:

    https://e2e.ti.com/f/1/t/935537 
    https://e2e.ti.com/f/1/t/1192341 

    Regards,
    Ryan

  • Thanks for so fast response, Ryan.

    The binary file's size is not a big problem: it could be cut to 0x58000. My concern is that executed from RAM functions are located after address 0x20,000,000  (RAM) in binary file and I can't find copies of these functions in FLASH. They must be initially located in FLASH and copped into RAM on startup.

    Thanks,

    Alex

  • Thanks for clarifying.  I recommend that you refer to the Load at One Address, Run from a Different Address section of the linked TI Linker Command File Primer guide.  There are also multiple relevant E2E threads on this.

    Regards,
    Ryan

  • Thanks. Binary file looks good now and start addresses of FLASH upgrade functions are located in RAM. What is the easiest way to copy few functions from  FLASH to SRAM. All these functions are located at different not neighbouring locations.

    Thanks,

    Alex

  • I recommend using memcpy (possibly osal_memcpy if the osal layer is used by your code).  I would be remiss to not include relevant E2E threads at this point.  It is worth noting that BLE OAD applications will use a static persistent application to avoid copying functions which should persist through OAD updates from Flash to RAM.  This is covered in the on-chip OAD sections of the BLE5-Stack User's Guide.

    Regards,
    Ryan

  • The .map file contains the following section:

    LINKER GENERATED COPY TABLES

    .........

    BINT @ 0002accc records: 1, size/record: 12, table size: 16
    .TI.ramfunc: load addr=0000003c, load size=0000033c, run addr=20000fe0, run size=0000033c, compression=none

    It means that there is mechanism to copy functions FLASH -> SRAM, but the load addr=0000003c is wrong. What part of project defines the "load start" address ?

    Regards,

    Alex

  • Here is a link to the TI Arm Clang Compiler Tools User Guide.  I will ask the TI Compiler Team to further comment on your inquiry.

    Regards,
    Ryan

  • Hi Alex,

    I'm not sure how your project has changed since the start of the thread, but you should include an explicit placement in your linker command file for .TI.ramfunc that ensures it is loaded to the address you intend (prior to the copy to SRAM)

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

    Of course, this is described in the TI linker primer that Ryan linked to above, so you may be already doing this. You can also use a hard coded address for the "load=" as well.  Can you show an example of your linker command file placement?  I'd like to understand why the load address you're getting is wrong.

    Thanks,

  • Hi Alan,

    My project is based on "simple_peripheral" project for CC2652PSIP, my CCS has v.12.2.0.202212151800, my silmplelink_cc13xx_cc26xx_sdk_6_40_00_13.

    I tried few options to determine this section and got wrong "load addr" or errors :

    OPTION #1

      .TI.ramfunc     :   {} load = FLASH, run = SRAM, table(BINT)

    From the .map - file:

    LINKER GENERATED COPY TABLES

    BINT @ 0002accc records: 1, size/record: 12, table size: 16
    .TI.ramfunc: load addr=0000003c, load size=0000033c, run addr=20000fe0, run size=0000033c, compression=none

    OPTION #2

      .TI.ramfunc     :   {} load = FLASH, run = SRAM, load_start = 0x2accc, load_end = 0x2b008, table(BINT)

    ***** CCS reports error that "=" cannot be used, use only (). 

    OPTION #3

      .TI.ramfunc     :   {} load = FLASH, run = SRAM, load_start(0x2accc), load_end(0x2b008), table(BINT)

    ***** CCS reports error that "expecting "<name>" instead of "0x2accc""

    OPTION #4

    _RamfuncsLoadStart = 0x2accc;

    _RamfuncsLoadEnd = 0x2b008;

      .TI.ramfunc     :   {} load = FLASH, run = SRAM, load_start(_RamfuncsLoadStart), load_end(_RamfuncsLoadEnd), table(BINT)

    ***** CCS reports: warning #10190-D: absolute symbol "_RamfuncsLoadStart" being redefined

    From the .map - file:

    BINT @ 0002accc records: 1, size/record: 12, table size: 16
    .TI.ramfunc: load addr=0000003c, load size=0000033c, run addr=20000fe0, run size=0000033c, compression=none

    OPTION #5

      .TI.ramfunc     :   {} load = FLASH, run = SRAM, load_start(_RamfuncsLoadStart), load_end(_RamfuncsLoadEnd), table(BINT)

    From the .map - file:

    BINT @ 0002accc records: 1, size/record: 12, table size: 16
    .TI.ramfunc: load addr=0000003c, load size=0000033c, run addr=20000fe0, run size=0000033c, compression=none

    I can assume that symbols: _RamfuncsLoadStart, _RamfuncsLoadEnd are taken from the file simple_peripheral_LP_CC2652PSIP_tirtos7_ticlang_linkInfo.xml 

    </symbol>
    <symbol id="sm-6">
    <name>_RamfuncsLoadStart</name>
    <value>0x3c</value>
    </symbol>
    <symbol id="sm-7">
    <name>_RamfuncsLoadEnd</name>
    <value>0x378</value>

    What parameters in project's configuration are used for the initialisation of the symbol _RamfuncsLoadStart in this file? What is the magic address: 0x3C?  How could it be fixed?

    Thanks,

    Alex

  • Hi Alex,

    Presently the linker is choosing a location inside of the FLASH memory region to place the section.  I don't see the memory region configuration of your linker command file, but presumably address ix 0x3x is within that region. 

    The load_start and load_end operators can only be used to identify symbols that the linker will generate to contain the chosen start and end addresses, respectively. 

    To vary the actual location of the load, you need to adjust the "load=FLASH" setting by either creating a new memory region with the location you intend or hand-coding the desired address. For example:

    .TI.ramfunc     :   {} load = 0x2accc, run = SRAM

    You can also specify alignment requirements for the section placement, which is described in the documentation.

    -Alan

  • Hi Alan,

    The hand-coding desired address works, but the address varies every time I build my project. Having more universal solution is more preferable. Could you provide, please, more information about another solution you recommended? 

    Regards,

    Alex

  • Hi Alex,

    This will depend on the configuration of your memory ranges in your linker command file.  Look at the this section of the Compiler Guide concerning the MEMORY directive; you will need to ensure your memory regions are configured correctly, and then you can place your .TI.ramfunc load placement at the right location.

    .TI.ramfunc     :   {} load = YOURREGION, run = SRAM

    Based on what I see above, presently .TI.ramfunc is just being placed in the memory region called FLASH, which doesn't appear to be configured according to the memory address ranges you expect.

    -Alan

  • Hi Alan,

    The MEMORY section looks like:

    /*******************************************************************************
    * Memory Sizes
    */
    #define FLASH_BASE 0x00000000
    #define GPRAM_BASE 0x11000000
    #define RAM_BASE 0x20000000
    #define ROM_BASE 0x10000000

    #define FLASH_SIZE 0x00058000
    #define GPRAM_SIZE 0x00002000
    #define RAM_SIZE 0x00014000
    #define ROM_SIZE 0x00040000

    #define RTOS_RAM_SIZE 0x0000012C
    #define RESERVED_RAM_SIZE_ROM_1 0x00000B08
    #define RESERVED_RAM_SIZE_ROM_2 0x00000EB3

    /*******************************************************************************
    * Memory Definitions
    ******************************************************************************/

    /*******************************************************************************
    * RAM
    */
    #if defined(FLASH_ROM_BUILD)
    #if (FLASH_ROM_BUILD == 1)
    #define RESERVED_RAM_SIZE_AT_START 0
    #define RESERVED_RAM_SIZE_AT_END RESERVED_RAM_SIZE_ROM_1
    #else // (FLASH_ROM_BUILD == 2)
    #define RESERVED_RAM_SIZE_AT_START (RTOS_RAM_SIZE + RESERVED_RAM_SIZE_ROM_2)
    #define RESERVED_RAM_SIZE_AT_END 0
    #endif
    #else /* Flash Only */
    #define RESERVED_RAM_SIZE_AT_START 0
    #define RESERVED_RAM_SIZE_AT_END 0
    #endif // FLASH_ROM_BUILD

    #define RAM_START (RAM_BASE + RESERVED_RAM_SIZE_AT_START)
    #ifdef ICALL_RAM0_START
    #define RAM_END (ICALL_RAM0_START - 1)
    #else
    #define RAM_END (RAM_BASE + RAM_SIZE - RESERVED_RAM_SIZE_AT_END - 1)
    #endif /* ICALL_RAM0_START */

    /* For ROM 2 devices, the following section needs to be allocated and reserved */
    #define RTOS_RAM_START RAM_BASE
    #define RTOS_RAM_END (RAM_BASE + RTOS_RAM_SIZE - 1)

    /*******************************************************************************
    * Flash
    */

    #define FLASH_START FLASH_BASE
    #define WORD_SIZE 4

    #define PAGE_SIZE 0x2000

    #ifdef PAGE_ALIGN
    #define FLASH_MEM_ALIGN PAGE_SIZE
    #else
    #define FLASH_MEM_ALIGN WORD_SIZE
    #endif /* PAGE_ALIGN */

    #define PAGE_MASK 0xFFFFE000

    /* The last Flash page is reserved for the application. */
    #define NUM_RESERVED_FLASH_PAGES 1
    #define RESERVED_FLASH_SIZE (NUM_RESERVED_FLASH_PAGES * PAGE_SIZE)

    /* Check if page alingment with the Stack image is required. If so, do not link
    * into a page shared by the Stack.
    */
    #ifdef ICALL_STACK0_START
    #ifdef PAGE_ALIGN
    #define ADJ_ICALL_STACK0_START (ICALL_STACK0_START * PAGE_MASK)
    #else
    #define ADJ_ICALL_STACK0_START ICALL_STACK0_START
    #endif /* PAGE_ALIGN */

    #define FLASH_END (ADJ_ICALL_STACK0_START - 1)
    #else
    #define FLASH_END (FLASH_BASE + FLASH_SIZE - RESERVED_FLASH_SIZE - 1)
    #endif /* ICALL_STACK0_START */

    #define FLASH_LAST_PAGE_START (FLASH_SIZE - PAGE_SIZE)

    MEMORY
    {
    FLASH (RX) : origin = FLASH_START, length = (FLASH_END - FLASH_START + 1)

    FLASH_LAST_PAGE (RX) : origin = FLASH_LAST_PAGE_START, length = PAGE_SIZE

    #if (defined(FLASH_ROM_BUILD) && (FLASH_ROM_BUILD == 2))
    RTOS_SRAM (RWX) : origin = RTOS_RAM_START, length = (RTOS_RAM_END - RTOS_RAM_START + 1)
    #endif
    SRAM (RWX) : origin = RAM_START, length = (RAM_END - RAM_START + 1)

    #ifdef CACHE_AS_RAM
    GPRAM(RWX) : origin = GPRAM_START, length = GPRAM_SIZE
    #endif /* CACHE_AS_RAM */
    }

    Regards,

    Alex

  • Hi Alex,

    Given that the memory region for FLASH is defined as:

    FLASH (RX) : origin = FLASH_START, length = (FLASH_END - FLASH_START + 1)

    With FLASH_START defined to be 0x00000000, and since .TI.ramfunc is being placed in FLASH (for load), the linker is simply choosing an available address in that region to place the section where it can fit, which ends up being 0x0000003c.  If that address is incorrect, you've got to create a new memory region to use to place the section appropriately.  The documentation describes how to do that.

    -Alan

  • Hi Alan,

    The start address  0x0000003c, located in Vector Addresses area, was confusing. Since vectors 15 and above are not used currently, it explains everything. The  symbols  _RamfuncsLoadStart, _RamfuncsLoadEnd are determined based on this fact. Relocated to SRAM functions works properly.

    Thanks,,

    Alex