Running your AVR processor at 20 MHz? millis not quite right? This may help.
The changes are based on the Arduino 0022 Core. This is the original code...
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;
SIGNAL(TIMER0_OVF_vect)
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
unsigned char f = timer0_fract;
m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}
timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;
return m;
}
The changes are highlighted...
#if (F_CPU == 16000000L) || (F_CPU == 8000000L)
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))// the whole number of milliseconds per timer0 overflow
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)// the fractional number of milliseconds per timer0 overflow. we shift right
// by three to fit these numbers into a byte. (for the clock speeds we care
// about - 8 and 16 MHz - this doesn't lose precision.)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)typedef uint8_t timer0_fract_t;
#elif (F_CPU == 20000000L)
#define MILLIS_INC (0)
#define FRACT_INC (512)
#define FRACT_MAX (625)
typedef uint16_t timer0_fract_t;
#endifvolatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static timer0_fract_t timer0_fract = 0;SIGNAL(TIMER0_OVF_vect)
{
// copy these to local variables so they can be stored in registers
// (volatile variables must be read from memory on every access)
unsigned long m = timer0_millis;
timer0_fract_t f = timer0_fract;/* rmv: The code below generates considerably less code (emtpy Sketch is 440 versus 418)...
m += MILLIS_INC;
f += FRACT_INC;
if (f >= FRACT_MAX) {
f -= FRACT_MAX;
m += 1;
}
...rmv */f += FRACT_INC;
if (f >= FRACT_MAX)
{
f -= FRACT_MAX;
m = m + MILLIS_INC + 1;
}
else
{
#if MILLIS_INC != (0)
m += MILLIS_INC;
#endif
}timer0_fract = f;
timer0_millis = m;
timer0_overflow_count++;
}
micros, delay, delayMicroseconds will not work correctly at 20 MHz. This change only corrects millis.
At the time of this post, the code is completely untested.
Questions? Does the code work for you?