本帖最后由 LINUX课程 于 2024-9-11 10:35 编辑
软件版本:vitis2021.1(vivado2021.1) 操作系统:WIN10 64bit 硬件平台:适用XILINX Z7/ZU系列FPGA
1 概述 PL到PS的中断是ARM和FPGA交互中非常重要的一项功能。PS的中断控制器及时响应PL的中断,以通知CPU及时处理。本文通过按键输入,模拟中断信号的参数,通过简单的实验掌握PL到PS中断使用。然后在后续很多demo中,我们都会遇到PL到PS中断使用。虽然本文只用到了PL中断,但是在本文的第二下节,我们会对ZYNQ MPSOC的中断资源做一个简要介绍。 本文实验目的: - 熟悉ZYNQ MPSOC的中断资源,并且重点掌握PL-PS的中断资源
- 搭建由FPGA按键输入模拟PL中断产生的的SOC工程
- 编写PL中断测试验证程序
2 系统框图 3 PL中断资源简介 共有16个PL到PS中断通过Shared Peripheral Interrupts接入到CPU. PL-PS的中断资源分2组,第1组的中断号为68~61;第2组的中断号为15~8 4 搭建SOC系统工程 详细的搭建过程这里不再重复,对于初学读者如果还不清楚如何创建SOC工程的,请学习“01Vitis Soc开发入门”这篇文章。 4.1 SOC系统工程 4.2 编译并导出平台文件 以下步骤简写,有不清楚的看“[米联客-XILINX-H3_CZ08_7100] LINUX基础篇连载-04 从vitis移植Ubuntu实现二次开发”。 1:打开soc_prj内工程。 2:生成Bit文件。 3:导出到硬件: FileExport HardwareInclude bitstream 4:导出完成后,对应工程路径的soc_hw路径下有硬件平台文件:system_wrapper.xsa的文件。根据硬件平台文件system_wrapper.xsa来创建需要Platform平台。 5:打开vitis,并添加设备树模板。 6:创建工程文件,选择device tree创建,创建完成后编译工程。 7:获得设备树以及启动文件,打开虚拟机将文件拷贝到开发包的指定位置。 4.3 设备树修改及驱动编译 1:设备树修改 本章vitis不会生成任何有用的设备树,所以需要手动添加,另外soc_dts内有写好的设备树,若不熟可以参考。设备树的修改如下: 添加的设备如下: - plint {
- compatible = "milianke,plint";
- interrupt-parent = <&intc>;
- interrupts = <0 29 4>; // 61 - 32
- };
复制代码compatible字段用来匹配驱动,而interrupts为中断号。 第一位的中断号为 61,在Linux使用中断号时。实际要减去32,即fdma的中断号为 29。 2:编译系统 拷贝上一步写好的设备树到指定路径,拷贝其他文件后,编译uboot,编译kernel,制作镜像并烧录系统。具体步骤参考“[米联客-XILINX-H3_CZ08_7100] LINUX基础篇连载-04 从vitis移植Ubuntu实现二次开发”。 3:编译驱动 将对应的demo拷贝至/home/uisrc下,同时确保/home/uisrc下有软件开发包uisrc-lab-xlnx。 进入demo的路径,使用make编译驱动。 其中.ko结尾的文件为我们编译出来的驱动。 4:拷贝程序 将对应的文件拷贝至sd卡上: 5 程序分析 - #include <linux/module.h>
- #include <linux/interrupt.h>
- #include <linux/of_platform.h>
- struct PLInt
- {
- int irq;
- };
- struct PLInt *PLInt_data;
- static irqreturn_t pl_irq_handler(int irq, void *data)
- {
- printk(KERN_CRIT "plbutton\n");
- return IRQ_HANDLED;
- }
- int of_PLInt_data(struct PLInt *pdata, struct platform_device *pdev)
- {
- pdata->irq = platform_get_irq(pdev, 0);
- if (pdata->irq < 0)
- {
- printk("[err]unable get irq.\n");
- return -1;
- }
- printk("irq: %d\n", pdata->irq);
- return 0;
- }
- static int PLInt_probe(struct platform_device *pdev)
- {
- int ret = 0;
- struct device *dev = &pdev->dev;
- struct PLInt *pdata = dev_get_platdata(dev);
- if (!pdata)
- {
- pdata = devm_kzalloc(dev, sizeof(struct PLInt), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
- platform_set_drvdata(pdev, pdata);
- }
- ret = of_PLInt_data(pdata, pdev);
- PLInt_data = pdata;
- ret = request_irq(PLInt_data->irq, pl_irq_handler, IRQF_TRIGGER_RISING, "PLInt", PLInt_data);
- return ret;
- }
- static int PLInt_remove(struct platform_device *pdev)
- {
- free_irq(PLInt_data->irq, PLInt_data);
- return 0;
- }
- static struct of_device_id PLInt_of_match[] = {
- {.compatible = "milianke,plint"},
- {},
- };
- static struct platform_driver PLInt_device_driver = {
- .driver = {
- .name = "PLInt",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(PLInt_of_match),
- },
- .probe = PLInt_probe,
- .remove = PLInt_remove,
- };
- static int __init PLInt_init(void)
- {
- return platform_driver_register(&PLInt_device_driver);
- }
- static void __exit PLInt_exit(void)
- {
- platform_driver_unregister(&PLInt_device_driver);
- }
- late_initcall(PLInt_init);
- module_exit(PLInt_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("uisrc");
复制代码行64,调用行55~58代码,与设备树的compatible字段匹配。 行20~47,驱动初始化函数,需要读取设备树的中断号,并使用中断号申请中断。 行49~53,驱动注销函数,主要用来释放中断。 行17~27,获取设备树中的中断号。 行11~15,中断回调函数。 6 演示结果 6.1 硬件准备 将SD卡插入板卡。 SD2.0 启动 01 而模式开关为 ON OFF(7100 需要先将系统烧录进qspi,然后才能从qspi启动sd卡,“[米联客-XILINX-H3_CZ08_7100] LINUX基础篇连载-04 从vitis移植Ubuntu实现二次开发”) 将 PS 端串口线连接电脑,如果要使用 ssh 登录,将网口线同样连接至电脑,最后给开发板通电。每次重新上电,需要重新插拔 PS 串口,否则会登录失败。 接入12V直流电源开机。 6.2 实验结果 登录板卡后,ls找到刚才拷贝进来的驱动文件,运行sudo insmod plint.ko装载驱动: 按下配套开发板上的PL 输入按键: 输出结果如下: 按几次就会输出几次plbutton。 |