This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Specifying RAM address in .ld does generate spurious flash section

Hello there,

In order to have a continuous RTT debug during DFU, I followed advices found in:

- https://devzone.nordicsemi.com/f/nordic-q-a/20708/rtt-logging-from-application-started-by-bootloader

- https://devzone.nordicsemi.com/f/nordic-q-a/30310/easy-way-to-merge-bootloader-and-application-rtt-output

It seems to work, but the bootloader's .hex generated has spurious sections (full of zero) that correspond to the 3 blocks for which the address is fixed in my .ld file:

hexinfo.py build/nrf52832_xxaa_s132.hex

- file: 'build/nrf52832_xxaa_s132.hex'
entry: 0x700080E5
data:
- { first: 0x00072000, last: 0x0007CEAF, length: 0x0000AEB0 }
- { first: 0x0007E1D8, last: 0x0007E5D7, length: 0x00000400 }
- { first: 0x0007E9D8, last: 0x0007EA1B, length: 0x00000044 }
- { first: 0x0007EA58, last: 0x0007EACF, length: 0x00000078 }
- { first: 0x10001014, last: 0x1000101B, length: 0x00000008 }

Extracts of my .ld file:

MEMORY
{
  FLASH (rx) : ORIGIN = 0x72000, LENGTH = 0xC000

  /** RAM Region for bootloader. This setting is suitable when used with s132. */
  RAM (rwx) :  ORIGIN = 0x20002C00, LENGTH = 0xc400

  /** Location of bootloader setting in flash. */
  BOOTLOADER_SETTINGS (rw) : ORIGIN = 0x0007F000, LENGTH = 0x1000

  /** Location in UICR where bootloader start address is stored. */
  UICR_BOOTLOADER (r) : ORIGIN = 0x10001014, LENGTH = 0x04

  /** Location of mbr params page in flash. */
  MBR_PARAMS_PAGE (rw) : ORIGIN = 0x0007E000, LENGTH = 0x1000

  /** Location in UICR where mbr params page address is stored. */
  UICR_MBR_PARAM_PAGE(r) : ORIGIN = 0x10001018, LENGTH = 0x04
}

SECTIONS
{
   [...]
}

SECTIONS
{
   [...]

  . = ALIGN(4);
  .dfu_trans :
  {
    PROVIDE(__start_dfu_trans = .);
    KEEP(*(.dfu_trans))
    PROVIDE(__stop_dfu_trans = .);
  } > RAM

  .rtt_ac_up 0x20004000 :
  {
    KEEP(*(.rtt_ac_up))
  } > RAM

  .rtt_ac_down 0x20004800 :
  {
    KEEP(*(.rtt_ac_down))
  } > RAM

  .rtt_segger 0x20004880 :
  {
    KEEP(*(.rtt_segger))
  } > RAM

} INSERT AFTER .data

The problems:

- 0x7e000 is reserved for MBR. How could the linker allow this ?

- since data should be handled by RTT,  I  do not want to use NOLOAD

- why can't those sections remain in bss (the zones are zeroes only). It inflates the .hex for nothing (and especially forbids a DFU of the bootloader since the new one does not fit in the previous one, which is why I found this strange thing).

Notes:

- SDK 12.0.0 & gcc 4.9 2015q3 under linux (juste Makefile)

- if I change the RAM's start address, the flash address changes (but in the reversed direction, RAM address increase implies Flash address decrease).

- with gcc 5.4.1 (the one shipped with my linux distro), the flash address start is changed, but the problem reappears by changing the RAM

Parents
  • HI marto, 

    Issue 1: The MBR parameter page is required for bootloader and SoftDevice updates, it is used to store progress data when swapping old and new firmware images. The reason for it being one flash page is due to the fact that you only can erase entire pages on the nRF52 family ICs. 

    Issue 2: I dont understand what you mean here: RTT only uses the RAM to buffer data that is to be sent over the SWD interface, not flash. 

    Issue 3: Since the MBR looks up the bootloader start address from the UICR upon start up and jumps to this address on startup( given that a bootloader is present, i.e. the address is written to UICR). Hence, if the new bootloader is larger than the previous one, you need to modify the start address in UICR. However, the UICR registers cannot be modified without erasing them first, so if you get a power failure or similar during this operation( readback, modify the readback values, erase and writting to UICR) you risk bricking your device. 

    It is possible to update the UICR at runtime to allow the update of larger bootloader, but its not failsafe: See https://devzone.nordicsemi.com/f/nordic-q-a/18199/dfu---updating-from-legacy-sdk-v11-0-0-bootloader-to-secure-sdk-v12-x-0-bootloader

    Best regards
    Bjørn 

  • Hello Bjørn,

    Issue 1: I was "complaining" on the compiler (well the linker) that allocates flash storage for my variables in the section reserved for the MBR. I understand that this page should be reserved, but I also understand from your explanation that there is no "problem" with linker putting zeroes in this page.

    Issue 2: yes RTT only uses RAM, but I specified an address in the linker script (well, an address for the section, and in RTT's code (not shown in original post), forced each of my var into a specific section). And the linker does generate three flash sections that corresponds to the size of my 3 variables: this is my main problem; i was expecting that no flash data is generated because they only contains zeroes (since they are uninitialized static globals, hence should be zero-initalized).

    #define FORCE_ADDR(name) __attribute__((section(name)))
    static char FORCE_ADDR(".rtt_ac_up") _acUpBuffer  [BUFFER_SIZE_UP];
    static char FORCE_ADDR(".rtt_ac_down") _acDownBuffer[BUFFER_SIZE_DOWN];
    //
    // Initialize SEGGER Real-time-Terminal control block (CB)
    //
    SEGGER_RTT_CB FORCE_ADDR(".rtt_segger") _SEGGER_RTT;
    
    

    Here is the dump of the end of the .hex (slightly different from the one shown in original post)

    nrf52/bootloader (test) hexinfo.py build/nrf52832_xxaa_s132.hex
    - file: 'build/nrf52832_xxaa_s132.hex'
      entry: 0x70008179
      data:
      - { first: 0x00072000, last: 0x0007DC03, length: 0x0000BC04 }
      - { first: 0x0007ED28, last: 0x0007F127, length: 0x00000400 }
      - { first: 0x0007F528, last: 0x0007F56B, length: 0x00000044 }
      - { first: 0x0007F5A8, last: 0x0007F61F, length: 0x00000078 }
      - { first: 0x10001014, last: 0x1000101B, length: 0x00000008 }
    
    nrf52/bootloader (test) hexxd build/nrf52832_xxaa_s132.hex 
    00072000: 00 f0 00 20 79 81 07 00  a1 81 07 00 a3 81 07 00  .p. y...!...#...
    [...]
    0007dc00: 21 70 07 00                                       !p..
    [...]
    0007ed20:                          00 00 00 00 00 00 00 00          ........
    0007ed30: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ed40: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ed50: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ed60: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ed70: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ed80: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ed90: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007eda0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007edb0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007edc0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007edd0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ede0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007edf0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee00: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee10: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee20: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee30: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee40: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee50: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee60: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee70: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee80: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ee90: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007eea0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007eeb0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007eec0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007eed0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007eee0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007eef0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef00: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef10: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef20: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef30: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef40: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef50: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef60: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef70: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef80: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007ef90: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007efa0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007efb0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007efc0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007efd0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007efe0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007eff0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f000: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f010: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f020: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f030: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f040: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f050: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f060: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f070: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f080: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f090: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f0a0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f0b0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f0c0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f0d0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f0e0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f0f0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f100: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f110: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f120: 00 00 00 00 00 00 00 00                           ........
    0007f520:                          00 00 00 00 00 00 00 00          ........
    0007f530: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f540: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f550: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f560: 00 00 00 00 00 00 00 00  00 00 00 00              ............
    0007f5a0:                          00 00 00 00 00 00 00 00          ........
    0007f5b0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f5c0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f5d0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f5e0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f5f0: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f600: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    0007f610: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
    10001010:             00 20 07 00  00 e0 07 00                  . ...`..
    

    If i remove the FORCE_ADDR() from any of the RTT variable, the corresponding section disapears. Moreover the size exactly match variable sizes:

    - 0x400: _acUpBuffer (1024)

    - 0x044: _acDownBuffer (defined at 64+4 from RTT's conf)

    - 0x78: _SEGGER_RTT (16 + 2*4 + 2 * 6 * 4 + 2 * 6 * 4)

    I think that since I specified a section in the linker script, the linker does not 'consider' those variables to be in .bss, hence will not be zero-erased by the loader code.

    Issue 3: thanks for the explanation; I think I will not try to play with UICR myself :).

    My main problem is issue 2 and the flash generated content with zeroes.

    Thanks,

    Marc.

  • Im trying to set this up with SES, where i set the RTT sections to NOLOAD and see if that works. 

  • Hi Marc,

     you can tell the linker to use the section ram address as the load address, i.e. 

     .rtt 0x20009000: AT(0x20009000)
    {
    PROVIDE(__start_rtt = .);
    KEEP(*(.rtt))
    PROVIDE(__stop_rtt = .);
    } > RAM

    this gets rid of the corresponding section of all zeros in flash. However, this means that the data will not be zero-initialized, but you can memset the section in main to zeros prior to calling the RTT init function. 

    Best regards

    Bjørn

Reply
  • Hi Marc,

     you can tell the linker to use the section ram address as the load address, i.e. 

     .rtt 0x20009000: AT(0x20009000)
    {
    PROVIDE(__start_rtt = .);
    KEEP(*(.rtt))
    PROVIDE(__stop_rtt = .);
    } > RAM

    this gets rid of the corresponding section of all zeros in flash. However, this means that the data will not be zero-initialized, but you can memset the section in main to zeros prior to calling the RTT init function. 

    Best regards

    Bjørn

Children
  • Hi Bjørn, 

    What is the difference between your proposal and simply specifying NOLOAD (that I wanted to avoid) ?

      .rtt_ac_up 0x20004000 (NOLOAD) :
      {
        KEEP(*(.rtt_ac_up))
      } > RAM
    
      .rtt_ac_down 0x20004800 (NOLOAD) :
      {
        KEEP(*(.rtt_ac_down))
      } > RAM
    
      .rtt_segger 0x20004880 (NOLOAD) :
      {
        KEEP(*(.rtt_segger))
      } > RAM
    

    Do you confirm that there is no solution to zero-initialize these variables without embedding zeroes of the size of the variables ?

    Regarding the Segger's part, how does the license play when publishing such diffs:

    diff --git a/xxx/nrf52/lib/nrf-sdk/external/segger_rtt/SEGGER_RTT.c b/xxx/nrf52/lib/nrf-sdk/external/segger_rtt/SEGGER_RTT.c
    index 9d399e8..f4bcf1f 100644
    --- a/xxx/nrf52/lib/nrf-sdk/external/segger_rtt/SEGGER_RTT.c
    +++ b/xxx/nrf52/lib/nrf-sdk/external/segger_rtt/SEGGER_RTT.c
    @@ -945,6 +945,23 @@ int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) {
       return r;
     }
     
    +/*********************************************************************
    +*
    +*       SEGGER_RTT_Reinit
    +*
    +*  Function description
    +*    Reinitializes the RTT Control Block.
    +*
    +*/
    +void SEGGER_RTT_Reinit (void) {
    +  // Clean-up ID since setting only "SEGGER RTT" is not enough
    +  // to be detected by Jlink (at least V630c)
    +  SEGGER_RTT_CB* p;
    +  p = &_SEGGER_RTT;
    +  memset(p->acID, 0x00, sizeof(p->acID));
    +  _DoInit();
    +}
    +
     /*********************************************************************
     *
     *       SEGGER_RTT_Init
    diff --git a/xxx/nrf52/lib/nrf-sdk/external/segger_rtt/SEGGER_RTT.h b/xxx/nrf52/lib/nrf-sdk/external/segger_rtt/SEGGER_RTT.h
    index 4d3a0bb..56da5e4 100644
    --- a/xxx/nrf52/lib/nrf-sdk/external/segger_rtt/SEGGER_RTT.h
    +++ b/xxx/nrf52/lib/nrf-sdk/external/segger_rtt/SEGGER_RTT.h
    @@ -108,6 +108,7 @@ int          SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sNam
     int          SEGGER_RTT_GetKey           (void);
     unsigned     SEGGER_RTT_HasData          (unsigned BufferIndex);
     int          SEGGER_RTT_HasKey           (void);
    +void         SEGGER_RTT_Reinit           (void);^M
     void         SEGGER_RTT_Init             (void);
     unsigned     SEGGER_RTT_Read             (unsigned BufferIndex,       void* pBuffer, unsigned BufferSize);
     unsigned     SEGGER_RTT_ReadNoLock       (unsigned BufferIndex,       void* pData,   unsigned BufferSize);
    

    The RTT license says:

    > Modified versions of this software in source or linkable form *
    > * may not be distributed without prior consent of SEGGER

    Should we contact Segger ?

    Thanks,

    Marc.

  • Hi Marc, you are completely correct that its in essence the same thing as using NOLOAD. So no, I don't see any other solution than using NOLOAD and then using memset to zero the section before running the segger function that inits the RTT control block. 

    I assumed that you would use this for debugging during development only. So if you plan on adding this in the production code, then yes you would need to contact segger. 

  • I contacted Segger that:

    - notified me that they changed the RTT licensing to allow easy redistribution

    - agreed to distribute such code

    Note that I modified the diff above to add the memset().

Related