EmbDev.net

Forum: ARM programming with GCC/GNU tools WINARM and ARM9 runtime problem


von Mike J. (mjubes)


Rate this post
useful
not useful
I have a test program which runs perfectly OK with an ARM7 device (NXP 
LPC2138), but not with an ARM9 device (EP9302).

With ARM9 the program crashes -only- when some library functions are 
called (marked (NO) below) It runs perfectly OK with others.

This sounds to me like some kind of library problem, but being rather 
unfamiliar with GCC (I am more of an IAR person) I wouldn't know where 
to start looking

Any ideas??  Thanks in advance


Lines that work/ don't work:

 a=atoi("20");    // yes

 p = malloc(100); // no

 sprintf(z,"hello");  // yes

 sprintf(z,"hello %d ",a);  // no

 puts("hello");       // no

 printf("hello");     // no





The programs were tested with an IAR compiler and both versions work.

"Cstartup.s" in both cases is set to leave the ARM in SYS mode (I have 
also tried SVC) with interrupts disabled and plenty of stack space 
allocated for all modes.

I have modified _write_r() in syscall.c to include output to the serial 
port, In the ARM9 version the program never gets to this point. It's OK 
with the ARM7 version

For the ARM9 project, I have tried various mods to the makefile i.e. 
-mcpu=arm920 =arm9 etc to no effect.

I am using the latest WINARM 20060606 downloaded just a few days ago 
(Dec 2009)
using arm-elf-gcc (GCC) 4.1.1 (WinARM)

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Mike Jubes wrote:
> I have a test program which runs perfectly OK with an ARM7 device (NXP
> LPC2138), but not with an ARM9 device (EP9302).
>
> With ARM9 the program crashes -only- when some library functions are
> called (marked (NO) below) It runs perfectly OK with others.

Please take a close look into the generated assembly file and/or the 
disassembly. The compiler might have already optimized "away" some 
function-calls and replaced them with direct assignments during 
compile-time for the functions marked "yes".

> This sounds to me like some kind of library problem, but being rather
> unfamiliar with GCC (I am more of an IAR person) I wouldn't know where
> to start looking
>
> Any ideas??  Thanks in advance
>
>
> Lines that work/ don't work:
>
>  a=atoi("20");    // yes
>
>  p = malloc(100); // no
>
>  sprintf(z,"hello");  // yes
>
>  sprintf(z,"hello %d ",a);  // no
>
>  puts("hello");       // no
>
>  printf("hello");     // no
>
> The programs were tested with an IAR compiler and both versions work.

How did you find out "yes"?

At least linker-configuration are very different and startup-code needes 
to be adapted for the GNU assembler.

> "Cstartup.s" in both cases is set to leave the ARM in SYS mode (I have
> also tried SVC) with interrupts disabled and plenty of stack space
> allocated for all modes.

For the libc-functions mentioned above the heap handling and must be 
working. Did you verify that the "end" or "_end" symbol defined by the 
linker and used by sbrk holds the address of the beginning of some free 
RAM memory not used be data/bss/stack.

> I have modified _write_r() in syscall.c to include output to the serial
> port, In the ARM9 version the program never gets to this point.

Did you check if a direct call to _write_r for your user-code sends a 
character to the uart? Double-check if the addresses (start/end) for 
data and bss are in RAM. I don't know the target-controller but for some 
controllers RAM must be enabled esp. if it's external RAM. If you have a 
debugger/JTAG-connection check if .data-copy, .bss zero-init and 
stack-setup work as expected.

> It's OK
> with the ARM7 version
>
> For the ARM9 project, I have tried various mods to the makefile i.e.
> -mcpu=arm920 =arm9 etc to no effect.
> I am using the latest WINARM 20060606 downloaded just a few days ago
> (Dec 2009)
> using arm-elf-gcc (GCC) 4.1.1 (WinARM)

I suggest to use a more up-to-date binary-package. The tools in my 
WinARM 6/06 are a little old. Codesourcery G++ lite, Yagarto and 
DevkitARM include newer versions of the GNU toolchain.

von Mike J. (mjubes)


Rate this post
useful
not useful
Thanks for your quick reply, here are my comments:

>Please take a close look into the generated assembly file and/or the
>disassembly. The compiler might have already optimized "away" some
>function-calls and replaced them with direct assignments during
>compile-time for the functions marked "yes".

I have looked at the .lss file ouput and followed the flow after 
malloc() or printf() are called.

For example Malloc calls through: malloc, malloc_r, __malloc_lock, 
_sbrk_r, __malloc_unlock


Printf calls through printf_r, vfprintf, vfprintf_r, localeconv, 
__sinit,_swsetup, fflush, and a few others,

The .LSS output is a bit spartan and a bit tedious to follow, so I 
didn't follow every bit, but noticed all calls are standard looking 
branches, with the code actually present and nearby, i.e. nothing 
untowards from just looking at the code first sight.

BTW: Optimisation is set to zero and the compiler is set to ARM mode 
only (or I think it is)



>How did you find out "yes"?

I placed traps in between those lines. By traps I mean a simple macro 
that sends a

byte to the serial output port, YOu can see how far the program gets 
before it stops altogether (or decides to reset and start all over 
again)



>At least linker-configuration are very different and startup-code needes
>to be adapted for the GNU assembler.
Thanks. I am aware of this. I have tested stack sizes and contents using 
my own functions and they are all OK. BTW both ARM7 and ARM9 versions 
work OK using my program which uses lots of my own calls, which include 
interrupts and is over 64K long. Problems only arise when I include some 
of the GCC library functions (and only on the ARM9 version)



>For the libc-functions mentioned above the heap handling and must be
>working. Did you verify that the "end" or "_end" symbol defined by the
>linker and used by sbrk holds the address of the beginning of some free
>RAM memory not used be data/bss/stack.

This is what the symbol table shows:  I also printed the value of _end 
in real time via the UART. (which showed the same)

00100000 D _data    Beginning of RAM
.....        My variables in between here
00103158 B fpga_phook    Last of my variables
0010315c A _bss_end_
00107200 A _end
00107200 B _stack
00107200 A end


This is the corresponding entry on the linker file

MEMORY
{
  ROM (rx) : ORIGIN = 0x00080000, LENGTH = 128k  /* program code loads 
here */
  RAM (rw) : ORIGIN = 0x00100000, LENGTH = 512k  /* program RAM starts 
here */
}



>Did you check if a direct call to _write_r for your user-code sends a
>character to the uart?
Yes it does. The same format is used in the ARM7 version which works OK.


>Double-check if the addresses (start/end) for
>data and bss are in RAM. I don't know the target-controller but for some
>controllers RAM must be enabled esp. if it's external RAM. If you have a
>debugger/JTAG-connection check if .data-copy, .bss zero-init and
>stack-setup work as expected.

Yes, double checked with the symbol table, all variables within the 
range.



>I suggest to use a more up-to-date binary-package. The tools in my
>WinARM 6/06 are a little old. Codesourcery G++ lite, Yagarto and
>DevkitARM include newer versions of the GNU toolchain.

I am not that versed in GCC to be able to generate these tools without a 
step by step idiot's guide. However I have downloaded the latest WinArm 
version 20080331, I shall try that.

von Clifford S. (clifford)


Rate this post
useful
not useful
ARM9 generally requires more complex C runtime start up that ARM7 to 
initialise the MMU, caches, and PLL.  Moreover ARM9 boards often use 
external SDRAM; if this is the case the SDRAM controller must be 
configured correctly before any code or data in external memory are 
accessed - it will certainly crash otherwise, since it will read junk 
from the memory.

von Mike J. (mjubes)


Rate this post
useful
not useful
Thanks, I am fully aware of this issue (we have been using this CPU chip 
for quite a long time) All relevant MMU, PLL setups etc are implemented 
in the startup module and work OK. So all memory partitions: cached, 
buffered etc are initialised for the project needs before main() is 
called. The program also works perfectly OK when compiled using the IAR 
IDE.

Playing with the GCC linker script file I have managed to get the 
program to work of sorts. It crashes on fewer functions by simply 
allowing plenty of memory space between the various data, bss and stack 
sections. So this is an area which we have to read the manual in more 
detail.

von Clifford S. (clifford)


Rate this post
useful
not useful
Looking at your list of functions that fail, I would note two things;

1) Stdio formatted I/O functions require a relatively large amount of 
stack space.  In my experience, around 4K minimum is required for all 
threads that use formatted I/O + plus whatever the thread needs for its 
own purposess.

2) malloc requires a correct implementation of _sbrk/_sbrk_r.  That is 
to say not only must it return a valid address, but it must not 'grow' 
the stack into any other memory regions such as the stack.  I doubt that 
the ARM7 memory map is identical to the ARM9, and your last comment 
would seem to indicate a memory map/allocation issue.  I suggest that 
you place a break-point in sbrk, or somehow log all sbrk requests, to 
see what addresses it providing and check them against the linker 
generated map to see that they are not encroaching on other entities and 
that the address is valid.


Clifford

von Mike J. (mjubes)


Rate this post
useful
not useful
Thanks for all that!


>stdio, around 4k minimum

With IAR I am using the "small" stdio model, which uses a lot less 
memory!


>sbrk

I had a trap at sbrk, but during my tests, the program never got that 
far!!


I finally managed to stop the program from crashing by allocating very 
large chunks of RAM to the data and stack sections in the linker 
description file.

I figure this is where the problem lies. So I have been spending time 
studying the linker file format and its peculiar language. There must be 
something causing an overlap there.

Haven't got very far with all the Christmas celebrations though. ):-)

von Clifford S. (clifford)


Rate this post
useful
not useful
Mike Jubes wrote:

>>sbrk
>
> I had a trap at sbrk, but during my tests, the program never got that
> far!!
>
I would expect sbrk to be invoked when dynamic memory allocation first 
occurs.

von Mike J. (mjubes)


Rate this post
useful
not useful
>I would expect sbrk to be invoked when dynamic memory allocation first
>occurs.

Interesting.

When I followed the binary code in the .lss file the sbrk calls were way 
down, after a few others. Admittedly, I didn't bother to check the paths 
very thoroughly.

Thanks very much for your other comments anyway, as they triggered me 
looking more deeply into the linker file.

von Clifford S. (clifford)


Rate this post
useful
not useful
Mike Jubes wrote:

> When I followed the binary code in the .lss file the sbrk calls were way
> down, after a few others.

I did not say that sbrk() was called first, but that it was called when 
malloc() was first called; which is entirely different.  It is called 
whenever the heap manager needs to extend the heap, which must happen at 
least once on first allocation.

I too suspect that this is (at least in part) a linker script issue.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.