11 100ASK_T113-PRO 利用设备树测试GPIO中断实验(PE12)
【代码】11 100ASK_T113-PRO 利用设备树测试GPIO中断实验(PE12)
·
1.原理图
2.设备树代码
pe12_gpio_interrupts {
compatible = "allwinner,sunxi-pinctrl-test";
pinctrl-names = "default";
key-gpios = <&pio PE 12 GPIO_ACTIVE_HIGH>;
status = "okay";
interrupt-parent = <&pio>; /* 指定中断控制器 */
interrupts = <&pio PE 12 IRQ_TYPE_LEVEL_LOW>;
};
3.驱动代码
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/of_irq.h>
#include <linux/irq.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define PE12_IRQ_NAME "pe12_irq" /* 名字 */
#define KEY0VALUE 0X01 /* KEY0按键值 */
#define INVAKEY 0XFF /* 无效的按键值 */
#define KEY_NUM 1 /* 按键数量 */
/* 中断IO描述结构体 */
struct irq_keydesc {
int gpio; /* gpio */
int irqnum; /* 中断号 */
unsigned char value; /* 按键对应的键值 */
char name[10]; /* 名字 */
irqreturn_t (*handler)(int, void *); /* 中断服务函数 */
};
/* imx6uirq设备结构体 */
struct pe12_dev{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
int minor; /* 次设备号 */
struct device_node *nd; /* 设备节点 */
atomic_t keyvalue; /* 有效的按键键值 */
atomic_t releasekey; /* 标记是否完成一次完成的按键,包括按下和释放 */
struct timer_list timer;/* 定义一个定时器*/
struct irq_keydesc irqkeydesc; /* 按键描述数组 */
unsigned char curkeynum; /* 当前的按键号 */
};
struct pe12_dev pe12_irq; /* irq设备 */
/* @description : 中断服务函数,开启定时器,延时10ms,
* 定时器用于按键消抖。
* @param - irq : 中断号
* @param - dev_id : 设备结构。
* @return : 中断执行结果
*/
static irqreturn_t key0_handler(int irq, void *dev_id)
{
// 清除中断标志位,具体清除方式需根据芯片手册确认
// 这里假设读取GPIO状态可自动清除标志位
int pe12_state = gpio_get_value(pe12_irq.irqkeydesc.gpio);
printk(KERN_INFO "PE12 GPID IRQ: %d\n", pe12_state);
// 在这里可以添加具体的业务逻辑处理
// 比如根据状态执行不同操作等
return IRQ_HANDLED;
}
/*
* @description : 驱动入口函数
* @param : 无
* @return : 无
*/
static int __init pe12_irq_init(void)
{
unsigned char i = 0;
int ret = 0;
pe12_irq.nd = of_find_node_by_path("/pe12_gpio_interrupts");
if (pe12_irq.nd== NULL)
{
printk("key node not find!\r\n");
return -EINVAL;
}
else;
pe12_irq.irqkeydesc.gpio = of_get_named_gpio(pe12_irq.nd ,"key-gpios", 0);
if (pe12_irq.irqkeydesc.gpio < 0)
{
printk("can't get key-gpios%d\r\n", i);
}
// 初始化key所使用的IO,并且设置成中断模式
//memset(pe12_irq.irqkeydesc[i].name, 0, sizeof(pe12_irq.irqkeydesc[i].name)); //缓冲区清零
//sprintf(pe12_irq.irqkeydesc[i].name, "KEY%d", i); /* 组合名字 */
//gpio_request(pe12_irq.irqkeydesc.gpio, "PE 12 IRQ");
//gpio_direction_input(pe12_irq.irqkeydesc.gpio);
//pe12_irq.irqkeydesc.irqnum = irq_of_parse_and_map(pe12_irq.nd, 0);
//#if 0
pe12_irq.irqkeydesc.irqnum = gpio_to_irq(pe12_irq.irqkeydesc.gpio);
//#endif
printk("key:gpio=%d, irqnum=%d\r\n", pe12_irq.irqkeydesc.gpio,pe12_irq.irqkeydesc.irqnum);
// 申请中断
ret = request_irq(pe12_irq.irqkeydesc.irqnum, key0_handler,
IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING, "PE 12 GPIO_IRQ", &pe12_irq);
if(ret < 0)
{
printk("irq %d request failed!\r\n", pe12_irq.irqkeydesc.irqnum);
return -EFAULT;
}
return 0;
}
/*
* @description : 驱动出口函数
* @param : 无
* @return : 无
*/
static void __exit pe12_irq_exit(void)
{
unsigned int i = 0;
// 删除定时器
//del_timer_sync(&imx6uirq.timer); /* 删除定时器 */
// 释放中断
free_irq(pe12_irq.irqkeydesc.irqnum, &pe12_irq);
gpio_free(pe12_irq.irqkeydesc.gpio);
cdev_del(&pe12_irq.cdev);
unregister_chrdev_region(pe12_irq.devid, 1);
device_destroy(pe12_irq.class, pe12_irq.devid);
class_destroy(pe12_irq.class);
}
module_init(pe12_irq_init);
module_exit(pe12_irq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zuozhongkai");
4.测试
更多推荐
所有评论(0)