2 * QTest testcase for STM32L4x5_EXTI
4 * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
5 * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
7 * This work is licensed under the terms of the GNU GPL, version 2 or later.
8 * See the COPYING file in the top-level directory.
11 #include "qemu/osdep.h"
12 #include "libqtest-single.h"
14 #define EXTI_BASE_ADDR 0x40010400
15 #define EXTI_IMR1 0x00
16 #define EXTI_EMR1 0x04
17 #define EXTI_RTSR1 0x08
18 #define EXTI_FTSR1 0x0C
19 #define EXTI_SWIER1 0x10
21 #define EXTI_IMR2 0x20
22 #define EXTI_EMR2 0x24
23 #define EXTI_RTSR2 0x28
24 #define EXTI_FTSR2 0x2C
25 #define EXTI_SWIER2 0x30
28 #define NVIC_ISER 0xE000E100
29 #define NVIC_ISPR 0xE000E200
30 #define NVIC_ICPR 0xE000E280
36 static void enable_nvic_irq(unsigned int n
)
38 writel(NVIC_ISER
, 1 << n
);
41 static void unpend_nvic_irq(unsigned int n
)
43 writel(NVIC_ICPR
, 1 << n
);
46 static bool check_nvic_pending(unsigned int n
)
48 return readl(NVIC_ISPR
) & (1 << n
);
51 static void exti_writel(unsigned int offset
, uint32_t value
)
53 writel(EXTI_BASE_ADDR
+ offset
, value
);
56 static uint32_t exti_readl(unsigned int offset
)
58 return readl(EXTI_BASE_ADDR
+ offset
);
61 static void exti_set_irq(int num
, int level
)
63 qtest_set_irq_in(global_qtest
, "/machine/soc/exti", NULL
,
67 static void test_reg_write_read(void)
69 /* Test that non-reserved bits in xMR and xTSR can be set and cleared */
71 exti_writel(EXTI_IMR1
, 0xFFFFFFFF);
72 g_assert_cmpuint(exti_readl(EXTI_IMR1
), ==, 0xFFFFFFFF);
73 exti_writel(EXTI_IMR1
, 0x00000000);
74 g_assert_cmpuint(exti_readl(EXTI_IMR1
), ==, 0x00000000);
76 exti_writel(EXTI_EMR1
, 0xFFFFFFFF);
77 g_assert_cmpuint(exti_readl(EXTI_EMR1
), ==, 0xFFFFFFFF);
78 exti_writel(EXTI_EMR1
, 0x00000000);
79 g_assert_cmpuint(exti_readl(EXTI_EMR1
), ==, 0x00000000);
81 exti_writel(EXTI_RTSR1
, 0xFFFFFFFF);
82 g_assert_cmpuint(exti_readl(EXTI_RTSR1
), ==, 0x007DFFFF);
83 exti_writel(EXTI_RTSR1
, 0x00000000);
84 g_assert_cmpuint(exti_readl(EXTI_RTSR1
), ==, 0x00000000);
86 exti_writel(EXTI_FTSR1
, 0xFFFFFFFF);
87 g_assert_cmpuint(exti_readl(EXTI_FTSR1
), ==, 0x007DFFFF);
88 exti_writel(EXTI_FTSR1
, 0x00000000);
89 g_assert_cmpuint(exti_readl(EXTI_FTSR1
), ==, 0x00000000);
91 exti_writel(EXTI_IMR2
, 0xFFFFFFFF);
92 g_assert_cmpuint(exti_readl(EXTI_IMR2
), ==, 0x000000FF);
93 exti_writel(EXTI_IMR2
, 0x00000000);
94 g_assert_cmpuint(exti_readl(EXTI_IMR2
), ==, 0x00000000);
96 exti_writel(EXTI_EMR2
, 0xFFFFFFFF);
97 g_assert_cmpuint(exti_readl(EXTI_EMR2
), ==, 0x000000FF);
98 exti_writel(EXTI_EMR2
, 0x00000000);
99 g_assert_cmpuint(exti_readl(EXTI_EMR2
), ==, 0x00000000);
101 exti_writel(EXTI_RTSR2
, 0xFFFFFFFF);
102 g_assert_cmpuint(exti_readl(EXTI_RTSR2
), ==, 0x00000078);
103 exti_writel(EXTI_RTSR2
, 0x00000000);
104 g_assert_cmpuint(exti_readl(EXTI_RTSR2
), ==, 0x00000000);
106 exti_writel(EXTI_FTSR2
, 0xFFFFFFFF);
107 g_assert_cmpuint(exti_readl(EXTI_FTSR2
), ==, 0x00000078);
108 exti_writel(EXTI_FTSR2
, 0x00000000);
109 g_assert_cmpuint(exti_readl(EXTI_FTSR2
), ==, 0x00000000);
112 static void test_direct_lines_write(void)
114 /* Test that direct lines reserved bits are not written to */
116 exti_writel(EXTI_RTSR1
, 0xFF820000);
117 g_assert_cmpuint(exti_readl(EXTI_RTSR1
), ==, 0x00000000);
119 exti_writel(EXTI_FTSR1
, 0xFF820000);
120 g_assert_cmpuint(exti_readl(EXTI_FTSR1
), ==, 0x00000000);
122 exti_writel(EXTI_SWIER1
, 0xFF820000);
123 g_assert_cmpuint(exti_readl(EXTI_SWIER1
), ==, 0x00000000);
125 exti_writel(EXTI_PR1
, 0xFF820000);
126 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
128 exti_writel(EXTI_RTSR2
, 0x00000087);
129 g_assert_cmpuint(exti_readl(EXTI_RTSR2
), ==, 0x00000000);
131 exti_writel(EXTI_FTSR2
, 0x00000087);
132 g_assert_cmpuint(exti_readl(EXTI_FTSR2
), ==, 0x00000000);
134 exti_writel(EXTI_SWIER2
, 0x00000087);
135 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000000);
137 exti_writel(EXTI_PR2
, 0x00000087);
138 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
141 static void test_reserved_bits_write(void)
143 /* Test that reserved bits stay are not written to */
145 exti_writel(EXTI_IMR2
, 0xFFFFFF00);
146 g_assert_cmpuint(exti_readl(EXTI_IMR2
), ==, 0x00000000);
148 exti_writel(EXTI_EMR2
, 0xFFFFFF00);
149 g_assert_cmpuint(exti_readl(EXTI_EMR2
), ==, 0x00000000);
151 exti_writel(EXTI_RTSR2
, 0xFFFFFF00);
152 g_assert_cmpuint(exti_readl(EXTI_RTSR2
), ==, 0x00000000);
154 exti_writel(EXTI_FTSR2
, 0xFFFFFF00);
155 g_assert_cmpuint(exti_readl(EXTI_FTSR2
), ==, 0x00000000);
157 exti_writel(EXTI_SWIER2
, 0xFFFFFF00);
158 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000000);
160 exti_writel(EXTI_PR2
, 0xFFFFFF00);
161 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
164 static void test_software_interrupt(void)
167 * Test that we can launch a software irq by :
168 * - enabling its line in IMR
169 * - and then setting a bit from '0' to '1' in SWIER
171 * And that the interruption stays pending in NVIC
172 * even after clearing the pending bit in PR.
176 * Testing interrupt line EXTI0
177 * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
180 enable_nvic_irq(EXTI0_IRQ
);
181 /* Check that there are no interrupts already pending in PR */
182 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
183 /* Check that this specific interrupt isn't pending in NVIC */
184 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
186 /* Enable interrupt line EXTI0 */
187 exti_writel(EXTI_IMR1
, 0x00000001);
188 /* Set the right SWIER bit from '0' to '1' */
189 exti_writel(EXTI_SWIER1
, 0x00000000);
190 exti_writel(EXTI_SWIER1
, 0x00000001);
192 /* Check that the write in SWIER was effective */
193 g_assert_cmpuint(exti_readl(EXTI_SWIER1
), ==, 0x00000001);
194 /* Check that the corresponding pending bit in PR is set */
195 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
196 /* Check that the corresponding interrupt is pending in the NVIC */
197 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
199 /* Clear the pending bit in PR */
200 exti_writel(EXTI_PR1
, 0x00000001);
202 /* Check that the write in PR was effective */
203 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
204 /* Check that the corresponding bit in SWIER was cleared */
205 g_assert_cmpuint(exti_readl(EXTI_SWIER1
), ==, 0x00000000);
206 /* Check that the interrupt is still pending in the NVIC */
207 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
210 * Testing interrupt line EXTI35
211 * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
214 enable_nvic_irq(EXTI35_IRQ
);
215 /* Check that there are no interrupts already pending */
216 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
217 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
219 /* Enable interrupt line EXTI0 */
220 exti_writel(EXTI_IMR2
, 0x00000008);
221 /* Set the right SWIER bit from '0' to '1' */
222 exti_writel(EXTI_SWIER2
, 0x00000000);
223 exti_writel(EXTI_SWIER2
, 0x00000008);
225 /* Check that the write in SWIER was effective */
226 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000008);
227 /* Check that the corresponding pending bit in PR is set */
228 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000008);
229 /* Check that the corresponding interrupt is pending in the NVIC */
230 g_assert_true(check_nvic_pending(EXTI35_IRQ
));
232 /* Clear the pending bit in PR */
233 exti_writel(EXTI_PR2
, 0x00000008);
235 /* Check that the write in PR was effective */
236 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
237 /* Check that the corresponding bit in SWIER was cleared */
238 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000000);
239 /* Check that the interrupt is still pending in the NVIC */
240 g_assert_true(check_nvic_pending(EXTI35_IRQ
));
243 unpend_nvic_irq(EXTI0_IRQ
);
244 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
245 unpend_nvic_irq(EXTI35_IRQ
);
246 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
249 static void test_edge_selector(void)
251 enable_nvic_irq(EXTI0_IRQ
);
253 /* Configure EXTI line 0 irq on rising edge */
255 exti_writel(EXTI_IMR1
, 0x00000001);
256 exti_writel(EXTI_RTSR1
, 0x00000001);
257 exti_writel(EXTI_FTSR1
, 0x00000000);
259 /* Test that an irq is raised on rising edge only */
261 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
262 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
265 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
266 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
269 exti_writel(EXTI_PR1
, 0x00000001);
270 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
271 unpend_nvic_irq(EXTI0_IRQ
);
272 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
274 /* Configure EXTI line 0 irq on falling edge */
276 exti_writel(EXTI_IMR1
, 0x00000001);
277 exti_writel(EXTI_RTSR1
, 0x00000000);
278 exti_writel(EXTI_FTSR1
, 0x00000001);
280 /* Test that an irq is raised on falling edge only */
282 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
283 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
286 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
287 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
290 exti_writel(EXTI_PR1
, 0x00000001);
291 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
292 unpend_nvic_irq(EXTI0_IRQ
);
293 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
295 /* Configure EXTI line 0 irq on falling and rising edge */
296 exti_writel(EXTI_IMR1
, 0x00000001);
297 exti_writel(EXTI_RTSR1
, 0x00000001);
298 exti_writel(EXTI_FTSR1
, 0x00000001);
300 /* Test that an irq is raised on rising edge */
302 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
303 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
306 exti_writel(EXTI_PR1
, 0x00000001);
307 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
308 unpend_nvic_irq(EXTI0_IRQ
);
309 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
311 /* Test that an irq is raised on falling edge */
313 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
314 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
317 exti_writel(EXTI_PR1
, 0x00000001);
318 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
319 unpend_nvic_irq(EXTI0_IRQ
);
320 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
322 /* Configure EXTI line 0 irq without selecting an edge trigger */
323 exti_writel(EXTI_IMR1
, 0x00000001);
324 exti_writel(EXTI_RTSR1
, 0x00000000);
325 exti_writel(EXTI_FTSR1
, 0x00000000);
327 /* Test that no irq is raised */
329 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
330 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
333 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
334 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
337 static void test_no_software_interrupt(void)
340 * Test that software irq doesn't happen when :
341 * - corresponding bit in IMR isn't set
342 * - SWIER is set to 1 before IMR is set to 1
346 * Testing interrupt line EXTI0
347 * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
350 enable_nvic_irq(EXTI0_IRQ
);
351 /* Check that there are no interrupts already pending in PR */
352 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
353 /* Check that this specific interrupt isn't pending in NVIC */
354 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
356 /* Mask interrupt line EXTI0 */
357 exti_writel(EXTI_IMR1
, 0x00000000);
358 /* Set the corresponding SWIER bit from '0' to '1' */
359 exti_writel(EXTI_SWIER1
, 0x00000000);
360 exti_writel(EXTI_SWIER1
, 0x00000001);
362 /* Check that the write in SWIER was effective */
363 g_assert_cmpuint(exti_readl(EXTI_SWIER1
), ==, 0x00000001);
364 /* Check that the pending bit in PR wasn't set */
365 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
366 /* Check that the interrupt isn't pending in NVIC */
367 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
369 /* Enable interrupt line EXTI0 */
370 exti_writel(EXTI_IMR1
, 0x00000001);
372 /* Check that the pending bit in PR wasn't set */
373 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
374 /* Check that the interrupt isn't pending in NVIC */
375 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
378 * Testing interrupt line EXTI35
379 * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
382 enable_nvic_irq(EXTI35_IRQ
);
383 /* Check that there are no interrupts already pending in PR */
384 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
385 /* Check that this specific interrupt isn't pending in NVIC */
386 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
388 /* Mask interrupt line EXTI35 */
389 exti_writel(EXTI_IMR2
, 0x00000000);
390 /* Set the corresponding SWIER bit from '0' to '1' */
391 exti_writel(EXTI_SWIER2
, 0x00000000);
392 exti_writel(EXTI_SWIER2
, 0x00000008);
394 /* Check that the write in SWIER was effective */
395 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000008);
396 /* Check that the pending bit in PR wasn't set */
397 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
398 /* Check that the interrupt isn't pending in NVIC */
399 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
401 /* Enable interrupt line EXTI35 */
402 exti_writel(EXTI_IMR2
, 0x00000008);
404 /* Check that the pending bit in PR wasn't set */
405 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
406 /* Check that the interrupt isn't pending in NVIC */
407 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
410 static void test_masked_interrupt(void)
413 * Test that irq doesn't happen when :
414 * - corresponding bit in IMR isn't set
415 * - SWIER is set to 1 before IMR is set to 1
419 * Testing interrupt line EXTI1
420 * with rising edge from GPIOx pin 1
423 enable_nvic_irq(EXTI1_IRQ
);
424 /* Check that there are no interrupts already pending in PR */
425 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
426 /* Check that this specific interrupt isn't pending in NVIC */
427 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
429 /* Mask interrupt line EXTI1 */
430 exti_writel(EXTI_IMR1
, 0x00000000);
432 /* Configure interrupt on rising edge */
433 exti_writel(EXTI_RTSR1
, 0x00000002);
435 /* Simulate rising edge from GPIO line 1 */
438 /* Check that the pending bit in PR wasn't set */
439 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
440 /* Check that the interrupt isn't pending in NVIC */
441 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
443 /* Enable interrupt line EXTI1 */
444 exti_writel(EXTI_IMR1
, 0x00000002);
446 /* Check that the pending bit in PR wasn't set */
447 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
448 /* Check that the interrupt isn't pending in NVIC */
449 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
452 static void test_interrupt(void)
455 * Test that we can launch an irq by :
456 * - enabling its line in IMR
457 * - configuring interrupt on rising edge
458 * - and then setting the input line from '0' to '1'
460 * And that the interruption stays pending in NVIC
461 * even after clearing the pending bit in PR.
465 * Testing interrupt line EXTI1
466 * with rising edge from GPIOx pin 1
469 enable_nvic_irq(EXTI1_IRQ
);
470 /* Check that there are no interrupts already pending in PR */
471 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
472 /* Check that this specific interrupt isn't pending in NVIC */
473 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
475 /* Enable interrupt line EXTI1 */
476 exti_writel(EXTI_IMR1
, 0x00000002);
478 /* Configure interrupt on rising edge */
479 exti_writel(EXTI_RTSR1
, 0x00000002);
481 /* Simulate rising edge from GPIO line 1 */
484 /* Check that the pending bit in PR was set */
485 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000002);
486 /* Check that the interrupt is pending in NVIC */
487 g_assert_true(check_nvic_pending(EXTI1_IRQ
));
489 /* Clear the pending bit in PR */
490 exti_writel(EXTI_PR1
, 0x00000002);
492 /* Check that the write in PR was effective */
493 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
494 /* Check that the interrupt is still pending in the NVIC */
495 g_assert_true(check_nvic_pending(EXTI1_IRQ
));
498 unpend_nvic_irq(EXTI1_IRQ
);
499 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
502 int main(int argc
, char **argv
)
506 g_test_init(&argc
, &argv
, NULL
);
507 g_test_set_nonfatal_assertions();
508 qtest_add_func("stm32l4x5/exti/direct_lines", test_direct_lines_write
);
509 qtest_add_func("stm32l4x5/exti/reserved_bits", test_reserved_bits_write
);
510 qtest_add_func("stm32l4x5/exti/reg_write_read", test_reg_write_read
);
511 qtest_add_func("stm32l4x5/exti/no_software_interrupt",
512 test_no_software_interrupt
);
513 qtest_add_func("stm32l4x5/exti/software_interrupt",
514 test_software_interrupt
);
515 qtest_add_func("stm32l4x5/exti/masked_interrupt", test_masked_interrupt
);
516 qtest_add_func("stm32l4x5/exti/interrupt", test_interrupt
);
517 qtest_add_func("stm32l4x5/exti/test_edge_selector", test_edge_selector
);
519 qtest_start("-machine b-l475e-iot01a");