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

Startup & data initialisation problems with gcc4.9.3 under eclipse environnement

Hi,

I'm working on nRF52822 device with gcc4.9.3 compiler under eclipse environnement (with gnuarm toolchain plugin).

I have some problems with data initialisation. To check what is wrong I made this simple example:

volatile uint32_t test_data=0x12345678;
volatile uint32_t test_bss = 0;

int main(void) {
	printf("test data %08X\n", (int)test_data);
	test_data = 0;

	printf("test bss %d\n", (int)test_bss);
	test_bss = 1;
}

On the first launch, the console shows:

test data 12345678
test bss 980  

Then I generate a reset to restart my test, the console shows:

test data 00000000
test bss 1

So

a) the "test_data" value is well initialized on the first time, but not on the following ones.

b) the "test_bss" value is never initialized.

Note, my linker options are -T "D:\Eclipse\eclipse64-mars\workbench.arm\nRF52\nRF52_AA.ld" -Xlinker --gc-sections -Wl,-Map,"nRF52.map" --specs=rdimon.specs

I use rdimon library to have the SWO console.

If I try to debug the code, in the statup routine form "gcc_startup_nrf52.s" file, some values (addresses) are not correct.

Reset_Handler:
    ldr r1, =__etext					; <= value correspond to the end of text section
    ldr r2, =__data_start__				; <= value correspond to the start of the RAM (0x20000000)
    ldr r3, =__bss_start__				; !! value = 0x8000 doesn't correspond to the start of bss section !!
...

So the initialization of data is not done here. I guess that it's done inside crt0 routine.

Then to initialize the bss section I've compiled with -D__STARTUP_CLEAR_BSS to be sure the the following code will be added.

#ifdef __STARTUP_CLEAR_BSS
    ldr r1, =__bss_start__				; !! value still set to 0x8000
    ldr r2, =__bss_end__				; !! value = 0x8000 doesn't correspond to the end of bss section !!

    movs r0, 0

    subs r2, r1
    ble .L_loop3_done

.L_loop3:
    subs r2, #4
    str r0, [r1, r2]
    bgt .L_loop3
    
.L_loop3_done:
#endif /* __STARTUP_CLEAR_BSS */	

My linker script is like this

MEMORY
{
  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
  RAM (rwx) :  ORIGIN = 0x20000000, LENGTH = 0x10000
}
...
    .bss :
    {
        . = ALIGN(4);
        __bss_start__ = .;
        *(.bss*)				# bss section content should be located between __bss_start__ and __bss_end__
        *(COMMON)
        . = ALIGN(4);
        __bss_end__ = .;
    } > RAM
...
  1. I don't know why bss_start and bss_end are not set to right values

  2. I don't know why crt routine doesn't initialize correctly the memory

Thanks for reply.

Regards, Thierry

Parents
  • Hi,

    I've copied and updated for nRF52 MCU an old linker script from another project (STM32 MCU). With this linker script, bss and data sections are correct with and without --specs=rdimon.specs.

    The bad linker script I use is provided by nordic (nRF5_SDK_11.0.0_89a8197).

    It's composed by the files :

    the first is located in the example directory <sdk_location>\examples\peripheral\blinky\pca10040\blank\armgcc\blinky_gcc_nrf52.ld and the second is located in the directory <sdk_location>\components\toolchain\nrf5x_common.ld

    I've just made single file including this two files

    I don't know why it's doesn't work !!!

    Below is my linker script:

    /*
    *****************************************************************************
    ** thln linker script updated 21/04/2016 form STM32 project
    *****************************************************************************
    */
    /* GROUP(-lgcc -lc -lnosys) */
    GROUP(-lgcc -lc -lrdimon)
    
    /* Entry Point */
    ENTRY(Reset_Handler)
    
    
    /* Specify the memory areas */
    MEMORY
    {
      FLASH (rx)      : ORIGIN = 0x00000000, LENGTH = 512K
      RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 64K
    }
    
    /* Define output sections */
    SECTIONS
    {
    
      /* The program code and other data goes into FLASH */
      .text :
      {
            KEEP(*(.isr_vector))
    
    		
    		
        *(.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);
    
      	__etext = _sidata;
    	
      /* Initialized data sections goes into RAM, load LMA copy after code */
      .data : 
      {
        . = ALIGN(4);
        _sdata = .;        /* create a global symbol at data start */
    	__data_start__ = _sdata;
        *(.data)           /* .data sections */
        *(.data*)          /* .data* sections */
    
        . = ALIGN(4);
        _edata = .;        /* define a global symbol at data end */
      } >RAM 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;
    	
      } >RAM
    
      
        .heap (COPY):
        {
            __end__ = .;
            PROVIDE(end = .);
            *(.heap*)
            __HeapLimit = .;
        } > RAM
    
        /* .stack_dummy section doesn't contains any symbols. It is only
         * used for linker to calculate size of stack sections, and assign
         * values to stack symbols later */
        .stack_dummy (COPY):
        {
            *(.stack*)
        } > RAM
    
    	/* Highest address of the user mode stack */
        /* Set stack top to end of RAM, and stack limit move down by
         * size of stack_dummy section */
        __StackTop = ORIGIN(RAM) + LENGTH(RAM);
        __StackLimit = __StackTop - SIZEOF(.stack_dummy);
        PROVIDE(__stack = __StackTop);
        
        /* Check if data + heap + stack exceeds RAM limit */
        ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
    	
    
      /* Remove information from the standard libraries */
      /DISCARD/ :
      {
        libc.a ( * )
        libm.a ( * )
        libgcc.a ( * )
      }
    
      .ARM.attributes 0 : { *(.ARM.attributes) }
    }
    
Reply
  • Hi,

    I've copied and updated for nRF52 MCU an old linker script from another project (STM32 MCU). With this linker script, bss and data sections are correct with and without --specs=rdimon.specs.

    The bad linker script I use is provided by nordic (nRF5_SDK_11.0.0_89a8197).

    It's composed by the files :

    the first is located in the example directory <sdk_location>\examples\peripheral\blinky\pca10040\blank\armgcc\blinky_gcc_nrf52.ld and the second is located in the directory <sdk_location>\components\toolchain\nrf5x_common.ld

    I've just made single file including this two files

    I don't know why it's doesn't work !!!

    Below is my linker script:

    /*
    *****************************************************************************
    ** thln linker script updated 21/04/2016 form STM32 project
    *****************************************************************************
    */
    /* GROUP(-lgcc -lc -lnosys) */
    GROUP(-lgcc -lc -lrdimon)
    
    /* Entry Point */
    ENTRY(Reset_Handler)
    
    
    /* Specify the memory areas */
    MEMORY
    {
      FLASH (rx)      : ORIGIN = 0x00000000, LENGTH = 512K
      RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 64K
    }
    
    /* Define output sections */
    SECTIONS
    {
    
      /* The program code and other data goes into FLASH */
      .text :
      {
            KEEP(*(.isr_vector))
    
    		
    		
        *(.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);
    
      	__etext = _sidata;
    	
      /* Initialized data sections goes into RAM, load LMA copy after code */
      .data : 
      {
        . = ALIGN(4);
        _sdata = .;        /* create a global symbol at data start */
    	__data_start__ = _sdata;
        *(.data)           /* .data sections */
        *(.data*)          /* .data* sections */
    
        . = ALIGN(4);
        _edata = .;        /* define a global symbol at data end */
      } >RAM 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;
    	
      } >RAM
    
      
        .heap (COPY):
        {
            __end__ = .;
            PROVIDE(end = .);
            *(.heap*)
            __HeapLimit = .;
        } > RAM
    
        /* .stack_dummy section doesn't contains any symbols. It is only
         * used for linker to calculate size of stack sections, and assign
         * values to stack symbols later */
        .stack_dummy (COPY):
        {
            *(.stack*)
        } > RAM
    
    	/* Highest address of the user mode stack */
        /* Set stack top to end of RAM, and stack limit move down by
         * size of stack_dummy section */
        __StackTop = ORIGIN(RAM) + LENGTH(RAM);
        __StackLimit = __StackTop - SIZEOF(.stack_dummy);
        PROVIDE(__stack = __StackTop);
        
        /* Check if data + heap + stack exceeds RAM limit */
        ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
    	
    
      /* Remove information from the standard libraries */
      /DISCARD/ :
      {
        libc.a ( * )
        libm.a ( * )
        libgcc.a ( * )
      }
    
      .ARM.attributes 0 : { *(.ARM.attributes) }
    }
    
Children
  • Hi,

    Finaly, I found what is wrong in the Nordicsemi linker script. The following part cause wrong values for bss and data section:

    SECTIONS
    {
      .fs_data :
      {
        PROVIDE(__start_fs_data = .);
        KEEP(*(.fs_data))
        PROVIDE(__stop_fs_data = .);
      } > RAM
    } INSERT AFTER .data;
    

    However, even if the fs_data section is empty, this section occurs an bug.

    .fs_data        0x200009ec        0x0
                    0x200009ec                PROVIDE (__start_fs_data, .)
     *(.fs_data)
                    0x200009ec                PROVIDE (__stop_fs_data, .)
    
    .bss            0x200009ec      0x158
                    0x200009ec                . = ALIGN (0x4)
                    0x200009ec                __bss_start__ = .
    			
    

    If you have more explanation, thank to reply.

  • Hi again :),

    By the way, I noticed that if I move fs_data section directly between data and bss sections, It works properly.

    May the statement "INSERT AFTER .data" corrupt the linker output ?

    .data : AT (__etext)
    {
        __data_start__ = .;
        *(vtable)
        *(.data*)
    
        . = ALIGN(4);
        /* preinit data */
        PROVIDE_HIDDEN (__preinit_array_start = .);
        KEEP(*(.preinit_array))
        PROVIDE_HIDDEN (__preinit_array_end = .);
    
        . = ALIGN(4);
        /* init data */
        PROVIDE_HIDDEN (__init_array_start = .);
        KEEP(*(SORT(.init_array.*)))
        KEEP(*(.init_array))
        PROVIDE_HIDDEN (__init_array_end = .);
    
    
        . = ALIGN(4);
        /* finit data */
        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP(*(SORT(.fini_array.*)))
        KEEP(*(.fini_array))
        PROVIDE_HIDDEN (__fini_array_end = .);
    
        KEEP(*(.jcr*))
        . = ALIGN(4);
        /* All data end */
        __data_end__ = .;
    
    } > RAM
    
    	.fs_data :
    	{
    		PROVIDE(__start_fs_data = .);
    		KEEP(*(.fs_data))
    		PROVIDE(__stop_fs_data = .);
    	}> RAM
    	
    .bss :
    {
        . = ALIGN(4);
        __bss_start__ = .;
        *(.bss*)
        *(COMMON)
        . = ALIGN(4);
        __bss_end__ = .;
    } > RAM
    
  • Which version of the SDK is this? There have been numerous issues with the way the GCC linker script was defined for .fs_data. First it was put in a separate file, but you can't have that, now it seems someone has ttried 'INSERT AFTER' but that's not working either. Do you have an old gcc, or a very new gcc?

    I think it would be good to report this on a support case at the 'My Page' so it gets fixed. The new named sections work very easily with Keil and IAR but they're really painful with GCC and a complete nightmare with Crossworks/SEGGER Studio.

    Let me see if I can find the last thread about this and point to this one.

  • I suggest taking this over to the previous thread to discuss there as there was quite a lot of discussion. I'm guessing a combination of the section orderings and the actual .S code is causing issues, the assembler wants a very particular ordering of things. I still don't quite see why that broke originally and put the bss in entirely the wrong place.

Related