avr-gcc-list
[Top][All Lists]

## Re: [avr-gcc-list] Avr-libc Floating Point Problem

 From: Paulo Marques Subject: Re: [avr-gcc-list] Avr-libc Floating Point Problem Date: Mon, 17 Jan 2011 20:29:13 +0000 User-agent: Thunderbird 2.0.0.23 (X11/20090817)

```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

> 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[10];
> uint8_t sio_buf[64];
>
>[...]
>
> ////////////////////////////////////////////////////////
> // 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."

```