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)
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.
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.
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.
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.
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
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. ):-)
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.
>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.
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
Log in with Google account
No account? Register here.