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
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