1 单按键模块的信号线接 TinkerBoard 的物理 21号引脚,通过 gpio readall 命令可以得知此引脚对应的CPU引脚号是39,后面有用。
在这里插入图片描述
从上图可以得知 21号引脚的名称是 GPIO1_A7,
也就是它是rk3399 GPIO 分组1 里面的第8个gpio 口,
查看rk3399的芯片手册的第20章,可以知道 分组1 的基地址是 0xFF730000
,方向寄存器的偏移是 0x0004。 中断寄存器的偏移是 0x0030,
如下所示:

#define GPIO_1_BASE  0xFF730000
#define  GPIO1_SWPORTA_DDR  0xFF730004
#define  GPIO_INTEN   (GPIO_1_BASE + 0x0030)

以下就是具体流程:

1 设置方向寄存器对应的bit位为0,也就是输入。
2 设置方向寄存器对应的bit位为1,也就是启用中断。
3 通过gpio_to_irq获得中断号。
4 调用request_irq(num, key_handler, IRQF_TRIGGER_LOW,
“key”, NULL),注意是下降沿触发,key_handler为回调函数。

以下是完整代码:

#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/cdev.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/init.h> /* Needed for the macros */
#include <linux/kernel.h> /* Needed for pr_info() */
#include <linux/module.h> /* Needed by all modules */
#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#define  GPIO_PIN  39
#define GPIO_1_BASE  0xFF730000
//#define  GPIO1_SWPORTA_DR GPIO_1_BASE
#define  GPIO1_SWPORTA_DDR  0xFF730004
#define  GPIO_INTEN   (GPIO_1_BASE + 0x0030)

// GPIO1_A7
#define LOCATION  7

irqreturn_t key_handler(int irq, void *dev_id) {
	pr_err("my key_handler   \n");
	return IRQ_HANDLED;
}

const struct file_operations my_fops = { .owner = THIS_MODULE, };

unsigned int num;

static __init int my_init(void) {
	int ret;
	unsigned int __iomem *direction = ioremap(GPIO1_SWPORTA_DDR, 4);
	unsigned int a = readl(direction);
	unsigned int __iomem *irq = ioremap(GPIO_INTEN, 4);

// set direction in
	writel(readl(direction) & (~(1 << LOCATION)), direction);
	//just check
	a = readl(direction);
	pr_err("direction: %d \n", a);

	pr_err("direction 1 or 0  ? : %d \n", (a & (1 << LOCATION)) >> LOCATION);

// enable Interrupt
	writel(readl(irq) | (1 << LOCATION), irq);

	pr_err("Interrupt 1 or 0  ? : %d \n",
		(readl(irq) & (1 << LOCATION)) >> LOCATION);

	num = gpio_to_irq(GPIO_PIN);

	pr_info("irq_num:%d\n",num);

	ret = request_irq(num, key_handler, IRQF_TRIGGER_FALLING,
				"my_key_driver", NULL);

	if (ret < 0) {
			pr_err("request_irq  failed \n");
			return ret;
		}
	pr_info(
		"a3 init_module success\n");
	return 0;
}

static void __exit my_exit(void) {
		free_irq(num, NULL);
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Andy");
MODULE_DESCRIPTION("andy one-key driver");
MODULE_ALIAS("one-key");


需要交叉编译,然后scp至开发板,通过sudo insmod 来安装,然后sudo dmesg -w
来查看日志,然后就可以触摸按键测试。

可以执行以下命令:

cat  /proc/interrupts |  grep  my_key_driver

来查看中断的具体信息。

欢迎评论交流.

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐