1 /*
2  * Copyright (c) 2025 Alexander Kozhinov <ak.alexander.kozhinov@gmail.com>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/ztest.h>
8 #include <zephyr/irq.h>
9 #include <zephyr/init.h>
10 #include <zephyr/device.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/atomic.h>
13 #include <zephyr/drivers/interrupt_controller/intc_exti_stm32.h>
14 
15 
16 #define EXTI_DT_NODE		DT_INST(0, st_stm32_exti)
17 #define EXTI_NUM_LINES_TOTAL	DT_PROP(EXTI_DT_NODE, num_lines)
18 #define EXTI_NUM_LINES_GPIO	DT_PROP(EXTI_DT_NODE, num_gpio_lines)
19 
20 #define TEST_EXTI_LINE_NR	DT_PROP(DT_INST(0, test_st_stm32_exti), exti_line_nr)
21 #define TEST_EXTI_IRQ_NR	DT_PROP(DT_INST(0, test_st_stm32_exti), exti_line_irq_nr)
22 #define TEST_EXTI_IRQ_PRIO	DT_PROP(DT_INST(0, test_st_stm32_exti), exti_line_irq_prio)
23 
24 
25 BUILD_ASSERT(TEST_EXTI_LINE_NR < EXTI_NUM_LINES_TOTAL, "Invalid EXTI line number");
26 
27 static atomic_t is_test_exti_isr_called;
28 
test_exti_isr(void)29 static void test_exti_isr(void)
30 {
31 	zassert_true(stm32_exti_is_pending(TEST_EXTI_LINE_NR));
32 	stm32_exti_clear_pending(TEST_EXTI_LINE_NR);
33 
34 	atomic_set(&is_test_exti_isr_called, true);
35 }
36 
ZTEST(intc_exti_stm32,test_sw_interrupt_rising_trigger)37 ZTEST(intc_exti_stm32, test_sw_interrupt_rising_trigger)
38 {
39 	int ret = 0;
40 
41 	ret = stm32_exti_enable(TEST_EXTI_LINE_NR,
42 				STM32_EXTI_TRIG_RISING,
43 				STM32_EXTI_MODE_IT);
44 	zassert_ok(ret, "Failed to enable EXTI line %d", TEST_EXTI_LINE_NR);
45 
46 	atomic_set(&is_test_exti_isr_called, false);
47 
48 	ret = stm32_exti_sw_interrupt(TEST_EXTI_LINE_NR);
49 	zassert_ok(ret, "Failed to fire SW interrupt on EXTI line %d",
50 		   TEST_EXTI_LINE_NR);
51 
52 	zassert_equal(is_test_exti_isr_called, true,
53 		      "ISR was not called for EXTI line %d", TEST_EXTI_LINE_NR);
54 }
55 
ZTEST(intc_exti_stm32,test_sw_interrupt_falling_trigger)56 ZTEST(intc_exti_stm32, test_sw_interrupt_falling_trigger)
57 {
58 	int ret = 0;
59 
60 	ret = stm32_exti_enable(TEST_EXTI_LINE_NR,
61 				STM32_EXTI_TRIG_FALLING,
62 				STM32_EXTI_MODE_IT);
63 	zassert_ok(ret, "Failed to enable EXTI line %d", TEST_EXTI_LINE_NR);
64 
65 	atomic_set(&is_test_exti_isr_called, false);
66 
67 	ret = stm32_exti_sw_interrupt(TEST_EXTI_LINE_NR);
68 	zassert_ok(ret, "Failed to fire SW interrupt on EXTI line %d",
69 		   TEST_EXTI_LINE_NR);
70 
71 	zassert_equal(is_test_exti_isr_called, true,
72 		      "ISR was not called for EXTI line %d", TEST_EXTI_LINE_NR);
73 }
74 
ZTEST(intc_exti_stm32,test_sw_interrupt_both_triggers)75 ZTEST(intc_exti_stm32, test_sw_interrupt_both_triggers)
76 {
77 	int ret = 0;
78 
79 	ret = stm32_exti_enable(TEST_EXTI_LINE_NR,
80 				STM32_EXTI_TRIG_BOTH,
81 				STM32_EXTI_MODE_IT);
82 	zassert_ok(ret, "Failed to enable EXTI line %d", TEST_EXTI_LINE_NR);
83 
84 	atomic_set(&is_test_exti_isr_called, false);
85 
86 	ret = stm32_exti_sw_interrupt(TEST_EXTI_LINE_NR);
87 	zassert_ok(ret, "Failed to fire SW interrupt on EXTI line %d",
88 		   TEST_EXTI_LINE_NR);
89 
90 	zassert_equal(is_test_exti_isr_called, true,
91 		      "ISR was not called for EXTI line %d", TEST_EXTI_LINE_NR);
92 }
93 
test_exti_intc_init(void)94 static void *test_exti_intc_init(void)
95 {
96 	IRQ_CONNECT(
97 		TEST_EXTI_IRQ_NR, TEST_EXTI_IRQ_PRIO,
98 		test_exti_isr, NULL, 0
99 	);
100 
101 	irq_enable(TEST_EXTI_IRQ_NR);
102 
103 	return NULL;
104 }
105 
106 ZTEST_SUITE(intc_exti_stm32, NULL, test_exti_intc_init, NULL, NULL, NULL);
107