From 9c4887e3b68a362f2f5a4e86daab98a51b3b769e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?In=C3=A8s=20Varhol?= <ines.varhol@telecom-paris.fr> Date: Sat, 29 Jun 2024 13:07:08 +0200 Subject: [PATCH] hw/misc: In STM32L4x5 EXTI, correct configurable interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The implementation of configurable interrupts (interrupts supporting edge selection) was incorrectly expecting alternating input levels : this commits adds a new status field `irq_levels` to actually detect edges. Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr> Message-id: 20240629110800.539969-2-ines.varhol@telecom-paris.fr Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/misc/stm32l4x5_exti.c | 28 +++++++++++++--------------- include/hw/misc/stm32l4x5_exti.h | 2 ++ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/hw/misc/stm32l4x5_exti.c b/hw/misc/stm32l4x5_exti.c index 495a0004ab..6a2ec62d78 100644 --- a/hw/misc/stm32l4x5_exti.c +++ b/hw/misc/stm32l4x5_exti.c @@ -88,6 +88,7 @@ static void stm32l4x5_exti_reset_hold(Object *obj, ResetType type) s->ftsr[bank] = 0x00000000; s->swier[bank] = 0x00000000; s->pr[bank] = 0x00000000; + s->irq_levels[bank] = 0x00000000; } } @@ -102,27 +103,23 @@ static void stm32l4x5_exti_set_irq(void *opaque, int irq, int level) /* Shift the value to enable access in x2 registers. */ irq %= EXTI_MAX_IRQ_PER_BANK; + if (level == extract32(s->irq_levels[bank], irq, 1)) { + /* No change in IRQ line state: do nothing */ + return; + } + s->irq_levels[bank] = deposit32(s->irq_levels[bank], irq, 1, level); + /* If the interrupt is masked, pr won't be raised */ if (!extract32(s->imr[bank], irq, 1)) { return; } - if (((1 << irq) & s->rtsr[bank]) && level) { - /* Rising Edge */ - s->pr[bank] |= 1 << irq; - qemu_irq_pulse(s->irq[oirq]); - } else if (((1 << irq) & s->ftsr[bank]) && !level) { - /* Falling Edge */ + if ((level && extract32(s->rtsr[bank], irq, 1)) || + (!level && extract32(s->ftsr[bank], irq, 1))) { + s->pr[bank] |= 1 << irq; qemu_irq_pulse(s->irq[oirq]); } - /* - * In the following situations : - * - falling edge but rising trigger selected - * - rising edge but falling trigger selected - * - no trigger selected - * No action is required - */ } static uint64_t stm32l4x5_exti_read(void *opaque, hwaddr addr, @@ -255,8 +252,8 @@ static void stm32l4x5_exti_init(Object *obj) static const VMStateDescription vmstate_stm32l4x5_exti = { .name = TYPE_STM32L4X5_EXTI, - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(imr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER), VMSTATE_UINT32_ARRAY(emr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER), @@ -264,6 +261,7 @@ static const VMStateDescription vmstate_stm32l4x5_exti = { VMSTATE_UINT32_ARRAY(ftsr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER), VMSTATE_UINT32_ARRAY(swier, Stm32l4x5ExtiState, EXTI_NUM_REGISTER), VMSTATE_UINT32_ARRAY(pr, Stm32l4x5ExtiState, EXTI_NUM_REGISTER), + VMSTATE_UINT32_ARRAY(irq_levels, Stm32l4x5ExtiState, EXTI_NUM_REGISTER), VMSTATE_END_OF_LIST() } }; diff --git a/include/hw/misc/stm32l4x5_exti.h b/include/hw/misc/stm32l4x5_exti.h index be961d2f01..55f763fa37 100644 --- a/include/hw/misc/stm32l4x5_exti.h +++ b/include/hw/misc/stm32l4x5_exti.h @@ -45,6 +45,8 @@ struct Stm32l4x5ExtiState { uint32_t swier[EXTI_NUM_REGISTER]; uint32_t pr[EXTI_NUM_REGISTER]; + /* used for edge detection */ + uint32_t irq_levels[EXTI_NUM_REGISTER]; qemu_irq irq[EXTI_NUM_INTERRUPT_OUT_LINES]; };