1 /*
2 * Copyright (C) 2022, Canaan Bright Sight Co., Ltd
3 *
4 * All enquiries to https://www.canaan-creative.com/
5 */
6
7 /*
8 * Copyright (c) 2006-2025 RT-Thread Development Team
9 *
10 * SPDX-License-Identifier: Apache-2.0
11 */
12
13 /*
14 * 本测试用例演示基于 01Studio Canmv-K230 开发板测试 gpio 的中断检测功能。其中
15 * 采用开发板上的按键 S3 以及其连接的 KEY_GPIO21 作为中断输入
16 * 在中断处理函数中控制 LED 的状态。LED2 采用开发板上的 LED2(连接 LED_GPIO52)。
17 * gpio_falling_edge_trigger_irq 将按键 S3 的中断触发方式设置为下降沿触发,测试
18 * 时应该会观察到在每次按下 S3 时收到中断。
19 * gpio_rising_edge_trigger_irq 将按键 S3 的中断触发方式设置为上升沿触发,测试
20 * 时应该会观察到在每次松开 S3 时收到中断。
21 * gpio_both_edge_trigger_irq 将按键 S3 的中断触发方式设置为双边沿触发。测试时
22 * 应该会观察到在每次按下或松开 S3 时都会收到中断。
23 */
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <rtthread.h>
27 #include <rtdevice.h>
28 #include "drv_gpio.h"
29 #include "utest.h"
30
31 #define LED_PIN_NUM 52
32 #define KEY_PIN_NUM 21
33
34 /* It is best to use an even number, especially for testing both edges triggering. */
35 #define MAX_LOOP_COUNT 6
36 static volatile int cnt;
37
38 #define LED_ON 1
39 #define LED_OFF 0
40 static volatile int led_status;
41
led_on(void)42 static void led_on(void)
43 {
44 LOG_W("led ON\n");
45 kd_pin_write(LED_PIN_NUM, GPIO_PV_HIGH);
46 led_status = LED_ON;
47 }
48
led_off(void)49 static void led_off(void)
50 {
51 LOG_W("led OFF\n");
52 kd_pin_write(LED_PIN_NUM, GPIO_PV_LOW);
53 led_status = LED_OFF;
54 }
55
key_irq(void * args)56 void key_irq(void *args)
57 {
58 LOG_I("---> IRQ: %d\n", ++cnt);
59 if(LED_OFF == led_status)
60 led_on();
61 else
62 led_off();
63 }
64
gpio_falling_edge_trigger_irq(void)65 static void gpio_falling_edge_trigger_irq(void)
66 {
67 cnt = 0;
68
69 /* Use default pinmux function */
70 kd_pin_mode(LED_PIN_NUM, GPIO_DM_OUTPUT);
71 led_off();
72
73 /* Use default pinmux function */
74 kd_pin_mode(KEY_PIN_NUM, GPIO_DM_INPUT);
75 kd_pin_attach_irq(KEY_PIN_NUM, GPIO_PE_FALLING, key_irq, RT_NULL);
76 kd_pin_irq_enable(KEY_PIN_NUM, KD_GPIO_IRQ_ENABLE);
77
78 while (cnt < MAX_LOOP_COUNT);
79 kd_pin_detach_irq(KEY_PIN_NUM);
80 }
81
gpio_rising_edge_trigger_irq(void)82 static void gpio_rising_edge_trigger_irq(void)
83 {
84 cnt = 0;
85
86 /* Use default pinmux function */
87 kd_pin_mode(LED_PIN_NUM, GPIO_DM_OUTPUT);
88 led_off();
89
90 /* Use default pinmux function */
91 kd_pin_mode(KEY_PIN_NUM, GPIO_DM_INPUT);
92 kd_pin_attach_irq(KEY_PIN_NUM, GPIO_PE_RISING, key_irq, RT_NULL);
93 kd_pin_irq_enable(KEY_PIN_NUM, KD_GPIO_IRQ_ENABLE);
94
95 while (cnt < MAX_LOOP_COUNT);
96 kd_pin_detach_irq(KEY_PIN_NUM);
97 }
98
gpio_both_edge_trigger_irq(void)99 static void gpio_both_edge_trigger_irq(void)
100 {
101 cnt = 0;
102
103 /* Use default pinmux function */
104 kd_pin_mode(LED_PIN_NUM, GPIO_DM_OUTPUT);
105 led_off();
106
107 /* Use default pinmux function */
108 kd_pin_mode(KEY_PIN_NUM, GPIO_DM_INPUT);
109 kd_pin_attach_irq(KEY_PIN_NUM, GPIO_PE_BOTH, key_irq, RT_NULL);
110 kd_pin_irq_enable(KEY_PIN_NUM, KD_GPIO_IRQ_ENABLE);
111
112 while (cnt < MAX_LOOP_COUNT);
113 kd_pin_detach_irq(KEY_PIN_NUM);
114 }
115
testcase(void)116 static void testcase(void)
117 {
118 UTEST_UNIT_RUN(gpio_falling_edge_trigger_irq);
119 UTEST_UNIT_RUN(gpio_rising_edge_trigger_irq);
120 UTEST_UNIT_RUN(gpio_both_edge_trigger_irq);
121 }
122
utest_tc_init(void)123 static rt_err_t utest_tc_init(void)
124 {
125 return RT_EOK;
126 }
127
utest_tc_cleanup(void)128 static rt_err_t utest_tc_cleanup(void)
129 {
130 return RT_EOK;
131 }
132
133 UTEST_TC_EXPORT(testcase, "gpio_irq", utest_tc_init, utest_tc_cleanup, 100);