Reply by Fausto Marzoli November 5, 20072007-11-05
Alle 14:42, luned5 novembre 2007, rtstofer ha scritto:

> That you have floating point operating is great but, if you have time,
> you should explore the differences in the files and find out EXACTLY
> where the problem occurred. It will probably lead to a greater
> understanding of the requirements of crt.s and the operation of 'ld'.

I agree: I'm going to do it!

Thank you, for now.

--
Fausto Marzoli - 8052.it - http://www.8052.it/

An Engineer's Guide to the LPC2100 Series

Reply by Fausto Marzoli November 5, 20072007-11-05
Alle 18:26, marted30 ottobre 2007, rtstofer ha scritto:

> HOWEVER, the library still works for:
> pow(9.3, 3.3) = 1570.340134
> And, yes, it agrees with my calculator.
[...]
> There is a MUCH higher probability of a user problem.

And you are right!

It was a problem in my code. I've not yet exactly understood where the problem
was, but I can do math floating point operations now on ARM7 NXP LPC2106
microcontroller!

Thank you all very much for your help.

The problem must have been in the .ld linker file or in the crt0.s file,
because I tried using the boot.s and .ld files from the John Wren's LPC2148
demo code as you suggested, and it works!
--
Fausto Marzoli - 8052.it - http://www.8052.it/
Reply by rtstofer October 31, 20072007-10-31
--- In l..., Fausto Marzoli wrote:
>
> Hi all!
>
> I have a problem that I can't fix with GNU ARM Toolchain and math
functions.
> Maybe someone has experimented floating point math function with GNU
ARM
> Toolchain and can help me...
>
> This is the problem: when using floating point arguments, some math
functions
> cause a program crash with "data abort" or "undefined instruction".
>
> I've done some tests with the newlib math functions with float
arguments, GNU
> arm toolchain and ARM7 NXP LPC2106 microcontroller:
> log works
> log10 works
> sqrt works
> tan Error (uncorrect result)
> cos Crash
> sin Crash
> pow Crash
>
> I've tried a lot of pre-compiled toolchains: YAGARTO, Ronetix,
CodeSourcery...
> I also compiled myself the toolchain (under linux): I tried a lot of
> different compiling options, always with the same results.
>
> I can't fix it. My test program is a simple test program that blinks
a led on
> a development board and in the led delay functions makes a dummy
math call
> (only to test the math call speed).
>
> If someone is interested in this argument, I can give you all the
info about
> compiling options or any other information you need.
>
> Anyone tried floating point math with GNU ARM Toolchain (arm-elf)
and newlib?
> Thank you,
>
> Fausto
>

Back on Oct 2d, there was a thread re: ARM7TDMI-S Conditional MOV
instruction not working. It was tossed back and forth because nobody
could believe that after millions of chips were sold and placed in
service that there could possibly be an error in the synthesis.

And there wasn't! It turned out to be a problem with a Segger J-Link
driver. Nothing at all to do with the ARM hardware.

I'm not saying that newlib works but, considering how many ports are
out there and how many developers are using it, I would be hesitant to
say there is a problem.

There are some fundamental floating point operations: add, subtract,
multiply and divide. From there, the other functions are built by
using various series expansions or other well known algorithms. They
all rely on the four fundamental operations to varying degrees. All
of the high level operations are written in C - how hard can it be to
verify the code?

My guess: stack problem. Or some other unrelated issue such as nested
interrupt routines.

A test program should take about 10 lines of code (not counting crt.s)
and it really couldn't be that hard to debug. So write a 10 line
program, bundle it up with crt.s, the makefile and linker script and
post it in the files section. Then everybody can hack away at it and
try to find the problem.

Something really simple:

#include
#include

float result;

int main(void)
{
result = sin(0.523598333);
printf("sin(30) = %f\n", result);
}

Compiled under Linux with:

cc -lm test.c -o test

and executed results in

sin(30) = 0.500000
The thing is, I just added

#include

and

printf("sin(30) = %f\n",sin(0.523598333));

to main.c of John Wren's EXCELLENT LPC2148 demo code (just ahead of
the task setup) and added -lm to the link flags and voila' The 2148
prints:

sin(30) = 0.500000

So, I am having a problem being convinced that there is a problem with
newlib.

Richard
Reply by Fausto Marzoli October 31, 20072007-10-31
Alle 21:10, luned29 ottobre 2007, aaajbell ha scritto:

> Another problem I had with my LPC2103 was with the interrupt routines.
> I had to use the ISR_ENTRY and ISR_EXIT macros found by researching
> messages in this forum to get the return statement in an interrupt
> routine to work properly. Are you by chance using interrupts for your
> blink program?

Not in this case. I've tried also a FREErtos port and in that case there was
interrupts, too. But the interrupts seems to work.

Now I'm testing a very simple program that only calls one math function.

In this moment I'm compiling the last CVS newlib and gcc 4.2.2: I want to test
the last available code in order to see if there is some difference.

--
Fausto Marzoli - 8052.it - http://www.8052.it/
Reply by Leon Heller October 30, 20072007-10-30
--- In l..., Fausto Marzoli wrote:
>
> Hi all!
>
> I have a problem that I can't fix with GNU ARM Toolchain and math
functions.
> Maybe someone has experimented floating point math function with
GNU ARM
> Toolchain and can help me...
>
> This is the problem: when using floating point arguments, some math
functions
> cause a program crash with "data abort" or "undefined instruction".
>
> I've done some tests with the newlib math functions with float
arguments, GNU
> arm toolchain and ARM7 NXP LPC2106 microcontroller:
> log works
> log10 works
> sqrt works
> tan Error (uncorrect result)
> cos Crash
> sin Crash
> pow Crash
>
> I've tried a lot of pre-compiled toolchains: YAGARTO, Ronetix,
CodeSourcery...
> I also compiled myself the toolchain (under linux): I tried a lot
of
> different compiling options, always with the same results.
>
> I can't fix it. My test program is a simple test program that
blinks a led on
> a development board and in the led delay functions makes a dummy
math call
> (only to test the math call speed).
>
> If someone is interested in this argument, I can give you all the
info about
> compiling options or any other information you need.
>
> Anyone tried floating point math with GNU ARM Toolchain (arm-elf)
and newlib?

They work OK with CrossWorks, which uses gcc.

Leon
Reply by Fausto Marzoli October 30, 20072007-10-30
Alle 17:55, marted30 ottobre 2007, rtstofer ha scritto:

> You need to look at the ANSI standard definition for pow(x,y) because
> y MUST be an integer and x must be positive.
> http://www.thinkage.ca/english/gcos/expl/c/lib/pow.html

No, this is not correct. I looked with attenction at the code in "The Standard
C Library" by P.J. Plauger before trying the math pow() operation when I
started testing its speed execution.

What the ANSI standard says is: in pow(x,y) if "x" is non-positive AND "y" is
not an integer, "pow" return -HUGE_VAL and sets "errno".

"AND", not "OR".

Only when both the conditions (x < 0) and (y not integer) are true, the
function returns an error. pow(9.2, 3.3) should work.

Why accept a floating point double y argument, if the y argument has to be
integer?

Moreover, I tried compiling the following code in linux with GCC in order to
test the corrispondence of the pow() function with the exp(y*log) function,
and it works:
-------------
int main(void)
{
double x = 10.2, y = 0.2;

do {
printf("%f\n", pow(x, y));
printf("%f\n", exp(y*log(x)));
y++;
} while(y < 11.0);

return 0;
}
-------------

I also tried the pow() function with IAR compiler for ARM, and it works. So
it's not an ANSI standard problem. It's a problem of my code, or of my
compiling/linking options, or of the library, or of the compiler.

Does your hardware executes pow(9.2, 3.3) correctly?
> I really don't think your problem has anything to do with the library.
> I always use a mental test when I come up against this kind of thing.
> What is the probability that I am the only one to discover this
> 'bug'? Even if it is a bug, someone will have already discovered it
> and found a way around. I will never be the first...

This is not always true... I agree in most cases, but if it was so easy there
would be no bugs in the world...
Anyway, I'm not saying that there is a bug in the library: I'm just trying to
understand why my code doesn't work.
--
Fausto Marzoli - 8052.it - http://www.8052.it/
Reply by rtstofer October 30, 20072007-10-30
--- In l..., "Paul Curtis" wrote:
>
> Richard,
>
> > You need to look at the ANSI standard definition for pow(x,y) because
> > y MUST be an integer and x must be positive.
> > http://www.thinkage.ca/english/gcos/expl/c/lib/pow.html
>
> No, that's complete nonsense, sorry. ;-) Your reference does not
say that!
> It says that *if* x is negative or zero then y cannot be other than an
> integer. It does not constrain y for x>0.
>

Yup, you're right! Sloppy reading on my part.

HOWEVER, the library still works for:

pow(9.3, 3.3) = 1570.340134

And, yes, it agrees with my calculator.

There might be a finite probability of an error in the library but we
aren't even close to boundary conditions.

The library does work, it does get the right answer and it doesn't
crash - in my simple tests. Obviously, I have neither the time,
talent or interest to prove it works for ALL cases. But, for simple
examples, it works fine. The code has been around a very long time
and the algorithms even longer.

There is a MUCH higher probability of a user problem.

Richard
Reply by Paul Curtis October 30, 20072007-10-30
Richard,

> You need to look at the ANSI standard definition for pow(x,y) because
> y MUST be an integer and x must be positive.
> http://www.thinkage.ca/english/gcos/expl/c/lib/pow.html

No, that's complete nonsense, sorry. ;-) Your reference does not say that!
It says that *if* x is negative or zero then y cannot be other than an
integer. It does not constrain y for x>0.

> Or look at the code in "The Standard C Library" by P.J. Plauger along
> with his description of the function.
>
> The real prototype for pow() is:
>
> double pow (double x, double y);
>
> This, again, from the hardware:
>
> pow(9.3, 3.0) = 804.357000

Try pow(9.3, 3.3) and pow(9.9, -3). This should give your calculator and
the library a small workout. It's quite possible to compute these values.

> I really don't think your problem has anything to do with the library.

Actually, that may *not* be true. There are indeed special cases for
dealing with discontinuities, branch cuts, and so on, typically values < and
>= 1 by using different approximations.

Whilst in all probability it is user error, there is a small but finite
chance it is not.

--
Paul Curtis, Rowley Associates Ltd http://www.rowley.co.uk
CrossWorks for ARM, MSP430, AVR, MAXQ, and now Cortex-M3 processors
Reply by rtstofer October 30, 20072007-10-30
> pow() works correctly also for me when using integer arguments, even
if you
> treat them as float. I mean, pow(9.0, 3.0) works but pow(9.2, 3.3)
does NOT
> work (in my tests). I found out that newlib math library calls
different
> procedures with a "wrapper" function depending on the arguments.

You need to look at the ANSI standard definition for pow(x,y) because
y MUST be an integer and x must be positive.
http://www.thinkage.ca/english/gcos/expl/c/lib/pow.html

Or look at the code in "The Standard C Library" by P.J. Plauger along
with his description of the function.

The real prototype for pow() is:

double pow (double x, double y);

This, again, from the hardware:

pow(9.3, 3.0) = 804.357000

and it agrees with my calculator.

I really don't think your problem has anything to do with the library.
I always use a mental test when I come up against this kind of thing.
What is the probability that I am the only one to discover this
'bug'? Even if it is a bug, someone will have already discovered it
and found a way around. I will never be the first...

Of course the library uses 'wrappers'. Why calculate cos(x) when it
is exactly sin((pi/2) - x)? So the cos() and sin() functions call the
same underlying sine() function (I forgot the exact function name)
with a flag to indicate whether to compute sin() or cos().

Richard
Reply by Fausto Marzoli October 30, 20072007-10-30
Alle 15:24, marted30 ottobre 2007, rtstofer ha scritto:

> I don't have a simulator, the test was done on real hardware. Even if
> I did have a simulator, I wouldn't trust it.

Perfect. So do I.
> I tried pow(9.0, 3.0) and this is the result:
>
> pow(9.0, 3.0) = 729.000000

Thank you for your attenction to me and my problem.

pow() works correctly also for me when using integer arguments, even if you
treat them as float. I mean, pow(9.0, 3.0) works but pow(9.2, 3.3) does NOT
work (in my tests). I found out that newlib math library calls different
procedures with a "wrapper" function depending on the arguments.
> Changes to main.c of demo code:
>
> #include <-- existing include
> #include <-- added this line
> ...
> ...
> memset (taskHandles, 0, sizeof (taskHandles)); <-- existing code
>
> printf("sin(30) = %f\n",sin(0.523598333)); <-- added this line
> printf("pow(9.0, 3.0) = %f\n",pow(9.0, 3.0)); <-- added this line
>
> Changes to Makefile:
>
> export LINKER_FLAGS=-lm $(COMMON)/common.a -Xlinker -olpc2148.elf
> -Xlinker -M -Xlinker -Map=lpc2148.map <-- added -lm to start of flag

Very good. Thank you very much. I'll try to adapt the code to my LPC2106
hardware and try it.
Or I will buy the same Olimex hardware for LPC2148, if necessary.
If it works, my problem is in the linker .ld file or in the startup code.

Thank you again. I will report on this group my test results.
Fausto

--
Fausto Marzoli - 8052.it - http://www.8052.it/