Skip to content

Commit efe4a71

Browse files
author
ga
committed
Plausible fix for Bug #465 -
"External pin interrupt kills performance despite being disabled." Do not start the timer until the interrupt is prending.
1 parent 8f11365 commit efe4a71

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

simavr/sim/avr_extint.c

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -138,26 +138,43 @@ static void avr_extint_irq_notify(struct avr_irq_t * irq, uint32_t value, void *
138138
{
139139
/**
140140
Datasheet excerpt:
141-
>When the external interrupt is enabled and is configured as level triggered (only INT0/INT1),
142-
>the interrupt will trigger as long as the pin is held low.
143-
Thus we have to query the pin value continiously while it's held low and try to trigger the interrupt.
144-
This can be expensive, so avr_extint_set_strict_lvl_trig function provisioned to allow the user
145-
to turn this feature off. In this case bahaviour will be similar to the falling edge interrupt.
141+
> When the external interrupt is enabled and is configured
142+
> as level triggered (only INT0/INT1), the interrupt
143+
> will trigger as long as the pin is held low.
144+
Thus we have to query the pin value continuously while
145+
it's held low and try to trigger the interrupt.
146+
This can be expensive, so avr_extint_set_strict_lvl_trig()
147+
function provisioned to allow the user to turn
148+
this feature off. In this case behaviour will be similar
149+
to the falling edge interrupt.
146150
*/
147151
if (!value) {
148-
if (avr->sreg[S_I]) {
149-
uint8_t raised = avr_regbit_get(avr, p->eint[irq->irq].vector.raised) || p->eint[irq->irq].vector.pending;
150-
if (!raised)
151-
avr_raise_interrupt(avr, &p->eint[irq->irq].vector);
152-
}
153-
if (p->eint[irq->irq].strict_lvl_trig) {
154-
avr_extint_poll_context_t *poll = malloc(sizeof(avr_extint_poll_context_t));
152+
uint8_t raised;
153+
154+
raised = (avr_regbit_get(
155+
avr,
156+
p->eint[irq->irq].vector.raised) ||
157+
p->eint[irq->irq].vector.pending);
158+
if (!raised)
159+
avr_raise_interrupt(avr, &p->eint[irq->irq].vector);
160+
if (!raised && p->eint[irq->irq].vector.pending) {
161+
avr_extint_poll_context_t *poll;
162+
163+
/* Interrupt pending, so start fast timer to re-enable
164+
* it if the pin level does not change in the handler.
165+
*/
166+
167+
poll = malloc(sizeof(avr_extint_poll_context_t));
155168
if (poll) {
156169
poll->eint_no = irq->irq;
157170
poll->extint = p;
158-
avr_cycle_timer_register(avr, 1, avr_extint_poll_level_trig, poll);
171+
avr_cycle_timer_register(
172+
avr, 1, avr_extint_poll_level_trig, poll);
159173
}
160174
}
175+
} else {
176+
avr_clear_interrupt(avr, &p->eint[irq->irq].vector);
177+
// If running, timer will clear on next call.
161178
}
162179
}
163180
break;

0 commit comments

Comments
 (0)