下图所示为zynq的pl工程图,请注意途中画蓝色框内,在图一左侧的蓝色框内,请在vivado约束条件中设置irq[0:0]与板子上的按键连接具体约束条件见。在右侧蓝框内的xlconcat_0中,由于In0[0:0]连接别的设备,In1[0:0]连接外部按键,故In0[0:0]的中断号为61,In1[0:0]的中断号为62。图二是将中断连接到zynq的IRQ_F2P[1:0]中。
图一:
图二:
其中interrupts = <0 32 2>;内的0代表的是SPI中断,32对应的中断号,2代表中断触发方式为下降沿触发。触发方式一共有4中,分别是上升沿触发(1),下降沿触发(2),高电平触发(4),低电平触发(8)。
// An highlighted block
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include /* error codes */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//
static char devname[16];
static int major;
static int mijor;
static struct class* cls;
static void __iomem* base_address;
static resource_size_t remap_size;
static int irq;
static struct device* dev;
#define DEVICE_NAME "irq_drv"
static volatile int irq_is_open = 0;
static struct fasync_struct *irq_async;
static int irq_drv_open(struct inode *Inode, struct file *File)
{
irq_is_open = 1;
return 0;
}
int irq_drv_release (struct inode *inode, struct file *file)
{
irq_is_open = 0;
return 0;
}
static ssize_t irq_drv_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
return 0;
}
static ssize_t irq_drv_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
return 0;
}
static int irq_drv_fasync (int fd, struct file *filp, int on)
{
return fasync_helper (fd, filp, on, &irq_async);
}
static struct file_operations irq_fops = {
.owner = THIS_MODULE,
.open = irq_drv_open,
.read = irq_drv_read,
.write = irq_drv_write,
.fasync = irq_drv_fasync,
.release = irq_drv_release,
};
static irqreturn_t irq_interrupt(int irq, void *dev_id)
{
printk("irq = %d\n", irq);
if(irq_is_open)
{
kill_fasync (&irq_async, SIGIO, POLL_IN);
}
return IRQ_HANDLED;
}
static int irq_probe(struct platform_device *pdev)
{
int err;
struct device *tmp_dev;
memset(devname,0,16);
strcpy(devname, DEVICE_NAME);
major = register_chrdev(0, devname, &irq_fops);
cls = class_create(THIS_MODULE, devname);
mijor = 1;
tmp_dev = device_create(cls, &pdev->dev, MKDEV(major, mijor), NULL, devname);
if (IS_ERR(tmp_dev)) {
class_destroy(cls);
unregister_chrdev(major, devname);
return 0;
}
irq = platform_get_irq(pdev,0);
if (irq <= 0)
return -ENXIO;
dev = &pdev->dev;
err = request_threaded_irq(irq, NULL,
irq_interrupt,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
devname, NULL);
if (err) {
printk(KERN_ALERT "irq_probe irq error=%d\n", err);
goto fail;
}
else
{
printk("irq = %d\n", irq);
printk("devname = %s\n", devname);
}
//保存dev
//platform_set_drvdata(pdev, &xxx);
return 0;
fail:
free_irq(irq, NULL);
device_destroy(cls, MKDEV(major, mijor));
class_destroy(cls);
unregister_chrdev(major, devname);
return -ENOMEM;
}
static int irq_remove(struct platform_device *pdev)
{
device_destroy(cls, MKDEV(major, mijor));
class_destroy(cls);
unregister_chrdev(major, devname);
free_irq(irq, NULL);
printk("irq = %d\n", irq);
return 0;
}
static int irq_suspend(struct device *dev)
{
return 0;
}
static int irq_resume(struct device *dev)
{
return 0;
}
static const struct dev_pm_ops irq_pm_ops = {
.suspend = irq_suspend,
.resume = irq_resume,
};
//MODULE_DEVICE_TABLE(platform, irq_driver_ids);
static const struct of_device_id irq_of_match[] = {
{.compatible = "hello,irq" },
{ }
};
MODULE_DEVICE_TABLE(of, irq_of_match);
static struct platform_driver irq_driver = {
.probe = irq_probe,
.remove = irq_remove,
.driver = {
.owner = THIS_MODULE,
.name = "irq@0",
.pm = &irq_pm_ops,
.of_match_table = irq_of_match,
},
};
// An highlighted block
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// 信号处理函数
void my_signal_fun(int signum)
{
printf("sigal number = %d\n", signum);
}
int main(int argc, char *argv[])
{
unsigned char key_val;
int ret;
int Oflags;
// 在应用程序中捕捉SIGIO信号(由驱动程序发送)
signal(SIGIO, my_signal_fun);
int fd = open("/dev/irq_drv", O_RDWR);
if (fd < 0)
{
printf(">>can't open file!\n");
}
fcntl(fd, F_SETOWN, getpid());
Oflags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, Oflags | FASYNC);
while (1)
{
sleep(1000);
}
return 0;
}
axi_gpio我已经学习了一段时间,由于对FPGA不是特别熟悉,所以走了一些弯路,后面写一些经验体会吧,希望能给大家有所帮助。