史上最简单的TinkerBoard 2s RK339 GPIO 按键驱动以及嵌入式linux中断编程入门
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_LOW,
"hahahhaha", 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
来查看日志,然后就可以触摸按键测试。
欢迎评论交流.