[Top][All Lists]
[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."
Re: [avr-gcc-list] Avr-libc Floating Point Problem,
Paulo Marques <=