linux按键中断点灯——imx6ull

韦东山老师视频地址

修改设备树

在根节点添加以下节点

    my_led{
        compatible="ss,led";
        pinctrl-names = "default";
        pinctrl-0 = <&my_pinctrl_leds>;
        led-gpios= < &gpio5 3 GPIO_ACTIVE_LOW>;
    };

    ss_key{
        compatible="ss,key";
        pinctrl-names = "default";
        pinctrl-0 = <&ss_key1_pinctrl &ss_key2_pinctrl>;

        key-gpios=<&gpio5 1  GPIO_ACTIVE_HIGH
                   &gpio4 14 GPIO_ACTIVE_HIGH>;
     };

驱动文件keydrv.c

入口函数和praform_driver


static const struct of_device_id ss_key_match[] = {
	{ .compatible = "ss,key", },
	{}
};

static struct  platform_driver ss_key_driver={
    .probe=key_probe,
    .remove=key_remove,
    .driver={
        .name="ss,key",
        .owner=THIS_MODULE,
        .of_match_table=ss_key_match,
    }
};

static int __init ss_key_init(void){
    return platform_driver_register(&ss_key_driver);
}

static void __exit ss_key_exit(void){
    platform_driver_unregister(&ss_key_driver);
}

module_init(ss_key_init);
module_exit(ss_key_exit);
MODULE_LICENSE("GPL");

probe和remove

static int  key_probe(struct platform_device *ppdev){
    int i;
    int error;
    count=gpiod_count(&(ppdev->dev),"key");//获取gpio引脚个数

    for(i=0;i<count;++i){
        //依次获取引脚描述符,并设置为输入模式
        key_gpio_desc[i]= gpiod_get_index(&(ppdev->dev),"key",i,GPIOD_IN);
        //获取中断号
        irqs[i]=gpiod_to_irq(key_gpio_desc[i]);
         //申请中断号
        error = request_irq(irqs[i], ss_key_irq,
                IRQF_TRIGGER_FALLING,
				"ss_key", key_gpio_desc[i]);
    }
    return 0;
}

static int  key_remove(struct platform_device *ppdev){
    int i;
    for(i=0;i<count;++i){
        //释放中断
        free_irq(irqs[i],key_gpio_desc[i]);
        gpiod_put(key_gpio_desc[i]);  //释放描述符
    }
    return 0;
}

中断函数

static irqreturn_t ss_key_irq(int irq, void *dev_id){
    struct  gpio_desc *p_desc=dev_id;
    //获取逻辑电平
    int value=gpiod_get_value(p_desc);

    printk("key %d is %d\n",irq,value);

    switch (irq)
    {
    case 189:
        //该函数在leddrv.c中定义
        turn_led(1);
        break;
    case 208:
        turn_led(0);
        break;
    default:
        break;
    }

    return IRQ_HANDLED;
}

驱动文件leddrv.c

添加接口供keydrv.c调用

void turn_led(int state){
    //设置引脚为输出,并初始化为state逻辑电平
    gpiod_direction_output(led_gpio_desc,state);
}
EXPORT_SYMBOL_GPL(turn_led);

request_irq

static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
	    const char *name, void *dev)
{
	return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}

        irq是终端号,handler是中断函数,flags是出发方式,有低电平触发,高电平触发,下降沿触发,上升沿触发,name是设置中断的名字,dev是传给中断函数的参数。

#define IRQF_TRIGGER_NONE	0x00000000
#define IRQF_TRIGGER_RISING	0x00000001
#define IRQF_TRIGGER_FALLING	0x00000002
#define IRQF_TRIGGER_HIGH	0x00000004
#define IRQF_TRIGGER_LOW	0x00000008
#define IRQF_TRIGGER_MASK	(IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \
				 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)
#define IRQF_TRIGGER_PROBE	0x00000010

free_irq

void free_irq(unsigned int irq, void *dev_id)

           irq是终端号,dev_id是传给中断函数的参数,与request_irq中的dev一样

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值