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

  • 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