基于ARM A53开发板,使用按键中断及中断底半部实现《led灯状态取反》的驱动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include<linux/interrupt.h>
//GIPO口的初始化
#define GPIO(m,n) m*32+n
#define GPIOA28 GPIO(0,28)
#define GPIOB12 GPIO(1,12)
#define GPIOE13 GPIO(4,13)
#define GPIOB8 GPIO(1,8)
#define GPIOB16 GPIO(1,16)
int irqno[2] = {GPIOB8,GPIOB16};
int gpiono[] = {GPIOA28,GPIOB12,GPIOE13};
//延时工作队列定义结构体
struct delayed_work dwork;
//中断底板部处理函数 延时
void myfunc(struct work_struct *work){
printk("%s : %s : %d\n",__FILE__,__func__,__LINE__);
schedule_delayed_work(&dwork,msecs_to_jiffies(1000));
}
//中断处理函数
irqreturn_t my_irq_handler(int irq, void *dev){
//红灯GPIO口状态获取、取反、及设置回填
int red_statu = gpio_get_value(GPIOA28);
red_statu = red_statu ? 0:1;
gpio_set_value(GPIOA28,red_statu);
//调用执行中断底板部处理函数
schedule_delayed_work(&dwork,0);
return IRQ_HANDLED;
}
//入口初始化函数
static int __init work_timer_init(void){
int i,ret;
//释放系统占用的gpio口
for(i=0; i<ARRAY_SIZE(gpiono); i++){
gpio_free(gpiono[i]);
}
//申请GPIO口(本实验只用红灯)
for(i = 0;i<ARRAY_SIZE(gpiono);i++){
ret = gpio_request(gpiono[i],NULL);
if(ret){
printk("gpio_request %d error",gpiono[i]);
return ret;
}
//输出方向
gpio_direction_output(gpiono[i],0);
}
//中断申请 两个按键
for(i=0;i<ARRAY_SIZE(irqno);i++){
ret = request_irq(gpio_to_irq(irqno[i]),my_irq_handler, IRQF_TRIGGER_FALLING,NULL, NULL);
if(ret){
printk("request_irq error");
return ret;
}
}
//延时工作队列初始化对象
INIT_DELAYED_WORK(&dwork,myfunc);
return 0;
}
//出口注销申请资源
static void __exit work_timer_exit(void){
int i;
for(i=0; i<ARRAY_SIZE(gpiono); i++){
gpio_free(gpiono[i]);
}
for(i=0;i<ARRAY_SIZE(irqno);i++)
{
free_irq(gpio_to_irq(irqno[i]), NULL);
}
cancel_delayed_work_sync(&dwork);
}
module_init(work_timer_init);
module_exit(work_timer_exit);
MODULE_LICENSE("GPL");