From: Jakob Gruber <jakob.gruber@gmail.com> Date: Thu, 23 Aug 2012 08:57:21 +0000 (+0200) Subject: timer: Avoid infinite cycle timer on TCNT write X-Git-Tag: v1.0~14 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=27bab459856ad7e06c5c9801722628e77a03e33c;p=sx%2Fsimavr.git timer: Avoid infinite cycle timer on TCNT write In some situations, it was possible to enter an infinite cycle timer loop. In avr_timer_tcnt_write, the tov cycle timer registration is not protected and can register a timer with p->tov_cycles == 0. The following atmega1280 program demonstrates this issue: int main() { TCCR1A = 0; TCCR1B = (1<<WGM12) | (1<<ICES1); OCR1B = OCR1A = 960; /* Start */ TCNT1 = 0; TCCR1B |= (1<<CS11); /* Stop */ TCCR1B &= ~(1<<CS11); TIFR1 |= (1<<OCF1A) | (1<<OCF1B); /* Start */ TCNT1 = 0; /**< Registers timer with tov_cycles == 0. */ TCCR1B |= (1<<CS11); while (1) ; return 0; } --- diff --git a/simavr/sim/avr_timer.c b/simavr/sim/avr_timer.c index aeda219..6e1d8cc 100644 --- a/simavr/sim/avr_timer.c +++ b/simavr/sim/avr_timer.c @@ -173,9 +173,11 @@ static void avr_timer_tcnt_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t // printf("%s-%c %d/%d -- cycles %d/%d\n", __FUNCTION__, p->name, tcnt, p->tov_top, (uint32_t)cycles, (uint32_t)p->tov_cycles); // this reset the timers bases to the new base - p->tov_base = 0; - avr_cycle_timer_register(avr, p->tov_cycles - cycles, avr_timer_tov, p); - avr_timer_tov(avr, avr->cycle - cycles, p); + if (p->tov_cycles > 1) { + avr_cycle_timer_register(avr, p->tov_cycles - cycles, avr_timer_tov, p); + p->tov_base = 0; + avr_timer_tov(avr, avr->cycle - cycles, p); + } // tcnt = ((avr->cycle - p->tov_base) * p->tov_top) / p->tov_cycles; // printf("%s-%c new tnt derive to %d\n", __FUNCTION__, p->name, tcnt);