Skip to content

Commit ea4c450

Browse files
authored
Merge pull request #441 from gatk555/timer
Fix TOV/ICR handling, SEI delay - updated version
2 parents d2aaebd + b653a13 commit ea4c450

File tree

3 files changed

+45
-26
lines changed

3 files changed

+45
-26
lines changed

simavr/sim/avr_timer.c

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -745,26 +745,25 @@ avr_timer_write_pending(
745745
void * param)
746746
{
747747
avr_timer_t * p = (avr_timer_t *)param;
748-
// save old bits values
749-
uint8_t ov = avr_regbit_get(avr, p->overflow.raised);
750-
uint8_t ic = avr_regbit_get(avr, p->icr.raised);
751-
uint8_t cp[AVR_TIMER_COMP_COUNT];
752-
753-
for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++)
754-
cp[compi] = avr_regbit_get(avr, p->comp[compi].interrupt.raised);
755-
756-
// write the value
757-
// avr_core_watch_write(avr, addr, v); // This raises flags instead of clearing it.
758-
759-
// clear any interrupts & flags
760-
if (avr_regbit_from_value(avr, p->overflow.raised, v))
761-
avr_clear_interrupt_if(avr, &p->overflow, ov);
762-
if (avr_regbit_from_value(avr, p->icr.raised, v))
763-
avr_clear_interrupt_if(avr, &p->icr, ic);
764-
765-
for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++)
766-
if (avr_regbit_from_value(avr, p->comp[compi].interrupt.raised, v))
767-
avr_clear_interrupt_if(avr, &p->comp[compi].interrupt, cp[compi]);
748+
749+
// All bits in this register are assumed to be write-1-to-clear.
750+
751+
if (addr == p->overflow.raised.reg &&
752+
avr_regbit_from_value(avr, p->overflow.raised, v)) {
753+
avr_clear_interrupt(avr, &p->overflow);
754+
}
755+
if (addr == p->icr.raised.reg &&
756+
avr_regbit_from_value(avr, p->icr.raised, v)) {
757+
avr_clear_interrupt(avr, &p->icr);
758+
}
759+
760+
for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) {
761+
if (addr == p->comp[compi].interrupt.raised.reg &&
762+
avr_regbit_from_value(avr, p->comp[compi].interrupt.raised,
763+
v)) {
764+
avr_clear_interrupt(avr, &p->comp[compi].interrupt);
765+
}
766+
}
768767
}
769768

770769
static void

simavr/sim/sim_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ static inline void avr_sreg_set(avr_t * avr, uint8_t flag, uint8_t ival)
113113
if (flag == S_I) {
114114
if (ival) {
115115
if (!avr->sreg[S_I])
116-
avr->interrupt_state = -2;
116+
avr->interrupt_state = -1;
117117
} else
118118
avr->interrupt_state = 0;
119119
}

tests/atmega48_enabled_timer.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
#include "avr_mcu_section.h"
1515
AVR_MCU(F_CPU, "atmega48");
1616

17+
volatile uint8_t count;
18+
1719
ISR(TIMER0_COMPA_vect)
1820
{
21+
++count;
1922
}
2023

2124
int main(void)
@@ -27,13 +30,30 @@ int main(void)
2730

2831
TCCR0B |= (1 << CS00) | (1 << CS01); // Start timer: clk/64
2932

33+
while ((TIFR0 & (1 << OCF0A)) == 0)
34+
;
35+
36+
// Now interrupt is pending. Try and clear it.
37+
38+
TIFR0 = 0;
39+
if (TIFR0 & (1 << OCF0A))
40+
++count; // Should not clear
41+
TIFR0 = (1 << OCF0A);
42+
if ((TIFR0 & (1 << OCF0A)) == 0)
43+
++count; // Should clear!
44+
3045
sei(); // Enable global interrupts
3146

32-
// here the interupts are enabled, but the interupt
33-
// vector should not be called
34-
sleep_mode();
47+
// Let it run to next interrupt.
3548

36-
// this should not be reached
37-
cli();
3849
sleep_mode();
50+
TIMSK0 = 0; // Disable CTC interrupt
51+
52+
if (count == 3) // Expected
53+
cli();
54+
55+
// Time out if interrupting or count wrong.
56+
57+
for (;;)
58+
sleep_mode();
3959
}

0 commit comments

Comments
 (0)