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
init.o
? Do you have the source?init.o
is traditionally responsible for clearingBSS
and setting up the stack. The fact you can debug anything indicates that you have some startup code. Also, how is it started? Does this get burned to flash so a reset vector jumps to the first part of the binary or are you loading via a boot loader? The boot loader could be setting up stack, etc. – artless noise