Commit 7e3e150b0ee5a4af352b26e96a6512272214d69e
authorMichel Pollet <buserror@gmail.com>
Tue, 11 May 2010 11:35:46 +0000 (12:35 +0100)
committerMichel Pollet <buserror@gmail.com>
Tue, 11 May 2010 11:35:46 +0000 (12:35 +0100)
Allow exclicit clearing of interupts by writing 1
to the pending bit.

Signed-off-by: Michel Pollet <buserror@gmail.com>
simavr/sim/avr_timer.c

index d20f313ec3e0a1fa97ce3ab7b4dbb1d27eee248e..ce66983dd6e68f73cac39e1fc50f0807ea7329fc 100644 (file)
@@ -296,6 +296,32 @@ static void avr_timer_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, v
        avr_timer_reconfigure(p);
 }
 
+/*
+ * write to the TIFR register. Watch for code that writes "1" to clear
+ * pending interrupts.
+ */
+static void avr_timer_write_pending(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
+{
+       avr_timer_t * p = (avr_timer_t *)param;
+       // save old bits values
+       uint8_t ov = avr_regbit_get(avr, p->overflow.raised);
+       uint8_t ic = avr_regbit_get(avr, p->icr.raised);
+       uint8_t cp[AVR_TIMER_COMP_COUNT];
+
+       for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++)
+               cp[compi] = avr_regbit_get(avr, p->comp[compi].interrupt.raised);
+
+       // write the value
+       avr_core_watch_write(avr, addr, v);
+
+       // clear any interrupts & flags
+       avr_clear_interupt_if(avr, &p->overflow, ov);
+       avr_clear_interupt_if(avr, &p->icr, ic);
+
+       for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++)
+               avr_clear_interupt_if(avr, &p->comp[compi].interrupt, cp[compi]);
+}
+
 static void avr_timer_irq_icp(struct avr_irq_t * irq, uint32_t value, void * param)
 {
        avr_timer_t * p = (avr_timer_t *)param;
@@ -383,6 +409,10 @@ void avr_timer_init(avr_t * avr, avr_timer_t * p)
 
        avr_register_io_write(avr, p->cs[0].reg, avr_timer_write, p);
 
+       // this assumes all the "pending" interrupt bits are in the same
+       // register. Might not be true on all devices ?
+       avr_register_io_write(avr, p->overflow.raised.reg, avr_timer_write_pending, p);
+
        /*
         * Even if the timer is 16 bits, we don't care to have watches on the
         * high bytes because the datasheet says that the low address is always