bsp: k230: add gpio driver

K230 supports 3 GPIO groups:
group0: GPIO0  ~ GPIO31, support i/o and irq
group1: GPIO32 ~ GPIO63, support i/o and irq
group2: GPIO64 ~ GPIO71, only support i/o.

Signed-off-by: Chen Wang <unicorn_wang@outlook.com>
This commit is contained in:
Chen Wang 2025-06-04 14:21:53 +08:00 committed by Rbb666
parent 60c6fc0e3a
commit 14c147cb00
6 changed files with 783 additions and 0 deletions

View File

@ -0,0 +1,11 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('GPIO', src, depend = [], CPPPATH = CPPPATH)
Return('group')

View File

@ -0,0 +1,400 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2006-2025, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtthread.h>
#include <rthw.h>
#include <rtdevice.h>
#include <riscv_io.h>
#include <rtdef.h>
#include "ioremap.h"
#include "drv_gpio.h"
#include "drv_hardlock.h"
#include "board.h"
#include <dfs_posix.h>
#include <lwp_user_mm.h>
#include <sys/ioctl.h>
#include <rtdbg.h>
#define DBG_TAG "GPIO"
#ifdef RT_DEBUG
#define DBG_LVL DBG_LOG
#else
#define DBG_LVL DBG_WARNING
#endif
#define DBG_COLOR
struct kd_gpio_device {
struct rt_device dev;
void* base[2];
int hardlock;
};
static struct kd_gpio_device gpio_dev;
static struct
{
void (*hdr)(void* args);
void* args;
gpio_pin_edge_t edge;
int debounce;
struct rt_work debounce_work;
struct rt_work send_sig_work;
struct rt_lwp* lwp;
int lwp_ref_cnt;
int signo;
void* sigval;
} irq_table[GPIO_MAX_NUM];
static void kd_gpio_reg_writel(void* reg, rt_size_t offset, rt_uint32_t value)
{
while (0 != kd_hardlock_lock(gpio_dev.hardlock))
;
rt_uint32_t val = readl(reg);
val &= ~(1 << offset);
val |= (value << offset);
writel(val, reg);
kd_hardlock_unlock(gpio_dev.hardlock);
}
static rt_uint32_t kd_gpio_reg_readl(void* reg, rt_size_t offset)
{
rt_uint32_t val = readl(reg);
return (val & (1 << offset)) >> offset;
}
static int check_pin_valid(rt_base_t pin)
{
if ((rt_uint16_t)pin < 0 || (rt_uint16_t)pin > GPIO_MAX_NUM)
{
LOG_E("pin %d is not valid\n", pin);
return -RT_EINVAL;
}
return pin;
}
rt_err_t kd_pin_mode(rt_base_t pin, rt_base_t mode)
{
void* reg;
uint32_t dir;
if (check_pin_valid(pin) < 0)
return -RT_EINVAL;
switch (mode)
{
case GPIO_DM_INPUT:
dir = 0;
break;
case GPIO_DM_OUTPUT:
dir = 1;
break;
default:
LOG_E("GPIO drive mode is not supported.");
return -RT_EINVAL;
}
if (pin < 32)
{
reg = gpio_dev.base[0] + DIRECTION;
} else {
pin -= 32;
if (pin < 32)
{
reg = gpio_dev.base[1] + DIRECTION;
} else {
reg = gpio_dev.base[1] + DIRECTION + DIRECTION_STRIDE;
pin -= 32;
}
}
kd_gpio_reg_writel(reg, pin, dir);
return RT_EOK;
}
int kd_pin_mode_get(rt_base_t pin)
{
void* reg;
if (check_pin_valid(pin) < 0)
return -RT_EINVAL;
if (pin < 32)
{
reg = gpio_dev.base[0] + DIRECTION;
} else {
pin -= 32;
if (pin < 32)
{
reg = gpio_dev.base[1] + DIRECTION;
} else {
reg = gpio_dev.base[1] + DIRECTION + DIRECTION_STRIDE;
pin -= 32;
}
}
return kd_gpio_reg_readl(reg, pin) ? GPIO_DM_OUTPUT : GPIO_DM_INPUT;
}
rt_err_t kd_pin_write(rt_base_t pin, rt_base_t value)
{
void* reg;
if (check_pin_valid(pin) < 0)
return -RT_EINVAL;
if (pin < 32)
{
reg = gpio_dev.base[0] + DATA_OUTPUT;
} else {
pin -= 32;
if (pin < 32)
{
reg = gpio_dev.base[1] + DATA_OUTPUT;
} else {
reg = gpio_dev.base[1] + DATA_OUTPUT + DATA_INPUT_STRIDE;
pin -= 32;
}
}
kd_gpio_reg_writel(reg, pin, value ? GPIO_PV_HIGH : GPIO_PV_LOW);
return RT_EOK;
}
int kd_pin_read(rt_base_t pin)
{
void* reg;
if (check_pin_valid(pin) < 0)
return -RT_EINVAL;
if (pin < 32)
{
reg = gpio_dev.base[0] + DATA_INPUT;
} else {
pin -= 32;
if (pin < 32)
{
reg = gpio_dev.base[1] + DATA_INPUT;
} else {
reg = gpio_dev.base[1] + DATA_INPUT + DATA_INPUT_STRIDE;
pin -= 32;
}
}
return kd_gpio_reg_readl(reg, pin) ? GPIO_PV_HIGH : GPIO_PV_LOW;
}
static int kd_set_pin_edge(rt_int32_t pin, gpio_pin_edge_t edge)
{
void* reg;
reg = gpio_dev.base[pin >> 5];
pin = pin & 0x1f;
switch (edge)
{
case GPIO_PE_RISING:
kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x1);
kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x1);
kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
break;
case GPIO_PE_FALLING:
kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x1);
kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x0);
kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
break;
case GPIO_PE_BOTH:
kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x1);
break;
case GPIO_PE_LOW:
kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x0);
kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x0);
kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
break;
case GPIO_PE_HIGH:
kd_gpio_reg_writel(reg + INT_TYPE_LEVEL, pin, 0x0);
kd_gpio_reg_writel(reg + INT_POLARITY, pin, 0x1);
kd_gpio_reg_writel(reg + INT_BOTHEDGE, pin, 0x0);
break;
default:
break;
}
kd_gpio_reg_writel(reg + INT_ENABLE, pin, 0x1);
return RT_EOK;
}
static void debounce_work(struct rt_work* work, void* param)
{
void* reg;
rt_size_t pin = (rt_size_t)param;
reg = gpio_dev.base[pin >> 5];
pin = pin & 0x1f;
rt_base_t level = rt_hw_interrupt_disable();
kd_gpio_reg_writel(reg + INT_MASK, pin, 0x0);
rt_hw_interrupt_enable(level);
}
static void pin_irq(int vector, void* param)
{
void* reg;
long pin = vector - IRQN_GPIO0_INTERRUPT;
gpio_pin_edge_t edge = irq_table[pin].edge;
long pin_offset;
reg = gpio_dev.base[pin >> 5];
pin_offset = pin & 0x1f;
switch (edge)
{
case GPIO_PE_RISING:
case GPIO_PE_FALLING:
case GPIO_PE_BOTH:
kd_gpio_reg_writel(reg + INT_CLEAR, pin_offset, 0x1);
break;
case GPIO_PE_LOW:
case GPIO_PE_HIGH:
kd_gpio_reg_writel(reg + INT_MASK, pin_offset, 0x1);
rt_work_init(&irq_table[pin].debounce_work, debounce_work, (void *)pin);
rt_work_submit(&irq_table[pin].debounce_work, irq_table[pin].debounce);
break;
default:
break;
}
if (irq_table[pin].hdr)
irq_table[pin].hdr(irq_table[pin].args);
}
static void gpio_irq_to_user(void* args)
{
}
rt_err_t kd_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void* args), void* args)
{
char irq_name[10];
if (check_pin_valid(pin) < 0)
return -RT_EINVAL;
if (pin >= GPIO_IRQ_MAX_NUM)
{
LOG_E("pin %d not support interrupt", pin);
return -RT_EINVAL;
}
irq_table[pin].hdr = hdr;
irq_table[pin].args = args;
if (hdr != gpio_irq_to_user)
{
irq_table[pin].lwp = NULL;
irq_table[pin].lwp_ref_cnt = 0;
}
if (mode < 0 || mode > 4)
return -RT_EINVAL;
irq_table[pin].edge = mode;
irq_table[pin].debounce = rt_tick_from_millisecond(10);
kd_set_pin_edge(pin, irq_table[pin].edge);
rt_snprintf(irq_name, sizeof irq_name, "pin%d", pin);
rt_hw_interrupt_install(IRQN_GPIO0_INTERRUPT + pin, pin_irq, RT_NULL, irq_name);
return RT_EOK;
}
rt_err_t kd_pin_detach_irq(rt_int32_t pin)
{
void* reg;
if (check_pin_valid(pin) < 0)
return -RT_EINVAL;
if (pin >= GPIO_IRQ_MAX_NUM)
{
LOG_E("pin %d not support interrupt", pin);
return -RT_EINVAL;
}
irq_table[pin].hdr = RT_NULL;
irq_table[pin].args = RT_NULL;
irq_table[pin].lwp = NULL;
irq_table[pin].lwp_ref_cnt = 0;
irq_table[pin].signo = 0;
irq_table[pin].sigval = 0;
reg = gpio_dev.base[pin >> 5];
pin = pin & 0x1f;
kd_gpio_reg_writel(reg + INT_ENABLE, pin, 0x0);
return RT_EOK;
}
rt_err_t kd_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled)
{
if (check_pin_valid(pin) < 0)
return -RT_EINVAL;
if (pin >= GPIO_IRQ_MAX_NUM)
{
LOG_E("pin %d not support interrupt", pin);
return -RT_EINVAL;
}
if (enabled)
rt_hw_interrupt_umask(IRQN_GPIO0_INTERRUPT + pin);
else
rt_hw_interrupt_mask(IRQN_GPIO0_INTERRUPT + pin);
return RT_EOK;
}
int rt_hw_gpio_init(void)
{
rt_err_t ret;
gpio_dev.base[0] = rt_ioremap((void*)GPIO0_BASE_ADDR, GPIO0_IO_SIZE);
gpio_dev.base[1] = rt_ioremap((void*)GPIO1_BASE_ADDR, GPIO1_IO_SIZE);
if (kd_request_lock(HARDLOCK_GPIO))
{
rt_kprintf("fail to request hardlock-%d\n", HARDLOCK_GPIO);
return -RT_ERROR;
}
gpio_dev.hardlock = HARDLOCK_GPIO;
ret = rt_device_register(&gpio_dev.dev, "gpio", RT_DEVICE_FLAG_RDWR);
return ret;
}
INIT_BOARD_EXPORT(rt_hw_gpio_init);

View File

@ -0,0 +1,132 @@
/* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2006-2025, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef DRV_GPIO_H__
#define DRV_GPIO_H__
#define GPIO_IRQ_MAX_NUM (64)
#define GPIO_MAX_NUM (64+8)
#define IRQN_GPIO0_INTERRUPT 32
/* k230 gpio register table */
#define DATA_OUTPUT 0x0
#define DIRECTION 0x04
#define DATA_SOURCE 0x08
#define INT_ENABLE 0x30
#define INT_MASK 0x34
#define INT_TYPE_LEVEL 0x38
#define INT_POLARITY 0x3c
#define INT_STATUS 0x40
#define INT_STATUS_RAW 0x44
#define INT_DEBOUNCE 0x48
#define INT_CLEAR 0x4c
#define DATA_INPUT 0x50
#define VER_ID_CODE 0x64
#define INT_BOTHEDGE 0x68
#define DATA_INPUT_STRIDE 0x04 /* register stride 32 bits */
#define DATA_OUTPUT_STRIDE 0x0c /* register stride 3*32 bits */
#define DIRECTION_STRIDE 0x0c /* register stride 3*32 bits, */
#define KD_GPIO_HIGH 1
#define KD_GPIO_LOW 0
#define KD_GPIO_IRQ_DISABLE 0x00
#define KD_GPIO_IRQ_ENABLE 0x01
/* ioctl */
#define KD_GPIO_DM_OUTPUT _IOW('G', 0, int)
#define KD_GPIO_DM_INPUT _IOW('G', 1, int)
#define KD_GPIO_DM_INPUT_PULL_UP _IOW('G', 2, int)
#define KD_GPIO_DM_INPUT_PULL_DOWN _IOW('G', 3, int)
#define KD_GPIO_WRITE_LOW _IOW('G', 4, int)
#define KD_GPIO_WRITE_HIGH _IOW('G', 5, int)
#define KD_GPIO_PE_RISING _IOW('G', 7, int)
#define KD_GPIO_PE_FALLING _IOW('G', 8, int)
#define KD_GPIO_PE_BOTH _IOW('G', 9, int)
#define KD_GPIO_PE_HIGH _IOW('G', 10, int)
#define KD_GPIO_PE_LOW _IOW('G', 11, int)
#define KD_GPIO_READ_VALUE _IOW('G', 12, int)
#define KD_GPIO_SET_MODE _IOW('G', 20, int)
#define KD_GPIO_GET_MODE _IOWR('G', 21, int)
#define KD_GPIO_SET_VALUE _IOW('G', 22, int)
#define KD_GPIO_GET_VALUE _IOWR('G', 23, int)
#define KD_GPIO_SET_IRQ _IOW('G', 24, int)
#define KD_GPIO_GET_IRQ _IOWR('G', 25, int)
typedef enum _gpio_pin_edge
{
GPIO_PE_RISING,
GPIO_PE_FALLING,
GPIO_PE_BOTH,
GPIO_PE_HIGH,
GPIO_PE_LOW,
} gpio_pin_edge_t;
typedef enum _gpio_drive_mode
{
GPIO_DM_OUTPUT,
GPIO_DM_INPUT,
GPIO_DM_INPUT_PULL_UP,
GPIO_DM_INPUT_PULL_DOWN,
} gpio_drive_mode_t;
typedef enum _gpio_pin_value
{
GPIO_PV_LOW,
GPIO_PV_HIGH
} gpio_pin_value_t;
typedef struct {
rt_uint16_t pin;
rt_uint16_t value;
} gpio_cfg_t;
typedef struct {
rt_uint16_t pin;
rt_uint8_t enable;
rt_uint8_t mode;
rt_uint16_t debounce;
rt_uint8_t signo;
void *sigval;
} gpio_irqcfg_t;
rt_err_t kd_pin_irq_enable(rt_base_t pin, rt_uint32_t enabled);
rt_err_t kd_pin_detach_irq(rt_int32_t pin);
rt_err_t kd_pin_attach_irq(rt_int32_t pin,rt_uint32_t mode, void (*hdr)(void *args), void *args);
rt_err_t kd_pin_write(rt_base_t pin, rt_base_t value);
rt_err_t kd_pin_mode(rt_base_t pin, rt_base_t mode);
int kd_pin_read(rt_base_t pin);
#endif

View File

@ -3,6 +3,8 @@ from building import *
src = []
if GetDepend('RT_UTEST_USING_ALL_CASES') or GetDepend('BSP_UTEST_DRIVERS'):
src += ['test_gpio.c']
src += ['test_gpio_irq.c']
if GetDepend('BSP_USING_TIMERS'):
src += ['test_timer.c']

View File

@ -0,0 +1,105 @@
/*
* Copyright (C) 2022, Canaan Bright Sight Co., Ltd
*
* All enquiries to https://www.canaan-creative.com/
*/
/*
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* 01Studio Canmv-K230 gpio
* gpio_led_flashing LED LED LED2 LED_GPIO52
* gpio_io 线 40Pin GPIO GPIO33 GPIO32 GPIO33
* GPIO32 GPIO33 GPIO32
*
*/
#include <unistd.h>
#include <stdio.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <ioremap.h>
#include "board.h"
#include "drv_pinctrl.h"
#include "drv_gpio.h"
#include "utest.h"
#define LED_PIN_NUM 52
#define OUT_PIN_NUM 33
#define IN_PIN_NUM 32
static void gpio_led_flashing(void)
{
int cnt = 5;
/* Use default pinmux function */
kd_pin_mode(LED_PIN_NUM, GPIO_DM_OUTPUT);
while(cnt--)
{
LOG_I("led ON");
kd_pin_write(LED_PIN_NUM, GPIO_PV_HIGH);
rt_thread_mdelay(1000);
LOG_I("led OFF");
kd_pin_write(LED_PIN_NUM, GPIO_PV_LOW);
rt_thread_mdelay(1000);
}
}
static void gpio_io(void)
{
int cnt = 5;
int level = 0xff;
rt_uint32_t val;
/* Set pinmux function */
k230_pinctrl_set_function(IN_PIN_NUM, IOMUX_FUNC1);
k230_pinctrl_set_ie(IN_PIN_NUM, 1);
k230_pinctrl_set_oe(IN_PIN_NUM, 0);
k230_pinctrl_set_function(OUT_PIN_NUM, IOMUX_FUNC1);
k230_pinctrl_set_ie(OUT_PIN_NUM, 0);
k230_pinctrl_set_oe(OUT_PIN_NUM, 1);
/* Set GPIO mode */
kd_pin_mode(OUT_PIN_NUM, GPIO_DM_OUTPUT);
kd_pin_mode(IN_PIN_NUM, GPIO_DM_INPUT);
while(cnt--)
{
kd_pin_write(OUT_PIN_NUM, GPIO_PV_LOW);
level = kd_pin_read(IN_PIN_NUM);
LOG_I("--> %d", level);
uassert_int_equal(level, GPIO_PV_LOW);
kd_pin_write(OUT_PIN_NUM, GPIO_PV_HIGH);
level = kd_pin_read(IN_PIN_NUM);
LOG_I("--> %d", level);
uassert_int_equal(level, GPIO_PV_HIGH);
rt_thread_mdelay(500);
}
}
static void testcase(void)
{
UTEST_UNIT_RUN(gpio_led_flashing);
UTEST_UNIT_RUN(gpio_io);
}
static rt_err_t utest_tc_init(void)
{
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
return RT_EOK;
}
UTEST_TC_EXPORT(testcase, "gpio", utest_tc_init, utest_tc_cleanup, 100);

View File

@ -0,0 +1,133 @@
/*
* Copyright (C) 2022, Canaan Bright Sight Co., Ltd
*
* All enquiries to https://www.canaan-creative.com/
*/
/*
* Copyright (c) 2006-2025 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* 01Studio Canmv-K230 gpio
* S3 KEY_GPIO21
* LED LED2 LED2 LED_GPIO52
* gpio_falling_edge_trigger_irq S3 沿
* S3
* gpio_rising_edge_trigger_irq S3 沿
* S3
* gpio_both_edge_trigger_irq S3 沿
* S3
*/
#include <unistd.h>
#include <stdio.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_gpio.h"
#include "utest.h"
#define LED_PIN_NUM 52
#define KEY_PIN_NUM 21
/* It is best to use an even number, especially for testing both edges triggering. */
#define MAX_LOOP_COUNT 6
static volatile int cnt;
#define LED_ON 1
#define LED_OFF 0
static volatile int led_status;
static void led_on(void)
{
LOG_W("led ON\n");
kd_pin_write(LED_PIN_NUM, GPIO_PV_HIGH);
led_status = LED_ON;
}
static void led_off(void)
{
LOG_W("led OFF\n");
kd_pin_write(LED_PIN_NUM, GPIO_PV_LOW);
led_status = LED_OFF;
}
void key_irq(void *args)
{
LOG_I("---> IRQ: %d\n", ++cnt);
if(LED_OFF == led_status)
led_on();
else
led_off();
}
static void gpio_falling_edge_trigger_irq(void)
{
cnt = 0;
/* Use default pinmux function */
kd_pin_mode(LED_PIN_NUM, GPIO_DM_OUTPUT);
led_off();
/* Use default pinmux function */
kd_pin_mode(KEY_PIN_NUM, GPIO_DM_INPUT);
kd_pin_attach_irq(KEY_PIN_NUM, GPIO_PE_FALLING, key_irq, RT_NULL);
kd_pin_irq_enable(KEY_PIN_NUM, KD_GPIO_IRQ_ENABLE);
while (cnt < MAX_LOOP_COUNT);
kd_pin_detach_irq(KEY_PIN_NUM);
}
static void gpio_rising_edge_trigger_irq(void)
{
cnt = 0;
/* Use default pinmux function */
kd_pin_mode(LED_PIN_NUM, GPIO_DM_OUTPUT);
led_off();
/* Use default pinmux function */
kd_pin_mode(KEY_PIN_NUM, GPIO_DM_INPUT);
kd_pin_attach_irq(KEY_PIN_NUM, GPIO_PE_RISING, key_irq, RT_NULL);
kd_pin_irq_enable(KEY_PIN_NUM, KD_GPIO_IRQ_ENABLE);
while (cnt < MAX_LOOP_COUNT);
kd_pin_detach_irq(KEY_PIN_NUM);
}
static void gpio_both_edge_trigger_irq(void)
{
cnt = 0;
/* Use default pinmux function */
kd_pin_mode(LED_PIN_NUM, GPIO_DM_OUTPUT);
led_off();
/* Use default pinmux function */
kd_pin_mode(KEY_PIN_NUM, GPIO_DM_INPUT);
kd_pin_attach_irq(KEY_PIN_NUM, GPIO_PE_BOTH, key_irq, RT_NULL);
kd_pin_irq_enable(KEY_PIN_NUM, KD_GPIO_IRQ_ENABLE);
while (cnt < MAX_LOOP_COUNT);
kd_pin_detach_irq(KEY_PIN_NUM);
}
static void testcase(void)
{
UTEST_UNIT_RUN(gpio_falling_edge_trigger_irq);
UTEST_UNIT_RUN(gpio_rising_edge_trigger_irq);
UTEST_UNIT_RUN(gpio_both_edge_trigger_irq);
}
static rt_err_t utest_tc_init(void)
{
return RT_EOK;
}
static rt_err_t utest_tc_cleanup(void)
{
return RT_EOK;
}
UTEST_TC_EXPORT(testcase, "gpio_irq", utest_tc_init, utest_tc_cleanup, 100);