Hello,
To make a long story short I have switched from the Yagarto package with
arm-elf (old, but good, Olimex GCCFD) to a fairly recent version using
arm-none-eabi (updating the IDE based on the Yagarto homepage this time
--- many thanks to Michael Fischer for putting it all together!).
When I compile my project I get the following error message (quite a few
object files removed from the link line for clarity):
arm-none-eabi-ld -v -Lc:\Programs\Yagarto\lib\gcc\arm-none-eabi\4.6.2
-Lc:\Programs\Yagarto\arm-none-eabi\lib -L. -Map main.map
-T2138_demo.cmd -o main.out crt.o main.o adcAD7686.o timer.o
UARTStdIO.o --start-group -lm -lg -lgcc -lc --end-group
GNU ld (GNU Binutils) 2.21
c:\Programs\Yagarto\arm-none-eabi\lib\libg.a(lib_a-sbrkr.o): In function
`_sbrk_r':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\newlib\libc\reent/..
/../../../../newlib-1.19.0/newlib/libc/reent/sbrkr.c:60: undefined
reference to `_sbrk'
make: *** [main.out] Error 1
**** Build Finished ****
It seems like there is a reference to the function _sbrk. Apparently
some function is calling this that I'm unaware of. Looking on the net,
it seems like _sbrk is a very hardware dependent function, but I can't
find any library (newlib?) for my LPC2138 and I'm not experienced enough
to write it myself. I tried making a simple stub and making a super
simple libnewlib.a only including this stub. Turns out the linking works
out, but the controller hangs...
The same line based on arm-elf works and can run the code so my guess is
that I - for some reason - need the newlib and the _sbrk function. Or
rather, using arm-none-eabi I use some function that makes a call to
_sbrk.
Any suggestions for the following would be highly appreciated:
1. Is there any way to find out what function actually is calling _sbrk?
When stepping through the controller code, it hangs when returning from
a function call so it's not obvious there.
2. Where can I find information about the difference between elf and
none-eabi (what is it? - OK, consider me newbie)?
3. Can anyone suggest a working newlib (with _sbrk) for the LPC2138? The
Yagarto that I have states newlib 1.19, but when I look through the
package, I only find a newlib.h file?
Many thanks in advance!
Regards,
Staffan
Hello,
Many thanks. I find a _sbrk_r, but no _sbrk? The stub I created earlier
looks like this (was actually based on a _sbrk_r from Aeolus
Development):
void * _sbrk(
struct _reent *_s_r,
ptrdiff_t nbytes)
{
char *base; /* errno should be set to ENOMEM on error */
if (!heap_ptr){ /* Initialize if first time through. */
heap_ptr = end;
}
base = heap_ptr; /* Point to end of heap. */
heap_ptr += nbytes; /* Increase heap. */
return base; /* Return pointer to start of new heap area. */
}
It didn't work out so well.
The syscalls.c file, does it go into newlib? Is there any place to look
for a makefile where libnewlib is generated. I'm not very familiar with
these things so any hints are highly appreciated. Also, if there are any
suggestions as to how one can figure out what functions a given lib-file
provides (and even better, from what files it's been compiled!), that
would be great! In my (very small) experience, one includes header files
with certain names, but is then expected to link with libraries having
different names --- is one supposed to have divine inspiration somewhere
or is there a method to find out what libraries that are to be used?
Regards,
Staffan
Staffan B. wrote:> Hello,>> Many thanks. I find a _sbrk_r, but no _sbrk?
_sbrk_r should be defined in the libc (newlib). It calls _sbrk which
needs to be defined by the user. In the newlib's documentation (
http://sourceware.org/newlib/libc.html ) this example is given:
1
caddr_tsbrk(intincr){
2
externchar_end;/* Defined by the linker */
3
staticchar*heap_end;
4
char*prev_heap_end;
5
6
if(heap_end==0){
7
heap_end=&_end;
8
}
9
prev_heap_end=heap_end;
10
if(heap_end+incr>stack_ptr){
11
write(1,"Heap and stack collision\n",25);
12
abort();
13
}
14
15
heap_end+=incr;
16
return(caddr_t)prev_heap_end;
17
}
>The stub I created earlier> looks like this (was actually based on a _sbrk_r from Aeolus> Development):>> void * _sbrk(> struct _reent *_s_r,> ptrdiff_t nbytes)> ...
This is the interface for an reentrant function with the name of the
stub-function.
> It didn't work out so well.
Hmm, so it did work somehow? More information needed here.
> The syscalls.c file, does it go into newlib?
It usually just "go" into your project. Compile the file and link the
generated object-code with the other object code. Just as i.e. main.c or
uart.c or ...
> Is there any place to look> for a makefile where libnewlib is generated. I'm not very familiar with> these things so any hints are highly appreciated. Also, if there are any> suggestions as to how one can figure out what functions a given lib-file> provides (and even better, from what files it's been compiled!), that> would be great!
You may read the GNU binutils documentation, esp. on the tools nm and
objdump.
> In my (very small) experience, one includes header files> with certain names, but is then expected to link with libraries having> different names --- is one supposed to have divine inspiration somewhere> or is there a method to find out what libraries that are to be used?
I don't think this is related to the problem. Here a function (_sbrk_r)
of the libc (newlib) expects a support function (_sbrk). There is no
need for an extra library, just define the system-calls as functions
with the interfaces given in the newlib-documentation.
Hope this helps,
Martin
Hello,
Thanks for all the links!
I have tried a couple of ways of including the _sbrk.c. Should have
realized that the copy of _sbrk_r wouldn't work as a stub for _sbrk...
The compiling part naturally worked, but when I later downloaded the
code and tried to get it running, it just hung. Debugging didn't give
much of insight since I just ended up in an UNDEF after leaving a
function call (that itself seemed to have worked well).
I have also tried the code snippet you suggested, but it misses the
definition of stack_ptr and I couldn't find a clear match.
My latest attempt has been to use the syscalls.c from the file
LPC2138_Test_IIC.zip. I have attached it as a file here.
It seems to perhaps be providing what I'm looking for, but it has some
oddities that my compiler can't handle.
Example:
=====
int
isatty (int fd)
{
return 1;
fd = fd;
}
=====
Several of these "var = var" exist in the code and it seems to be
preventing compilation. Any clues why this is done and what to do to get
by?
Regards,
Staffan
"it seems to be preventing" should result in a clear arror message from
the compiler. If not, there is no problem.
As "var = var" is prefectly valid C-Code, there should be no error. I
guess, that this line has been put there to prevent an "unused argument"
warning, but as is is placed after the return, there could be an
"unreachabel code" warning instead.
Anyhow, read the error messages, this will help you to splve any
problems.
Oliver
Hello,
You're right. I compile using Eclipse (Indigo) and in the "Problems"
tab, I get error messages like:
Description Resource Path Location Type
Assignment to itself 'm = m' syscalls.c /test1/LPC2138_Test_IIC line
457 Code Analysis Problem
This is apparently not an error, but why does Eclipse consider it to be
so?
Anyways, with this known, I managed to get the file compiled (other
stupid mistakes made the linker missing the file - the object file ended
up in the wrong directory).
The code can now be linked (syscalls.o at the absolute end of the set of
files --- started out at the beginning before crt.o, not a good idea)
without errors and I can download the code to the eval board.
However, I still get the same error as before. Being a little bit more
observant, I notice that the error occurring is a Prefetch Abort
(instruction fetch memory fault, interrupt vector mem location 0xc in
LPC2138). When running the debugger, I consistently get the same result
and I've tried on two different eval boards so I guess there is
something strange in the code.
What I also notice is that the debugger 'looses track'. The calling
hierarchy is shown (starting with main() on top, showing the different
functions that are part in the 'calling tree' to get the the current
code. After a while, when returning from a function call, the top level
(starting with main()) 'disappears' and fairly quickly (not so many
levels), the top level is changed from known location to somewhere way
off in memory (0x1880e7f8 - there is no code whatsoever there) and when
returning to this 'calling function', I get a PAbt interrupt - perhaps
not so strange. When being in the function just below this strange
location, I continuously get warnings like the following for each line
of code that is executed:
Warn : memory read caused data abort (address: 0x1880e7f8, size: 0x4,
count: 0x1)
I have tried to set a breakpoint in the sbrk function, but it seems for
some reason that breakpoints are disabled so there is no easy way to
figure out who has been calling.
I'm rather clueless as to what to do except that I guess it still in
some way is related to the syscalls/sbrk. Any clues would be highly
appreciated!
Regards,
Staffan
The check for stack-heap-collision can be removed from the newlib
example. Sorry, should have removed it after copy/paste to avoid
confusion.
Check the value for the start-of-heap in the map-file. The symbol used
in the newlib-example is _end. So check your linker-script if _end is
defined there and check the value in the map-file. Maybe another label
is used (end has been shown in a previous post, may also be called __end
or _end__ or __heap_start_) Just make sure the used label is hold the
correct value for start-of-heap. Maybe the name has been used elsewhere
in the code. Esp. if "provide" is used in the linker-script the linker
will not complain about a missing symbol but will also not set the
correct value. Show your linker-script and the map-file if you need more
support.
Also check that there are several kBytes of RAM "free" for the heap.
Malloc may request heap-space in portions of 4 kBytes depending on the
configuration of the newlib (4KiB is default IRC).
It's difficult to help without further information. Maybe the heap just
overwrites data/bss and/or one of the stacks, maybe it's an alignment
problem, maybe not enough free RAM.
Side-notes:
- With a correct linker-script the order of object-file-names given to
the linker should not matter. It's only important that the
exception-table is assigned ot the correct location. A good approach is
an extra section for the table (using .section and ASM) and to force
this section to the address where the core looks for it by using the
section-name of in the linker script (with KEEP when using
unused-code-removal).
- I have often used expressions like var=var; to avoid unused variable
warnings from the compiler. But it seems that the method now causes the
Eclipse and/or newer gcc (can't remember which) to give an
self-assign-warning. Replacing var=var; by (void)var; should solve this.
Hello,
Clearly, I get more information than I almost can handle --- many many
thanks for taking your time with this!
Not sure I actually do the what you suggest, but anyways:
I took a look at my linker script (attached as 2138_demo.cmd) and it
seems to only be providing _end. Actually, when reviewing it, it seems
like there has been issues with sbrk also in arm-elf (I've added a note
at least, long ago...).
Looking in main.map (not attached since it is 187kB), it looks like
this:
...
.bss 0x40004d0c 0x0
c:\Programs\Yagarto\lib\gcc\arm-none-eabi\4.6.2\libgcc.a(_arm_fixsfsi.o)
.bss 0x40004d0c 0x0
c:\Programs\Yagarto\lib\gcc\arm-none-eabi\4.6.2\libgcc.a(_arm_fixunssfsi
.o)
COMMON 0x40004d0c 0x100
c:\Programs\Yagarto\arm-none-eabi\lib\libg.a(lib_a-gdtoa-gethex.o)
0x40004d0c __hexdig
COMMON 0x40004e0c 0x4
c:\Programs\Yagarto\arm-none-eabi\lib\libg.a(lib_a-reent.o)
0x40004e0c errno
0x40004e10 . = ALIGN (0x4)
0x40004e10 _bss_end = .
0x40004e10 _end = .
0x40004e10 PROVIDE (end, .)
LOAD crt.o
LOAD main.o
LOAD adcAD7686.o
...
Hmm, RAM could definitely be an issue I think. I have 32k available, but
probably consume quite a bit of that (one reason for choosing the
LPC2138 was the amount of flash and RAM). According to the spec, ram
will be in the address space 0x4000 0000 - 0x4000 7fff. According to the
part from main.map above, _end occurrs at 0x4000 4e10 --- does it mean
there is space from 4e10 to 7fff free? In that case, there should be
sufficient amount?
Just changed the var=var to (void) var and now there are no complaints
there, thanks! Strange that eclipse should complain... Changing the
preferences could perhaps be better since the code in itself is correct
(thanks Oliver) - now I know why it's there though.
---OOPS, just noticed one thing. At the very end of linker script
2138_demo.cmd, there is the line
PROVIDE ( end = . );
Should this be PROVIDE ( _end = .); (with underscore)?
You mention that PROVIDE may turn off some checking?
You pretty much lost me with the comments at the end on the linker
script. If there is a sample file I can look at, that would be great (my
script apparently was sensitive to what order the makefile listed the
object files...)
Again, many thanks for all comments and help!
Regards,
Staffan
Hello,
Just tried changing the last line of 2138_demo.cmd to
PROVIDE ( _end = . );
(with underscore), but it didn't change anything. Same kind of error
still.
Regards,
Staffan