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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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
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[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."



reply via email to

[Prev in Thread] Current Thread [Next in Thread]