why TI starterware examples do not clear correctly BSS segment when compiled using CodeSourcery gcc

StackOverflow https://stackoverflow.com/questions/15085119

  •  11-03-2022
  •  | 
  •  

سؤال

I ran into severe troubles with beaglebone running TI AM3359arm. I'm using code sourcery to compile code. I tried to compile one of the examples, called enet_lwip, which uses lightweight IP (lwip) to provide http server.

The application crashes at certain point. By debugging I have found, that it is this piece of code, which is responsible for it:

unsigned int lwIPInit(LWIP_IF *lwipIf)
{

    struct ip_addr ip_addr;

    struct ip_addr net_mask;

    struct ip_addr gw_addr;

    unsigned int *ipAddrPtr;

    static unsigned int lwipInitFlag = 0;

    unsigned int ifNum;

    unsigned int temp;

    /* do lwip library init only once */
    if(0 == lwipInitFlag)
    {
        lwip_init();
    }

A very funny thing happens to this: one would expect, that lwipInitFlag gets initialized to 0 and hence the function calls lwip_init();

Well, this does not happen even the very first time the lwIPInit function gets called. The reason for this is, that the variable lwipInitFlag is not set to 0.

I would like to know why this is. If such initialization appears in the code, compiler should generate sequence to null it. But probably because it is preceded by static modifier, it leaves it 'as is'. Why?

The lwipInitFlag is in .bss linker section, which points to DDR memory. How can I assure, that such static assignments get initialized?

For the moment I'll hack the code for lwIP to see if this works, but it is just a warning for me, that there might be another statically declared variables somewhere in the libraries, which do not get initialized.

Any hint how to resolve this?


Adding more information to this: after your fruitful hints I think I have even more mess in how it should work. So: It is true, that I do not call/link crt*.o. On the other hand the TI starterware platform contains initialization asm source, which DOES BSS cleanup. It does it between addresses _bss_start and _bss_end.

When looking into linker script, everything looks pretty ordinary:

SECTIONS
{

        . = 0x80000000;
        . = ALIGN(4);
        .startcode     :
        {
               *init.o      (.text)
        }

        . = ALIGN(4);
        .text      :
        {
                *(.text)
        }

        . = ALIGN(4);

        .data :
        {
                *(.data)
        }

        . = ALIGN(4);

        _bss_start = .;
        .bss :
        {
                *(.bss)
        }
        . = ALIGN(4);

        _bss_end = .;

        _stack = 0x87FFFFF8;
}

So _bss_start is address before BSS block and _bss_end is at the end of the block. The trouble is what map the Codesourcery generates.

When looking at the end of BSS in generated map file, I can see this:

 COMMON         0x80088f0c      0x200 ../binary/armv7a/gcc/am335x/system_config/Debug/libsystem_config.a(interrupt.o)
                0x80088f0c                fnRAMVectors
                0x8008910c                . = ALIGN (0x4)
                0x8008910c                _bss_end = .
                0x87fffff8                _stack = 0x87fffff8
LOAD ../binary/armv7a/gcc/am335x/drivers/Debug/libdrivers.a
LOAD ../binary/armv7a/gcc/utils/Debug/libutils.a
LOAD ../binary/armv7a/gcc/am335x/beaglebone/platform/Debug/libplatform.a
LOAD ../binary/armv7a/gcc/am335x/system_config/Debug/libsystem_config.a
LOAD /opt/CodeSourcery/arm-none-eabi/lib//libc.a
LOAD /opt/CodeSourcery/lib/gcc/arm-none-eabi/4.5.2//libgcc.a
LOAD ../binary/armv7a/gcc/am335x/drivers/Debug/libdrivers.a
LOAD ../binary/armv7a/gcc/utils/Debug/libutils.a
LOAD ../binary/armv7a/gcc/am335x/beaglebone/platform/Debug/libplatform.a
LOAD ../binary/armv7a/gcc/am335x/system_config/Debug/libsystem_config.a
LOAD /opt/CodeSourcery/arm-none-eabi/lib//libc.a
LOAD /opt/CodeSourcery/lib/gcc/arm-none-eabi/4.5.2//libgcc.a
OUTPUT(Debug/bbdidt.out elf32-littlearm)

.bss.pageTable  0x8008c000     0x4000
 .bss.pageTable
                0x8008c000     0x4000 Debug/enetLwip.o

.bss.ram        0x80090000        0x4
 .bss.ram       0x80090000        0x4 Debug/lwiplib.o

There is clearly 'something'. There is another BSS section after the _bss_end, which contains a lot of stuff which is expected to be zeroed, but it is not zeroed, because zeroing finishes at address given by _bss_end.

The probable reason why this is done like this is, that the pageTable is statically declared and required to have 16kiB boundary address:

static volatile unsigned int pageTable[4*1024] __attribute__((aligned(16*1024)));

So as there is a gap between last linker declared BSS segment and pageTable, it places the _bss_end in the middle of the bss segment.

Now the question is, how to tell to linker (I'm using for this arm-none-eabi-ld) that _bss_end should be really at the end of BSS and not somewhere in the middle?

Many thanks

هل كانت مفيدة؟

المحلول 2

thanks for all these comments. It was for me almost a detective work. At the end I have changed the linker script to get something like this:

SECTIONS
{

        . = 0x80000000;
        . = ALIGN(4);
        .startcode     :
        {
               *init.o      (.text)
        }

        . = ALIGN(4);
        .text      :
        {
                *(.text)
        }

        . = ALIGN(4);

        .data :
        {
                *(.data)
        }

        . = ALIGN(4);

        _bss_start = .;
        .bss :
        {
                *(.bss)
                *(COMMON)
                *(.bss.*)
        }
        . = ALIGN(4);

        _bss_end = .;

        _stack = 0x87FFFFF8;
}

So I basically forced linker to include into BSS segment all the sub-segments which start with COMMON and .bss..

This apparently resolves the issue as the linker now generates correct map such, that it places _bss_end pointer really to the last address of BSS section.

So my soft now runs correctly, gets PHY running. I still cannot acquire the DHCP, but I guess this is a problem of uninitialised .data segment. LwIP uses at some places static assignments as

static u32_t xid = 0xABCD0000;

which is going into .data segment, but apparently it does not get initialised and hence I cannot get any DHCP anwer... but this is another story

thanks to all

نصائح أخرى

The fact that no statics are initialised makes me wonder: how have you come by your startup code? This code is required to perform the initialisations.

See http://doc.ironwoodlabs.com/arm-arm-none-eabi/html/getting-started/sec-cs3-startup.html - section 5.2.3 which says:


The C startup function is declared as follows:

void __cs3_start_c (void) __attribute__ ((noreturn));

This function performs the following steps:

  • Initialize all .data-like sections by copying their contents. For example, ROM-profile linker scripts use this mechanism to initialize writable data in RAM from the read-only data program image.
  • ... etc

It sounds like you might be lacking that code.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top