Electronics & Programming

develissimo

Open Source electronics development and programming

  • You are not logged in.
  • Root
  • » AVR-GCC
  • » [avr-gcc-list] Avr-libc Floating Point Problem [RSS Feed]

#1 Jan. 14, 2011 22:30:52

Thomas D.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[avr-gcc-list] Avr-libc Floating Point Problem


I am attempting to compare the uM-FPU and avr-libc floating point times.
I think I am missing something, but, what?

See the code at the bottom.

The code is compiled with:
avr-gcc -Os -mmcu=atmega128 -c -o main.o main.c
avr-gcc -Os -mmcu=atmega128 main.o -o main.elf -lc
avr-objcopy --only-section .text --only-section .data \
--output-target=ihex main.elf main.hex

The output on the sio is:

AVR Floating Point Tests
AVR Floating Point Tests
ssprintf ? 58
Fporta ? 6
Fmul ? 18
Fadd ? 16
Fdiv ? 0
Fsin ? 0
Llint -235875775 0

All the floating point numbers are converted to '?' It appears the
floating point conversion is not done???

If I link with
avr-gcc -Os -mmcu=atmega128 main.o -o main.elf \
-L/usr/lib/avr/lib/avr51 -lc -lm
I get the same code, looking at the output of avr-objdump. It appears
that avr-gcc either uses the intrinsic code or always uses libm.a.
Which?

What am I doing wrong?

tomdean

=== Code =============================================================

// main.c - part of atmega float test
//
// 20110113 tomdean - initial version
// This code is GPL
//
// $Id$

////////////////////////////////////////////////////////
// includes
#include <avr/io.h> // port definitions
#include <math.h> // math functions
#include <string.h> // string functions
#include <avr/interrupt.h> // interrupt
#include <stdio.h> // sprintf
// need two defines before setbaud
#define F_CPU 16000000L
#define BAUD 38400
#include <util/setbaud.h>

////////////////////////////////////////////////////////
// defines
#define TRACE_PORT PORTB
#define TRACE_DDR DDRB
#define TRACE_ON(n) TRACE_PORT |= _BV((n))
#define TRACE_OFF(n) TRACE_PORT &= ~_BV((n))

////////////////////////////////////////////////////////
// globals
uint16_t ovfl;
uint16_t tcnt;
uint16_t tmp;
uint16_t start, delta;
uint8_t sio_buf;

////////////////////////////////////////////////////////
// serial init
void serial_init() {
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
UCSR0B = _BV(RXEN0) | _BV(TXEN0);
// UCSR0C = _BV(USBS) | _BV(UCSZ1) | _BV(UCSZ0);
return;
}

////////////////////////////////////////////////////////
// counter1 init
void counter1_init() {
TCCR1B = _BV(CS11); // clk/8 = 1/2 usec ticks
TIMSK |= _BV(TOIE1); // counter1 overflow interrupt
return;
}


////////////////////////////////////////////////////////
// counter 1 ISR
ISR(SIG_OVERFLOW1) {
ovfl++;
}

////////////////////////////////////////////////////////
// usec - return the number of usec since we started.
uint32_t usec() {
tcnt = TCNT1;
tmp = ovfl;
return (uint32_t)tcnt + (uint32_t)65536*(uint32_t)tmp;
}

/////////////////////////////////////////////////////////////
// serial_recv
uint8_t serial_recv() {
while (!(UCSR0A & _BV(RXC0)));
/* return the char */
return UDR0;
}

/////////////////////////////////////////////////////////////
// serial_send
void serial_send(uint8_t c) {
while (!(UCSR0A & _BV(UDRE0)));
/* send the char */
UDR0 = c;
return;
}

/////////////////////////////////////////////////////////////
// serial_print
void serial_print(uint8_t *msg) {
while (*msg != 0)
serial_send (*msg++);
return;
}

////////////////////////////////////////////////////////
// initialize
void initialize(void) {
TRACE_DDR = 0xff; // all output
serial_init();
counter1_init();
}

////////////////////////////////////////////////////////
// main
int main() {
float pi, fmul, fadd, fdiv, fsin;
float ftcnt1;
long long ltcnt1, ltcnt2, llint;
char ch;

initialize();
ch = serial_recv();
serial_print("AVR Floating Point Tests\n");

while(1) {
ch = serial_recv();
serial_print("AVR Floating Point Tests\n");
// Start
TRACE_PORT ^= _BV(0);
//
TRACE_ON(1);
start = usec();
ftcnt1 = (float)TCNT1; // sort of like a random number
delta = usec() - start;
TRACE_OFF(1);

TRACE_ON(2);
start = usec();
sprintf(sio_buf,"%f",M_PI);
delta = usec() - start;
TRACE_OFF(2);

TRACE_ON(3);
start = usec();
fmul = ftcnt1 * M_PI;
delta = usec() - start;
TRACE_OFF(3);

TRACE_ON(4);
start = usec();
fadd = fmul + ftcnt1;
delta = usec() - start;
TRACE_OFF(4);

TRACE_ON(5);
start = usec();
fdiv = fmul/fadd;
delta = usec() - start;
TRACE_OFF(5);

TRACE_ON(6);
start = usec();
fsin = sin(fadd);
delta = usec() - start;
TRACE_OFF(6);

ltcnt1 = (long long)TCNT1;
ltcnt2 = (long long)TCNT1;
TRACE_OFF(7);
start = usec();
llint = ltcnt1 * ltcnt2;
delta = usec() - start;
TRACE_OFF(7);

serial_print("sprintf ");
serial_print(sio_buf);
sprintf(sio_buf," %d\n",delta);
serial_print(sio_buf);

sprintf(sio_buf,"Ftcnt1 %f %d\n",ftcnt1, delta);
serial_print(sio_buf);

sprintf(sio_buf,"Fmul %f %d\n",fmul,delta);
serial_print(sio_buf);

sprintf(sio_buf,"Fadd %f %d\n",fadd, delta);
serial_print(sio_buf);

sprintf(sio_buf,"Fdiv %f %d\n",fdiv,delta);
serial_print(sio_buf);

sprintf(sio_buf,"Fsin %f %d\n",fsin,delta);
serial_print(sio_buf);

sprintf(sio_buf,"Llint %ld %d\n",llint,delta);
serial_print(sio_buf);

// reset the clock
ovfl = 0;

}
// never get here ...
return 0;
}



_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.orghttp://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Offline

#2 Jan. 14, 2011 22:52:40

Oleksandr R.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[avr-gcc-list] Avr-libc Floating Point Problem


2011/1/15 Thomas D. Dean <tomd***@*peakeasy.org>:

By default, "standard" (without floating point formats support) print
formatter version is linked.
Add switches for "full" formatter linking

> avr-gcc -Os   -mmcu=atmega128 main.o -o main.elf \
>   -L/usr/lib/avr/lib/avr51 -lc -lm \
-Wl,-u,vfprintf -lprintf_flt


--
wbr,
ReAl

_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.orghttp://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Offline

#3 Jan. 14, 2011 22:54:27

Marcelo P.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[avr-gcc-list] Avr-libc Floating Point Problem


It seems to me that you are missing the printf_flt. Try adding:

LDFLAGS+=-lm -Wl,-u,vfprintf -lprintf_flt

Since the avr are so tiny on rom and ram the developers made a version
without float support
to reduce resources usage when possible.

Best Marcelo.

2011/1/14 Thomas D. Dean <tomd***@*peakeasy.org>

> I am attempting to compare the uM-FPU and avr-libc floating point times.
> I think I am missing something, but, what?
>
> See the code at the bottom.
>
> The code is compiled with:
> avr-gcc -Os -mmcu=atmega128 -c -o main.o main.c
> avr-gcc -Os -mmcu=atmega128 main.o -o main.elf -lc
> avr-objcopy --only-section .text --only-section .data \
> --output-target=ihex main.elf main.hex
>
> The output on the sio is:
>
> AVR Floating Point Tests
> AVR Floating Point Tests
> ssprintf ? 58
> Fporta ? 6
> Fmul ? 18
> Fadd ? 16
> Fdiv ? 0
> Fsin ? 0
> Llint -235875775 0
>
> All the floating point numbers are converted to '?' It appears the
> floating point conversion is not done???
>
> If I link with
> avr-gcc -Os -mmcu=atmega128 main.o -o main.elf \
> -L/usr/lib/avr/lib/avr51 -lc -lm
> I get the same code, looking at the output of avr-objdump. It appears
> that avr-gcc either uses the intrinsic code or always uses libm.a.
> Which?
>
> What am I doing wrong?
>
> tomdean
>
> === Code =============================================================
>
> // main.c - part of atmega float test
> //
> // 20110113 tomdean - initial version
> // This code is GPL
> //
> // $Id$
>
> ////////////////////////////////////////////////////////
> // includes
> #include <avr/io.h> // port definitions
> #include <math.h> // math functions
> #include <string.h> // string functions
> #include <avr/interrupt.h> // interrupt
> #include <stdio.h> // sprintf
> // need two defines before setbaud
> #define F_CPU 16000000L
> #define BAUD 38400
> #include <util/setbaud.h>
>
> ////////////////////////////////////////////////////////
> // defines
> #define TRACE_PORT PORTB
> #define TRACE_DDR DDRB
> #define TRACE_ON(n) TRACE_PORT |= _BV((n))
> #define TRACE_OFF(n) TRACE_PORT &= ~_BV((n))
>
> ////////////////////////////////////////////////////////
> // globals
> uint16_t ovfl;
> uint16_t tcnt;
> uint16_t tmp;
> uint16_t start, delta;
> uint8_t sio_buf;
>
> ////////////////////////////////////////////////////////
> // serial init
> void serial_init() {
> UBRR0H = UBRRH_VALUE;
> UBRR0L = UBRRL_VALUE;
> UCSR0B = _BV(RXEN0) | _BV(TXEN0);
> // UCSR0C = _BV(USBS) | _BV(UCSZ1) | _BV(UCSZ0);
> return;
> }
>
> ////////////////////////////////////////////////////////
> // counter1 init
> void counter1_init() {
> TCCR1B = _BV(CS11); // clk/8 = 1/2 usec ticks
> TIMSK |= _BV(TOIE1); // counter1 overflow interrupt
> return;
> }
>
>
> ////////////////////////////////////////////////////////
> // counter 1 ISR
> ISR(SIG_OVERFLOW1) {
> ovfl++;
> }
>
> ////////////////////////////////////////////////////////
> // usec - return the number of usec since we started.
> uint32_t usec() {
> tcnt = TCNT1;
> tmp = ovfl;
> return (uint32_t)tcnt + (uint32_t)65536*(uint32_t)tmp;
> }
>
> /////////////////////////////////////////////////////////////
> // serial_recv
> uint8_t serial_recv() {
> while (!(UCSR0A & _BV(RXC0)));
> /* return the char */
> return UDR0;
> }
>
> /////////////////////////////////////////////////////////////
> // serial_send
> void serial_send(uint8_t c) {
> while (!(UCSR0A & _BV(UDRE0)));
> /* send the char */
> UDR0 = c;
> return;
> }
>
> /////////////////////////////////////////////////////////////
> // serial_print
> void serial_print(uint8_t *msg) {
> while (*msg != 0)
> serial_send (*msg++);
> return;
> }
>
> ////////////////////////////////////////////////////////
> // initialize
> void initialize(void) {
> TRACE_DDR = 0xff; // all output
> serial_init();
> counter1_init();
> }
>
> ////////////////////////////////////////////////////////
> // main
> int main() {
> float pi, fmul, fadd, fdiv, fsin;
> float ftcnt1;
> long long ltcnt1, ltcnt2, llint;
> char ch;
>
> initialize();
> ch = serial_recv();
> serial_print("AVR Floating Point Tests\n");
>
> while(1) {
> ch = serial_recv();
> serial_print("AVR Floating Point Tests\n");
> // Start
> TRACE_PORT ^= _BV(0);
> //
> TRACE_ON(1);
> start = usec();
> ftcnt1 = (float)TCNT1; // sort of like a random number
> delta = usec() - start;
> TRACE_OFF(1);
>
> TRACE_ON(2);
> start = usec();
> sprintf(sio_buf,"%f",M_PI);
> delta = usec() - start;
> TRACE_OFF(2);
>
> TRACE_ON(3);
> start = usec();
> fmul = ftcnt1 * M_PI;
> delta = usec() - start;
> TRACE_OFF(3);
>
> TRACE_ON(4);
> start = usec();
> fadd = fmul + ftcnt1;
> delta = usec() - start;
> TRACE_OFF(4);
>
> TRACE_ON(5);
> start = usec();
> fdiv = fmul/fadd;
> delta = usec() - start;
> TRACE_OFF(5);
>
> TRACE_ON(6);
> start = usec();
> fsin = sin(fadd);
> delta = usec() - start;
> TRACE_OFF(6);
>
> ltcnt1 = (long long)TCNT1;
> ltcnt2 = (long long)TCNT1;
> TRACE_OFF(7);
> start = usec();
> llint = ltcnt1 * ltcnt2;
> delta = usec() - start;
> TRACE_OFF(7);
>
> serial_print("sprintf ");
> serial_print(sio_buf);
> sprintf(sio_buf," %d\n",delta);
> serial_print(sio_buf);
>
> sprintf(sio_buf,"Ftcnt1 %f %d\n",ftcnt1, delta);
> serial_print(sio_buf);
>
> sprintf(sio_buf,"Fmul %f %d\n",fmul,delta);
> serial_print(sio_buf);
>
> sprintf(sio_buf,"Fadd %f %d\n",fadd, delta);
> serial_print(sio_buf);
>
> sprintf(sio_buf,"Fdiv %f %d\n",fdiv,delta);
> serial_print(sio_buf);
>
> sprintf(sio_buf,"Fsin %f %d\n",fsin,delta);
> serial_print(sio_buf);
>
> sprintf(sio_buf,"Llint %ld %d\n",llint,delta);
> serial_print(sio_buf);
>
> // reset the clock
> ovfl = 0;
>
> }
> // never get here ...
> return 0;
> }
>
>
>
> _______________________________________________
> AVR-GCC-list mailing list
> AVR-GCC-l***@*ongnu.org
>http://lists.nongnu.org/mailman/listinfo/avr-gcc-list>



--
s,
Marcelo_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.orghttp://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Offline

#4 Jan. 14, 2011 22:57:08

Thomas D.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[avr-gcc-list] Avr-libc Floating Point Problem


On Fri, 2011-01-14 at 20:44 -0200, Marcelo Politzer wrote:
> It seems to me that you are missing the printf_flt. Try adding:
>
>
> LDFLAGS+=-lm -Wl,-u,vfprintf -lprintf_flt
>
>
> Since the avr are so tiny on rom and ram the developers made a version
> without float support
> to reduce resources usage when possible.

Thanks, I knew I was missing something.

I always try to avoid using floating point. But, I need some trig ans
poly calculations.

tomdean



_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.orghttp://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Offline

#5 Jan. 14, 2011 23:33:47

Thomas D.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[avr-gcc-list] Avr-libc Floating Point Problem


On Fri, 2011-01-14 at 20:44 -0200, Marcelo Politzer wrote:

That fixed my problem I have some surprises in the results.

Scope Timer1 What
4.3us 3.5us Convert tcnt1 to float
156us 154us sprintf M_PI
10us 8.5us float mult
8.5us 7.0us float add
1.5us 0us float div - sometimes shows 0.5us
1.5us 0us float sin - sometimes shows 0.5us
2.3us 0us long long mult
2.3us 2us atan2 <-- for testing replaced long long mult
in the posted code

I do not understand the timer1 values for the last 3.

The results mostly agree with scilab 5.3.

Now, to hook up the uM-FPU and repeat the tests.

tomdean


_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.orghttp://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Offline

#6 Jan. 15, 2011 00:40:48

Thomas D.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[avr-gcc-list] Avr-libc Floating Point Problem


On Fri, 2011-01-14 at 15:33 -0800, Thomas D. Dean wrote:
I fixed my code and, now see

func value time(usec)
sprintf 3.141593 154.250000
Ftcnt1 21740.000000 3.312500
Fmul 68298.227000 10.187500
Fadd 90038.227000 7.875000
Fdiv 0.758547 30.250000
Fsin 0.180126 121.500000
Llint 4015 2.002692 < value cast to uint32_t
Fatan 0.648949 169.687500

This seems reasonable...

Now, on to the uM-FPU. I will post those results, if anyone is
interested.

tomdean


_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.orghttp://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Offline

#7 Jan. 15, 2011 01:14:04

Weddington, E.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[avr-gcc-list] Avr-libc Floating Point Problem


> -----Original Message-----
> From: avr-gcc-list-bounces+eric.weddington=atmel.***@*ongnu.org
> On
> Behalf Of Thomas D. Dean
> Sent: Friday, January 14, 2011 5:37 PM
> To: avr-gcc-l***@*ongnu.org
> Subject: Re: Avr-libc Floating Point Problem
>
>
> Now, on to the uM-FPU. I will post those results, if anyone is
> interested.

Yes, please do. :-)

Eric

_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.orghttp://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Offline

#8 Jan. 17, 2011 00:04:56

Dmitry K.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[avr-gcc-list] Avr-libc Floating Point Problem


In addition, there is the benchmark table in avr-libc doc.

Regards,
Dmitry.


_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.orghttp://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Offline

#9 Jan. 17, 2011 20:29:43

Paulo M.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[avr-gcc-list] Avr-libc Floating Point Problem


Thomas D. Dean wrote:
>
> What am I doing wrong?

I didn't have time to read all the thread, but there are a few things I
would like to point out, in case they help you somehow.

> tomdean
>
> === Code =============================================================
>
> // main.c - part of atmega float test
> //
> // 20110113 tomdean - initial version
> // This code is GPL
> //
> // $Id$
>
> ////////////////////////////////////////////////////////
> // includes
> #include <avr/io.h> // port definitions
> #include <math.h> // math functions
> #include <string.h> // string functions
> #include <avr/interrupt.h> // interrupt
> #include <stdio.h> // sprintf
> // need two defines before setbaud
> #define F_CPU 16000000L
> #define BAUD 38400
> #include <util/setbaud.h>
>
> ////////////////////////////////////////////////////////
> // defines
> #define TRACE_PORT PORTB
> #define TRACE_DDR DDRB
> #define TRACE_ON(n) TRACE_PORT |= _BV((n))
> #define TRACE_OFF(n) TRACE_PORT &= ~_BV((n))
>
> ////////////////////////////////////////////////////////
> // globals
> uint16_t ovfl;

This "ovfl" variable needs to be:

volatile uint16_t ovfl;

> uint16_t tcnt;
> uint16_t tmp;
> uint16_t start, delta;
> uint8_t sio_buf;
>
>
>
> ////////////////////////////////////////////////////////
> // counter 1 ISR
> ISR(SIG_OVERFLOW1) {
> ovfl++;
> }
>
> ////////////////////////////////////////////////////////
> // usec - return the number of usec since we started.
> uint32_t usec() {
> tcnt = TCNT1;
> tmp = ovfl;
> return (uint32_t)tcnt + (uint32_t)65536*(uint32_t)tmp;
> }

This "usec()" function is not interrupt safe.

If you read the TCNT1 value and it overflows before you read the ovfl
variable, the two values will be inconsistent.

A simple solution for that is to do:

uint32_t usec() {
uint32_t tmp1, tmp2;

do {
tmp1 = ovfl;
tcnt = TCNT1;
tmp2 = ovfl;
} while (tmp1 != tmp2);

return (uint32_t)tcnt + (uint32_t)65536*(uint32_t)tmp1;
}

This might had an occasional small jitter but it makes sure that the
timer sample is in the correct "overflow slot".

For really clock-accurate measurements of avr code execution it is
easier to just use the avrtest simulator and its timer functions ;)

--
Paulo Marques
Software Development Department - Grupo PIE, S.A.
Phone: +351 252 290600, Fax: +351 252 290601
Web: www.grupopie.com

"All generalizations are false."

_______________________________________________
AVR-GCC-list mailing list
AVR-GCC-list@nongnu.orghttp://lists.nongnu.org/mailman/listinfo/avr-gcc-list

Offline

  • Root
  • » AVR-GCC
  • » [avr-gcc-list] Avr-libc Floating Point Problem [RSS Feed]

Board footer

Moderator control

Enjoy the 21st of August
PoweredBy

The Forums are managed by develissimo stuff members, if you find any issues or misplaced content please help us to fix it. Thank you! Tell us via Contact Options
Leave a Message
Welcome to Develissimo Live Support