* [PATCH 1/2] hw/misc: In STM32L4x5 EXTI, correct configurable interrupts
  2024-06-29 11:07 [PATCH 0/2] hw/misc: Fix STM32L4x5 EXTI interrupts Inès Varhol
@ 2024-06-29 11:07 ` Inès Varhol
  2024-06-29 11:07 ` [PATCH 2/2] tests/qtest: Ensure STM32L4x5 EXTI state is correct at the end of QTests Inès Varhol
  2024-07-01 11:48 ` [PATCH 0/2] hw/misc: Fix STM32L4x5 EXTI interrupts Peter Maydell
  2 siblings, 0 replies; 4+ messages in thread
From: Inès Varhol @ 2024-06-29 11:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Inès Varhol, Paolo Bonzini,
	Laurent Vivier, Arnaud Minier, Alistair Francis,
	Philippe Mathieu-Daudé, Peter Maydell
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>
---
 include/hw/misc/stm32l4x5_exti.h |  2 ++
 hw/misc/stm32l4x5_exti.c         | 28 +++++++++++++---------------
 2 files changed, 15 insertions(+), 15 deletions(-)
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];
 };
 
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()
     }
 };
-- 
2.43.2
^ permalink raw reply related	[flat|nested] 4+ messages in thread* [PATCH 2/2] tests/qtest: Ensure STM32L4x5 EXTI state is correct at the end of QTests
  2024-06-29 11:07 [PATCH 0/2] hw/misc: Fix STM32L4x5 EXTI interrupts Inès Varhol
  2024-06-29 11:07 ` [PATCH 1/2] hw/misc: In STM32L4x5 EXTI, correct configurable interrupts Inès Varhol
@ 2024-06-29 11:07 ` Inès Varhol
  2024-07-01 11:48 ` [PATCH 0/2] hw/misc: Fix STM32L4x5 EXTI interrupts Peter Maydell
  2 siblings, 0 replies; 4+ messages in thread
From: Inès Varhol @ 2024-06-29 11:07 UTC (permalink / raw)
  To: qemu-devel
  Cc: Thomas Huth, qemu-arm, Inès Varhol, Paolo Bonzini,
	Laurent Vivier, Arnaud Minier, Alistair Francis,
	Philippe Mathieu-Daudé, Peter Maydell
EXTI's new field `irq_levels` tracks irq levels between tests when using
`global_qtest`.
This happens in `stm32l4x5_exti-test.c`, `stm32l4x5_syscfg-test.c` and
`stm32l4x5_gpio-test.c` (`dm163.c` doesn't use `global_qtest`).
To ensure that `irq_levels` has the same value before and after each
QTest, this commit toggles back the irq lines that were changed at the
end of each problematic test. Most QTests were already doing this.
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
---
 tests/qtest/stm32l4x5_exti-test.c   | 8 ++++++++
 tests/qtest/stm32l4x5_syscfg-test.c | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/tests/qtest/stm32l4x5_exti-test.c b/tests/qtest/stm32l4x5_exti-test.c
index 7092860b9b..7e39c992fd 100644
--- a/tests/qtest/stm32l4x5_exti-test.c
+++ b/tests/qtest/stm32l4x5_exti-test.c
@@ -448,6 +448,9 @@ static void test_masked_interrupt(void)
     g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
     /* Check that the interrupt isn't pending in NVIC */
     g_assert_false(check_nvic_pending(EXTI1_IRQ));
+
+    /* Clean EXTI */
+    exti_set_irq(1, 0);
 }
 
 static void test_interrupt(void)
@@ -498,6 +501,9 @@ static void test_interrupt(void)
     /* Clean NVIC */
     unpend_nvic_irq(EXTI1_IRQ);
     g_assert_false(check_nvic_pending(EXTI1_IRQ));
+
+    /* Clean EXTI */
+    exti_set_irq(1, 0);
 }
 
 static void test_orred_interrupts(void)
@@ -531,6 +537,8 @@ static void test_orred_interrupts(void)
 
         unpend_nvic_irq(EXTI5_9_IRQ);
         g_assert_false(check_nvic_pending(EXTI5_9_IRQ));
+
+        exti_set_irq(i, 0);
     }
 }
 
diff --git a/tests/qtest/stm32l4x5_syscfg-test.c b/tests/qtest/stm32l4x5_syscfg-test.c
index 506ca08bc2..4416959b4a 100644
--- a/tests/qtest/stm32l4x5_syscfg-test.c
+++ b/tests/qtest/stm32l4x5_syscfg-test.c
@@ -221,10 +221,10 @@ static void test_interrupt(void)
     g_assert_true(get_irq(1));
 
     /* Clean the test */
-    syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
     syscfg_set_irq(0, 0);
     syscfg_set_irq(15, 0);
     syscfg_set_irq(17, 0);
+    syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
 }
 
 static void test_irq_pin_multiplexer(void)
-- 
2.43.2
^ permalink raw reply related	[flat|nested] 4+ messages in thread