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
34 #define EXTI5_9_IRQ 23
37 static void enable_nvic_irq(unsigned int n
)
39 writel(NVIC_ISER
, 1 << n
);
42 static void unpend_nvic_irq(unsigned int n
)
44 writel(NVIC_ICPR
, 1 << n
);
47 static bool check_nvic_pending(unsigned int n
)
49 return readl(NVIC_ISPR
) & (1 << n
);
52 static void exti_writel(unsigned int offset
, uint32_t value
)
54 writel(EXTI_BASE_ADDR
+ offset
, value
);
57 static uint32_t exti_readl(unsigned int offset
)
59 return readl(EXTI_BASE_ADDR
+ offset
);
62 static void exti_set_irq(int num
, int level
)
64 qtest_set_irq_in(global_qtest
, "/machine/soc/exti", NULL
,
68 static void test_reg_write_read(void)
70 /* Test that non-reserved bits in xMR and xTSR can be set and cleared */
72 exti_writel(EXTI_IMR1
, 0xFFFFFFFF);
73 g_assert_cmpuint(exti_readl(EXTI_IMR1
), ==, 0xFFFFFFFF);
74 exti_writel(EXTI_IMR1
, 0x00000000);
75 g_assert_cmpuint(exti_readl(EXTI_IMR1
), ==, 0x00000000);
77 exti_writel(EXTI_EMR1
, 0xFFFFFFFF);
78 g_assert_cmpuint(exti_readl(EXTI_EMR1
), ==, 0xFFFFFFFF);
79 exti_writel(EXTI_EMR1
, 0x00000000);
80 g_assert_cmpuint(exti_readl(EXTI_EMR1
), ==, 0x00000000);
82 exti_writel(EXTI_RTSR1
, 0xFFFFFFFF);
83 g_assert_cmpuint(exti_readl(EXTI_RTSR1
), ==, 0x007DFFFF);
84 exti_writel(EXTI_RTSR1
, 0x00000000);
85 g_assert_cmpuint(exti_readl(EXTI_RTSR1
), ==, 0x00000000);
87 exti_writel(EXTI_FTSR1
, 0xFFFFFFFF);
88 g_assert_cmpuint(exti_readl(EXTI_FTSR1
), ==, 0x007DFFFF);
89 exti_writel(EXTI_FTSR1
, 0x00000000);
90 g_assert_cmpuint(exti_readl(EXTI_FTSR1
), ==, 0x00000000);
92 exti_writel(EXTI_IMR2
, 0xFFFFFFFF);
93 g_assert_cmpuint(exti_readl(EXTI_IMR2
), ==, 0x000000FF);
94 exti_writel(EXTI_IMR2
, 0x00000000);
95 g_assert_cmpuint(exti_readl(EXTI_IMR2
), ==, 0x00000000);
97 exti_writel(EXTI_EMR2
, 0xFFFFFFFF);
98 g_assert_cmpuint(exti_readl(EXTI_EMR2
), ==, 0x000000FF);
99 exti_writel(EXTI_EMR2
, 0x00000000);
100 g_assert_cmpuint(exti_readl(EXTI_EMR2
), ==, 0x00000000);
102 exti_writel(EXTI_RTSR2
, 0xFFFFFFFF);
103 g_assert_cmpuint(exti_readl(EXTI_RTSR2
), ==, 0x00000078);
104 exti_writel(EXTI_RTSR2
, 0x00000000);
105 g_assert_cmpuint(exti_readl(EXTI_RTSR2
), ==, 0x00000000);
107 exti_writel(EXTI_FTSR2
, 0xFFFFFFFF);
108 g_assert_cmpuint(exti_readl(EXTI_FTSR2
), ==, 0x00000078);
109 exti_writel(EXTI_FTSR2
, 0x00000000);
110 g_assert_cmpuint(exti_readl(EXTI_FTSR2
), ==, 0x00000000);
113 static void test_direct_lines_write(void)
115 /* Test that direct lines reserved bits are not written to */
117 exti_writel(EXTI_RTSR1
, 0xFF820000);
118 g_assert_cmpuint(exti_readl(EXTI_RTSR1
), ==, 0x00000000);
120 exti_writel(EXTI_FTSR1
, 0xFF820000);
121 g_assert_cmpuint(exti_readl(EXTI_FTSR1
), ==, 0x00000000);
123 exti_writel(EXTI_SWIER1
, 0xFF820000);
124 g_assert_cmpuint(exti_readl(EXTI_SWIER1
), ==, 0x00000000);
126 exti_writel(EXTI_PR1
, 0xFF820000);
127 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
129 exti_writel(EXTI_RTSR2
, 0x00000087);
130 g_assert_cmpuint(exti_readl(EXTI_RTSR2
), ==, 0x00000000);
132 exti_writel(EXTI_FTSR2
, 0x00000087);
133 g_assert_cmpuint(exti_readl(EXTI_FTSR2
), ==, 0x00000000);
135 exti_writel(EXTI_SWIER2
, 0x00000087);
136 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000000);
138 exti_writel(EXTI_PR2
, 0x00000087);
139 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
142 static void test_reserved_bits_write(void)
144 /* Test that reserved bits stay are not written to */
146 exti_writel(EXTI_IMR2
, 0xFFFFFF00);
147 g_assert_cmpuint(exti_readl(EXTI_IMR2
), ==, 0x00000000);
149 exti_writel(EXTI_EMR2
, 0xFFFFFF00);
150 g_assert_cmpuint(exti_readl(EXTI_EMR2
), ==, 0x00000000);
152 exti_writel(EXTI_RTSR2
, 0xFFFFFF00);
153 g_assert_cmpuint(exti_readl(EXTI_RTSR2
), ==, 0x00000000);
155 exti_writel(EXTI_FTSR2
, 0xFFFFFF00);
156 g_assert_cmpuint(exti_readl(EXTI_FTSR2
), ==, 0x00000000);
158 exti_writel(EXTI_SWIER2
, 0xFFFFFF00);
159 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000000);
161 exti_writel(EXTI_PR2
, 0xFFFFFF00);
162 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
165 static void test_software_interrupt(void)
168 * Test that we can launch a software irq by :
169 * - enabling its line in IMR
170 * - and then setting a bit from '0' to '1' in SWIER
172 * And that the interruption stays pending in NVIC
173 * even after clearing the pending bit in PR.
177 * Testing interrupt line EXTI0
178 * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
181 enable_nvic_irq(EXTI0_IRQ
);
182 /* Check that there are no interrupts already pending in PR */
183 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
184 /* Check that this specific interrupt isn't pending in NVIC */
185 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
187 /* Enable interrupt line EXTI0 */
188 exti_writel(EXTI_IMR1
, 0x00000001);
189 /* Set the right SWIER bit from '0' to '1' */
190 exti_writel(EXTI_SWIER1
, 0x00000000);
191 exti_writel(EXTI_SWIER1
, 0x00000001);
193 /* Check that the write in SWIER was effective */
194 g_assert_cmpuint(exti_readl(EXTI_SWIER1
), ==, 0x00000001);
195 /* Check that the corresponding pending bit in PR is set */
196 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
197 /* Check that the corresponding interrupt is pending in the NVIC */
198 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
200 /* Clear the pending bit in PR */
201 exti_writel(EXTI_PR1
, 0x00000001);
203 /* Check that the write in PR was effective */
204 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
205 /* Check that the corresponding bit in SWIER was cleared */
206 g_assert_cmpuint(exti_readl(EXTI_SWIER1
), ==, 0x00000000);
207 /* Check that the interrupt is still pending in the NVIC */
208 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
211 * Testing interrupt line EXTI35
212 * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
215 enable_nvic_irq(EXTI35_IRQ
);
216 /* Check that there are no interrupts already pending */
217 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
218 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
220 /* Enable interrupt line EXTI0 */
221 exti_writel(EXTI_IMR2
, 0x00000008);
222 /* Set the right SWIER bit from '0' to '1' */
223 exti_writel(EXTI_SWIER2
, 0x00000000);
224 exti_writel(EXTI_SWIER2
, 0x00000008);
226 /* Check that the write in SWIER was effective */
227 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000008);
228 /* Check that the corresponding pending bit in PR is set */
229 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000008);
230 /* Check that the corresponding interrupt is pending in the NVIC */
231 g_assert_true(check_nvic_pending(EXTI35_IRQ
));
233 /* Clear the pending bit in PR */
234 exti_writel(EXTI_PR2
, 0x00000008);
236 /* Check that the write in PR was effective */
237 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
238 /* Check that the corresponding bit in SWIER was cleared */
239 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000000);
240 /* Check that the interrupt is still pending in the NVIC */
241 g_assert_true(check_nvic_pending(EXTI35_IRQ
));
244 unpend_nvic_irq(EXTI0_IRQ
);
245 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
246 unpend_nvic_irq(EXTI35_IRQ
);
247 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
250 static void test_edge_selector(void)
252 enable_nvic_irq(EXTI0_IRQ
);
254 /* Configure EXTI line 0 irq on rising edge */
256 exti_writel(EXTI_IMR1
, 0x00000001);
257 exti_writel(EXTI_RTSR1
, 0x00000001);
258 exti_writel(EXTI_FTSR1
, 0x00000000);
260 /* Test that an irq is raised on rising edge only */
262 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
263 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
266 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
267 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
270 exti_writel(EXTI_PR1
, 0x00000001);
271 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
272 unpend_nvic_irq(EXTI0_IRQ
);
273 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
275 /* Configure EXTI line 0 irq on falling edge */
277 exti_writel(EXTI_IMR1
, 0x00000001);
278 exti_writel(EXTI_RTSR1
, 0x00000000);
279 exti_writel(EXTI_FTSR1
, 0x00000001);
281 /* Test that an irq is raised on falling edge only */
283 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
284 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
287 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
288 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
291 exti_writel(EXTI_PR1
, 0x00000001);
292 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
293 unpend_nvic_irq(EXTI0_IRQ
);
294 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
296 /* Configure EXTI line 0 irq on falling and rising edge */
297 exti_writel(EXTI_IMR1
, 0x00000001);
298 exti_writel(EXTI_RTSR1
, 0x00000001);
299 exti_writel(EXTI_FTSR1
, 0x00000001);
301 /* Test that an irq is raised on rising edge */
303 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
304 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
307 exti_writel(EXTI_PR1
, 0x00000001);
308 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
309 unpend_nvic_irq(EXTI0_IRQ
);
310 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
312 /* Test that an irq is raised on falling edge */
314 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000001);
315 g_assert_true(check_nvic_pending(EXTI0_IRQ
));
318 exti_writel(EXTI_PR1
, 0x00000001);
319 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
320 unpend_nvic_irq(EXTI0_IRQ
);
321 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
323 /* Configure EXTI line 0 irq without selecting an edge trigger */
324 exti_writel(EXTI_IMR1
, 0x00000001);
325 exti_writel(EXTI_RTSR1
, 0x00000000);
326 exti_writel(EXTI_FTSR1
, 0x00000000);
328 /* Test that no irq is raised */
330 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
331 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
334 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
335 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
338 static void test_no_software_interrupt(void)
341 * Test that software irq doesn't happen when :
342 * - corresponding bit in IMR isn't set
343 * - SWIER is set to 1 before IMR is set to 1
347 * Testing interrupt line EXTI0
348 * Bit 0 in EXTI_*1 registers (EXTI0) corresponds to GPIO Px_0
351 enable_nvic_irq(EXTI0_IRQ
);
352 /* Check that there are no interrupts already pending in PR */
353 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
354 /* Check that this specific interrupt isn't pending in NVIC */
355 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
357 /* Mask interrupt line EXTI0 */
358 exti_writel(EXTI_IMR1
, 0x00000000);
359 /* Set the corresponding SWIER bit from '0' to '1' */
360 exti_writel(EXTI_SWIER1
, 0x00000000);
361 exti_writel(EXTI_SWIER1
, 0x00000001);
363 /* Check that the write in SWIER was effective */
364 g_assert_cmpuint(exti_readl(EXTI_SWIER1
), ==, 0x00000001);
365 /* Check that the pending bit in PR wasn't set */
366 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
367 /* Check that the interrupt isn't pending in NVIC */
368 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
370 /* Enable interrupt line EXTI0 */
371 exti_writel(EXTI_IMR1
, 0x00000001);
373 /* Check that the pending bit in PR wasn't set */
374 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
375 /* Check that the interrupt isn't pending in NVIC */
376 g_assert_false(check_nvic_pending(EXTI0_IRQ
));
379 * Testing interrupt line EXTI35
380 * Bit 3 in EXTI_*2 registers (EXTI35) corresponds to PVM 1 Wakeup
383 enable_nvic_irq(EXTI35_IRQ
);
384 /* Check that there are no interrupts already pending in PR */
385 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
386 /* Check that this specific interrupt isn't pending in NVIC */
387 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
389 /* Mask interrupt line EXTI35 */
390 exti_writel(EXTI_IMR2
, 0x00000000);
391 /* Set the corresponding SWIER bit from '0' to '1' */
392 exti_writel(EXTI_SWIER2
, 0x00000000);
393 exti_writel(EXTI_SWIER2
, 0x00000008);
395 /* Check that the write in SWIER was effective */
396 g_assert_cmpuint(exti_readl(EXTI_SWIER2
), ==, 0x00000008);
397 /* Check that the pending bit in PR wasn't set */
398 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
399 /* Check that the interrupt isn't pending in NVIC */
400 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
402 /* Enable interrupt line EXTI35 */
403 exti_writel(EXTI_IMR2
, 0x00000008);
405 /* Check that the pending bit in PR wasn't set */
406 g_assert_cmpuint(exti_readl(EXTI_PR2
), ==, 0x00000000);
407 /* Check that the interrupt isn't pending in NVIC */
408 g_assert_false(check_nvic_pending(EXTI35_IRQ
));
411 static void test_masked_interrupt(void)
414 * Test that irq doesn't happen when :
415 * - corresponding bit in IMR isn't set
416 * - SWIER is set to 1 before IMR is set to 1
420 * Testing interrupt line EXTI1
421 * with rising edge from GPIOx pin 1
424 enable_nvic_irq(EXTI1_IRQ
);
425 /* Check that there are no interrupts already pending in PR */
426 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
427 /* Check that this specific interrupt isn't pending in NVIC */
428 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
430 /* Mask interrupt line EXTI1 */
431 exti_writel(EXTI_IMR1
, 0x00000000);
433 /* Configure interrupt on rising edge */
434 exti_writel(EXTI_RTSR1
, 0x00000002);
436 /* Simulate rising edge from GPIO line 1 */
439 /* Check that the pending bit in PR wasn't set */
440 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
441 /* Check that the interrupt isn't pending in NVIC */
442 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
444 /* Enable interrupt line EXTI1 */
445 exti_writel(EXTI_IMR1
, 0x00000002);
447 /* Check that the pending bit in PR wasn't set */
448 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
449 /* Check that the interrupt isn't pending in NVIC */
450 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
453 static void test_interrupt(void)
456 * Test that we can launch an irq by :
457 * - enabling its line in IMR
458 * - configuring interrupt on rising edge
459 * - and then setting the input line from '0' to '1'
461 * And that the interruption stays pending in NVIC
462 * even after clearing the pending bit in PR.
466 * Testing interrupt line EXTI1
467 * with rising edge from GPIOx pin 1
470 enable_nvic_irq(EXTI1_IRQ
);
471 /* Check that there are no interrupts already pending in PR */
472 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
473 /* Check that this specific interrupt isn't pending in NVIC */
474 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
476 /* Enable interrupt line EXTI1 */
477 exti_writel(EXTI_IMR1
, 0x00000002);
479 /* Configure interrupt on rising edge */
480 exti_writel(EXTI_RTSR1
, 0x00000002);
482 /* Simulate rising edge from GPIO line 1 */
485 /* Check that the pending bit in PR was set */
486 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000002);
487 /* Check that the interrupt is pending in NVIC */
488 g_assert_true(check_nvic_pending(EXTI1_IRQ
));
490 /* Clear the pending bit in PR */
491 exti_writel(EXTI_PR1
, 0x00000002);
493 /* Check that the write in PR was effective */
494 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
495 /* Check that the interrupt is still pending in the NVIC */
496 g_assert_true(check_nvic_pending(EXTI1_IRQ
));
499 unpend_nvic_irq(EXTI1_IRQ
);
500 g_assert_false(check_nvic_pending(EXTI1_IRQ
));
503 static void test_orred_interrupts(void)
506 * For lines EXTI5..9 (fanned-in to NVIC irq 23),
507 * test that raising the line pends interrupt
510 enable_nvic_irq(EXTI5_9_IRQ
);
511 /* Check that there are no interrupts already pending in PR */
512 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
513 /* Check that this specific interrupt isn't pending in NVIC */
514 g_assert_false(check_nvic_pending(EXTI5_9_IRQ
));
516 /* Enable interrupt lines EXTI[5..9] */
517 exti_writel(EXTI_IMR1
, (0x1F << 5));
519 /* Configure interrupt on rising edge */
520 exti_writel(EXTI_RTSR1
, (0x1F << 5));
522 /* Raise GPIO line i, check that the interrupt is pending */
523 for (unsigned i
= 5; i
< 10; i
++) {
525 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 1 << i
);
526 g_assert_true(check_nvic_pending(EXTI5_9_IRQ
));
528 exti_writel(EXTI_PR1
, 1 << i
);
529 g_assert_cmpuint(exti_readl(EXTI_PR1
), ==, 0x00000000);
530 g_assert_true(check_nvic_pending(EXTI5_9_IRQ
));
532 unpend_nvic_irq(EXTI5_9_IRQ
);
533 g_assert_false(check_nvic_pending(EXTI5_9_IRQ
));
537 int main(int argc
, char **argv
)
541 g_test_init(&argc
, &argv
, NULL
);
542 g_test_set_nonfatal_assertions();
543 qtest_add_func("stm32l4x5/exti/direct_lines", test_direct_lines_write
);
544 qtest_add_func("stm32l4x5/exti/reserved_bits", test_reserved_bits_write
);
545 qtest_add_func("stm32l4x5/exti/reg_write_read", test_reg_write_read
);
546 qtest_add_func("stm32l4x5/exti/no_software_interrupt",
547 test_no_software_interrupt
);
548 qtest_add_func("stm32l4x5/exti/software_interrupt",
549 test_software_interrupt
);
550 qtest_add_func("stm32l4x5/exti/masked_interrupt", test_masked_interrupt
);
551 qtest_add_func("stm32l4x5/exti/interrupt", test_interrupt
);
552 qtest_add_func("stm32l4x5/exti/test_edge_selector", test_edge_selector
);
553 qtest_add_func("stm32l4x5/exti/test_orred_interrupts",
554 test_orred_interrupts
);
556 qtest_start("-machine b-l475e-iot01a");