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.

Compiler/CC2640R2F: Export the last filled address to variable using linker command file and split sections

Part Number: CC2640R2F


Tool/software: TI C/C++ Compiler

Hello,

I am developing a sample application for the CC2640R2 that is intended to be upgraded over the air via a BLE connection.

The design has the following constraints.

  1. An Image header must start at the beginning of the image. This must be page aligned 
  2. The entry section must follow immediately after the image header and must be tacked to a known address in flash
  3. The last filled address must be exported via the linker command file to a variable. This variable is then used to fill a header structure in a .c file that is sent OTA
  4. Flash should be filled sequentially from lower addresses to high address while minimizing the number of gaps in placement.

My question is how to reliably know the last filled address of within the image. Ideally I would like to split sections for optimal placement, and use groups to ensure that required sections are placed in order. However in some images that have .snvSectors the flashEndAddr is not really placed at .cinit. However .cinit cannot be split.

Below are the relevant snippets of the linker file:

MEMORY
{
  /* EDITOR'S NOTE:
   * the FLASH and SRAM lengths can be changed by defining
   * ICALL_STACK0_START or ICALL_RAM0_START in
   * Properties->ARM Linker->Advanced Options->Command File Preprocessing.
   */

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

  ENTRY (RX) : origin = ENTRY_START, length = ENTRY_SIZE
  FLASH_IMG_HDR (RX) : origin = OAD_HDR_START, length = OAD_HDR_SIZE
  SRAM (RWX) : origin = RAM_START, length = ICALL_RAM0_START - RAM_START
}

// ... Some parts have been redacted for readability/simplicity of example

SECTIONS
{
  GROUP > FLASH_IMG_HDR
  {
    .image_header align PAGE_SIZE
  }

  GROUP > ENTRY
  {
    .resetVecs
    .intvecs
    EntrySection  LOAD_START(prgEntryAddr)
  }

  GROUP >>  FLASH
  {
    .text
    .const
    .constdata
    .rodata
    .emb_text
    .pinit
  }

  .cinit          :   > FLASH LOAD_END(flashEndAddr)
  .snvSectors     :   > FLASH (HIGH)
}

  • Things I have tried:

    1. Exporting the SPC to a symbol as per 8.5.10.2 in the TI ARM Assembly Language user's guide. and assigning it after the last placement in the sections directive above
    2. Manually tack the .cinit section to a low address (immediately following the entry section). This did not seem to work. It still would move the section to the end of flash.

    Thanks in advance for the help!
  • Sean2 said:
    My question is how to reliably know the last filled address of within the image.

    For one memory range (like FLASH) pick exactly one output section to be last.  Then use the HIGH placement specifier on that section.  For more details see the section titled Controlling Placement Using The HIGH Location Specifier in the ARM assembly tools manual.  To capture the last address, use the appropriate END operator from the section titled Address and Dimension Operators.  

    Looking at your linker command file code, this ...

    Sean2 said:
    GROUP >> FLASH
    {
       .text
       .const
       .constdata
       .rodata
       .emb_text
       .pinit
    }

    .cinit : > FLASH LOAD_END(flashEndAddr)
    .snvSectors : > FLASH (HIGH)

    ... doesn't need a GROUP.  Just allocate each output section in FLASH, and the let the linker choose the order, with the exception of the one output section you use HIGH on.  

    Thanks and regards,

    -George

  • George,

    Thanks for the quick reply. The issue is that I would like to (if possible) pack the code to the lower addresses by default. 

    The reason why is that the image will be transformed into a .bin file and sent over the air. There may be a case where the FLASH region can be up to let's say 0x1F000, but the image built by the toolchain only consumes 0x9000 bytes. In this case I would not want to place anything beyond 0x9000 to save space and complexity of the image to be sent over the air. This is why I was attempting to use the GROUP directive to place everything sequentially in lower flash addresses.

     The sequential requirement is not required, but I would like to avoid using the HIGH directive on anything besides the SNV sectors (which are not part of the image sent OTA).

  • I cannot think of a good solution for your situation.  What about ...

      GROUP
      {
        .text
        .const
        .constdata
        .rodata
        .emb_text
        .pinit
        .cinit
      } > FLASH, END(flashEndAddr)

    That puts all of those sections in FLASH, in that order, and assigns the highest address used to flashEndAddr.  This is a bit more restrictive than you need.  But I think it is worth a try.

    However, I won't be surprised if this causes some other problem to show up.  It would be better if, without using GROUP, you could capture the highest address in FLASH.  I filed CODEGEN-2377 in the SDOWP system to request that capability in the linker.  You are welcome to follow it with the SDOWP link below in my signature.

    Thanks and regards,

    -George