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);