标志
|
功能 |
IRQF_SHARED |
多个设备共享一个中断线,共享的所有中断都必须指
定此标志。如果使用共享中断的话, request_irq 函数的 dev 参数就是唯一区分他们的标志。
|
IRQF_ONESHOT
|
单次中断,中断执行一次就结束。 |
IRQF_TRIGGER_NONE | 无触发。 |
IRQF_TRIGGER_RISING | 上升沿触发。 |
IRQF_TRIGGER_FALLING | 下降沿触发。 |
IRQF_TRIGGER_HIGH | 高电平触发。 |
IRQF_TRIGGER_LOW | 低电平触发。 |
1 gpio5 : gpio @020ac000{
2 compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
3 reg = <0x020ac000 0x4000>;
4 interrupts = , ;
5 gpio-controller;
6 #gpio-cells = <2>;
7 interrupt-controller;
8 #interrupt-cells = <2>;
9 };
第 4 行,interrupts 描述中断源信息,对于 gpio5 来说一共有两条信息,中断类型都是 SPI,触发电平都是 IRQ_TYPE_LEVEL_HIGH。不同之处在于中断源,一个是 74,一个是 75。
#include
#include
#include
#include
#include
#include
#include
#include
#include
//定义结构体表示我们的节点
struct device_node *test_device_node;
struct property *test_node_property;
//要申请的中断号
int irq;
// GPIO 编号
int gpio_nu;
/*** @description: 中断处理函数 test_key
* @param {int} irq :要申请的中断号
* @param {void} *args :
* @return {*}IRQ_HANDLED
*/
irqreturn_t test_key(int irq, void *args)
{
printk("test_key \n");
return IRQ_RETVAL(IRQ_HANDLED);
}
/******************************************************************************
* @brief beep_probe : 与设备信息层(设备树)匹配成功后自动执行此函数,
* @param inode : 文件索引
* @param file : 文件
* @return 成功返回 0
******************************************************************************/
int beep_probe(struct platform_device *pdev)
{
int ret = 0;
// 打印匹配成功进入 probe 函数
printk("beep_probe\n");
// of_find_node_by_path 函数通过路径查找节点,/test_key 是设备树下的节点路径
test_device_node = of_find_node_by_path("/test_key");
if (test_device_node == NULL)
{
//查找节点失败则打印信息
printk("of_find_node_by_path is error \n");
return -1;
}
//of_get_named_gpio 函数获取 GPIO 编号
gpio_nu = of_get_named_gpio(test_device_node, "gpios", 0);
if (gpio_nu < 0)
{
printk("of_get_namd_gpio is error \n");
return -1;
}
//设置 GPIO 为输入模式
gpio_direction_input(gpio_nu);
//获取 GPIO 对应的中断号
// irq = gpio_to_irq(gpio_nu);
irq =irq_of_parse_and_map(test_device_node,0);
printk("irq is %d \n", irq);
/*申请中断,irq:中断号名字
test_key:中断处理函数
IRQF_TRIGGER_RISING:中断标志,意为上升沿触发
"test_key":中断的名字
*/
ret = request_irq(irq, test_key, IRQF_TRIGGER_RISING, "test_key", NULL);
if (ret < 0)
{
printk("request_irq is error \n");
return -1;
}
return 0;
}
int beep_remove(struct platform_device *pdev)
{
printk("beep_remove\n");
return 0;
}
const struct platform_device_id beep_idtable = {
.name = "keys",
};
const struct of_device_id of_match_table_test[] = {
{.compatible = "keys"},
{},
};
struct platform_driver beep_driver = {
//3. 在 beep_driver 结构体中完成了 beep_probe 和 beep_remove
.probe = beep_probe,
.remove = beep_remove,
.driver = {
.owner = THIS_MODULE,
.name = "beep_test",
.of_match_table = of_match_table_test},
//4 .id_table 的优先级要比 driver.name 的优先级要高,优先与.id_table 进行匹配
.id_table = &beep_idtable};
/**
* @description: 模块初始化函数
* @param {*}
* @return {*}
*/
static int beep_driver_init(void)
{
//1.我们看驱动文件要从 init 函数开始看
int ret = 0;
//2.在 init 函数里面注册了 platform_driver
ret = platform_driver_register(&beep_driver);
if (ret < 0)
{
printk("platform_driver_register error \n");
}
printk("platform_driver_register ok \n");
return 0;
}
/**
* @description: 模块卸载函数
* @param {*}
* @return {*}
*/
static void beep_driver_exit(void)
{
free_irq(irq, NULL);
platform_driver_unregister(&beep_driver);
printk("gooodbye! \n");
}
module_init(beep_driver_init);
module_exit(beep_driver_exit);
MODULE_LICENSE("GPL");