历史上的今天
今天是:2025年04月22日(星期二)
2019年04月22日 | ARM-Linux下的GPIO中断程序
2019-04-22 来源:eefocus
为了调试ARM板上的GPIO引脚中断效果,以便在后续项目使用ARM与ZLG7290按键LED中断芯片连接中随意选择空闲的GPIO引脚来作为ZLG7290的中断信号线,特意编写了一个小的Linux GPIO中断驱动程序下载到开发板上做实验。经验证,这种软件中断方式也还差强人意。下面贴出自己编写的不成熟的代码,见笑(
实验的硬件电路为ARM GPIO的PB17连接一个共阴LED,PB18与PB19连接,PB18由中断驱动设置为低电平触发,PB19由GPIO驱动程序控制,上层应用程序通过驱动控制PB19高低电平变化,从而引发PB18发生中断,中断程序中控制PB17的LED亮和灭。
Linux中断驱动部分:
/*
* PB18_IRQTest.c
* This is a test program for sam9260, using PB19(J5_18 pin) input a signal to PB18(J5_16 pin),
* PB18 receive this signal as IRQ and make the LED linking on PB17((J5_14 pin)) turn on or turn off
*
* @Author: Cun Tian Rui
* @Date :March.18.2011
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void led_on()
{
at91_set_gpio_output(AT91_PIN_PB17,1);
}
void led_off()
{
at91_set_gpio_output(AT91_PIN_PB17 ,0);
}
struct light_dev *light_devp;
int light_major = 200;
struct light_dev
{
struct cdev cdev;
unsigned char value;
};
MODULE_AUTHOR("Cun Tian Rui");
MODULE_LICENSE("Dual BSD/GPL");
static void io_init(void)
{
at91_set_gpio_input(AT91_PIN_PB18, 1);
at91_set_deglitch(AT91_PIN_PB18, 1);
at91_sys_write(1 + PIO_IDR, 1<<18);
at91_sys_write(1 + PIO_IER, (~(1<<18)));
at91_sys_write(AT91_PMC_PCER, 1 << 3);
}
struct gpio_irq_desc
{
int irq;
unsigned long flags;
char *name;
};
static struct gpio_irq_desc PB18_IRQ={AT91_PIN_PB18,AT91_AIC_SRCTYPE_LOW,"PB18"};
static irqreturn_t PB18_intHandle(int irq, void *dev_id)
{
led_on();
return IRQ_RETVAL(IRQ_HANDLED);
}
int light_open(struct inode *inode,struct file *filp)
{
int err;
struct light_dev *dev;
dev = container_of(inode->i_cdev,struct light_dev,cdev);
filp->private_data = dev;
io_init();
err = request_irq(PB18_IRQ.irq,PB18_intHandle,PB18_IRQ.flags,PB18_IRQ.name,(void*)0);
if(err)
{
free_irq(PB18_IRQ.irq,(void*)0);
return -EBUSY;
}
return 0;
}
int light_release(struct inode *inode,struct file *filp)
{
free_irq(PB18_IRQ.irq,(void*)0);
return 0;
}
// ioctl
int light_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,
unsigned long arg)
{
struct light_dev *dev = filp->private_data;
switch(cmd)
{
case 0:
at91_set_gpio_output(AT91_PIN_PB19,0);
break;
case 1:
at91_set_gpio_output(AT91_PIN_PB19,1);
led_off();
break;
default:
return -ENOTTY;
// break;
}
return 0;
}
struct file_operations light_fops =
{
.owner = THIS_MODULE,
.ioctl = light_ioctl,
.open = light_open,
.release = light_release,
};
static void light_setup_cdev(struct light_dev *dev,int index)
{
int err,devno = MKDEV(light_major,index);
cdev_init(&dev->cdev,&light_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &light_fops;
err = cdev_add(&dev->cdev,devno,1);
if(err)
{
printk(KERN_NOTICE "Error %d adding LED%d",err,index);
}
}
int light_init(void)
{
int result;
dev_t dev = MKDEV(light_major,0);
if(light_major)
{
result = register_chrdev_region(dev,1,"PB18_IRQTest");
}
if(result < 0)
{
return result;
}
light_devp = kmalloc(sizeof(struct light_dev),GFP_KERNEL);
if(!light_devp)
{
result = - ENOMEM;
goto fail_malloc;
}
memset(light_devp,0,sizeof(struct light_dev));
light_setup_cdev(light_devp,0);
return 0;
fail_malloc:unregister_chrdev_region(dev,light_devp);
return result;
}
void light_cleanup(void)
{
cdev_del(&light_devp->cdev);
kfree(light_devp);
unregister_chrdev_region(MKDEV(light_major,0),1);
}
module_init(light_init);
module_exit(light_cleanup);
Linux上层应用程序:
#include
//#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc ,char *argv[])
{
int fd;
char input;
fd = open("/dev/PB18_IRQTest",O_RDWR);
if(fd < 0)
{
perror("open PB18_IRQTest device");
return 0;
}
while(1)
{
printf("input 0 to trigger int/n");
scanf("%c",&input);
switch(input)
{
case '0':
ioctl(fd,0,0);
printf("/n");
break;
case '1':
ioctl(fd,1,0);
printf("/n");
break;
default:
printf("/n");
break;
}
}
return 0;
}
由上面的代码可以看出,Linux内核在中断程序处理方面已经做了很多抽象,对于驱动程序编写者只需要按照内核中断构架去实现一定的控制函数就可以,以后有时间会专门撰文剖析还原Linux内核里那些对中断实现的抽象。
上一篇:如何判断外设使用的地址空间
史海拾趣
|
文章以综述的方式概要的介绍了宝钢一、二、三期工程建设中交流调速的应用情况。在分析现场应用各类的基本结构、性能、应用效果、存在的不足以及变频调速的应用给系统带来的电磁兼容问题的基础上。提出了宝钢三期后过程以及一、二期设备改造中交流调 ...… 查看全部问答> |
|
谁有amx中控的编程软件和说明书?我去AMX公司,他们老板说网上下载,可是AMX的网站的下载在维护,不知那位哥们姐们有这块的编程软件和说明书,给个下载地址,谢谢… 查看全部问答> |
|
请问下如何通过CPU,来控制电压的大小? 意思就是说CPU给出如0101...的命令,应该怎么设计电路,或是有什么器件,可以使到这些命令可以控制电路中某个点电压的大小。… 查看全部问答> |
|
我想用LM3S8962驱动VS1003,但是8962的SPI被SD卡和OLED占用了,我打算用GPIO模拟SPI驱动VS1003,我是按照TI 最新的StellarisWare里的SoftSSI配置的GPIO,从icdev下了VS1003的驱动,配置好有没有听到正弦波,检测CLK好像也不对,请高手给指点一下吧 ...… 查看全部问答> |
|
在iar编译工具中,内置了一些内部函数,也就是Intrinsic.h头文件,里面的许多函数有些可以加快编写速度,有些可以指定变量的存放位置,还有些可以实现复杂的功能,但是我也只是了解其中的一些,请问各位谁有内部函数的讲解可以拿出来分享一下,感激 ...… 查看全部问答> |
|
毕业后,找了个测试工作,觉得没前途,于是想抓紧时间学点别的。本人水平有限,听人说这样很好实现,指标要求不高,主要是锻炼一下。找了好多资料,买了个最小系统,和tft屏幕。其他的打算自己制作。但是不知从何处下手。谁给点建议… 查看全部问答> |




