cancel
Showing results for 
Search instead for 
Did you mean: 

How to get last address loaded, or size, from .ld file?

DHase.1
Associate III

A live CAN loader resides in the first 0x8000 in a STM32L431RB. I want to do a CRC check on the application that loads, following the loader, e.g. 0x08008000. The goal is for the loader to run a CRC check upon reset and jump to the app if the CRC is OK. To run a CRC check requires obtaining the application size. (The expected CRC can be placed following the application but also requires knowing the size.)

The approach I've tried is to place a ".word" ahead of the ResetHandler in the startup .s file which would allow the loader to locate the address via the start address at 0x08005004. How can set the .ld linker script be modified to store the size?

If I assign that ".word" with '_sidata' from the ld script, I get a size that is 120 bytes shorter than the .bin file, or last byte of the .srec file. I haven't figured out just what those additional bytes are use for, however I would expect they are there for a purpose.

Is there a place in .ld script where a label could be inserted that has the full size of the binary?

    .section	.text.Reset_Handler
	.weak	Reset_Handler
	.type	Reset_Handler, %function
	.word _sidata
Reset_Handler:
  ldr   sp, =_estack    /* Set stack pointer */

4 REPLIES 4
  .word  _limit_flash
  .word  _limit_flash - g_pfnVectors /*  Size, Front to Back */
...

/*
*****************************************************************************
**
 
**  File        : LinkerScript.ld
**
**  Abstract    : Linker script for STM32H743XIHx Device with
**                2048KByte FLASH, 128KByte RAM
**
**                Set heap size, stack size and stack location according
**                to application requirements.
**
**                Set memory bank area and size if external memory is used.
**
**  Target      : STMicroelectronics STM32
**
** Determine Length - sourcer32@gmail.com
**
*****************************************************************************
*/
 
/* Entry Point */
ENTRY(Reset_Handler)
 
/* Highest address of the user mode stack */
_estack = 0x20020000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */
 
/* Specify the memory areas */
MEMORY
{
DTCMRAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
RAM_D1 (xrw)      : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw)      : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw)      : ORIGIN = 0x38000000, LENGTH = 64K
ITCMRAM (xrw)      : ORIGIN = 0x00000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
}
 
/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH
 
  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
 
    KEEP (*(.init))
    KEEP (*(.fini))
 
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH
 
  /* Constant data goes into FLASH */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH
 
  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH
 
  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH
 
  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);
 
  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
 
    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >DTCMRAM AT> FLASH
 
 
  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)
 
    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >DTCMRAM
 
  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >DTCMRAM
 
 
  /* End section */
  . = ALIGN(4);
 
 .endof :
 {
   /* This is used by the startup in order to find the end */
   _limit_flash = .;   /* define a global symbol at the end of flash */
 } >FLASH
 
 
  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
 
  .ARM.attributes 0 : { *(.ARM.attributes) }

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Clive provided you the answer above, I just add this:

> If I assign that ".word" with '_sidata' from the ld script, I get a size that is 120 bytes shorter than the .bin file, or last byte of the .srec file.

> I haven't figured out just what those additional bytes are use for, however I would expect they are there for a purpose.

Those are the data to initialize your explicitly initialized variables, see startup code.

For better understanding of how linker allocates sections, look into the .map file.

JW

Thanks. I had not thought of adding a section. I was trying to find places to insert at "_label = .;" with no success.

Thanks for the additional thought. The following generates the end address (+1), but I'm not sure it would be correct in all cases when additional sections are defined.

addr = _sidata + (_sdata - _sdata);

Regarding additional sections, I have a fuzzy recollection from many years ago that there is sometimes a section for table generated for addresses to handlers for things such as divide by zero. .extab? (This may have been in the HC11/HCS12 days). The above formula wouldn't work if there are additional sections.

In the .map file, the end address (+1) does show up several places, .e.g. where is 0x08005fa0 is the address sought. The section .jcr is not in the .ld file.

.jcr            0x20000078        0x0 load address 0x08005fa0.

I think .jcr is a section having to do with java constructors that would be added to the .ld file. Hardly applicable in this case.