1 说明
zynq 平台,需要用到 pl (FPGA)端发送中断给 ps端(ARM),发送的中断名称为 IRQ_F2P[15:0],该中断一共有16个,中断号分别为 61-68, 84-91。本文针对该中断在linux 环境开,开发驱动,驱动方式采用 uio 模型。
2 开发环境
1、软件环境:ubuntu14.04
vivado:2015.04
2、linux 内核版本:zynq7010黑金开发板配套内核包,linux 版本4.0.0
3、硬件环境:黑金开发板 zynq7010.
3 操作
3.1 PL 部分
3.2 PS 部分
3.2.1 中断号说明
对于zynq 驱动,需要注意:
1、对于SPI中断,则对应到Linux 的中断标号,为芯片datasheet的中断号 -16.
例如中断号为 30,则对应的linux 中断号为 30 -16 = 14.
2、对于非 SPI 中断,则对应的 linux 中断标号,为芯片 datasheet 的中断号 -32.
例如 IRQ_F2P中断,中断号为 61,则对应的 linux 中断号为 61 - 32 = 29.
3.2.2 修改设备树
本文中,使用的中断为 irq_f2p 的中断号 61,那么对应的 linux 中断号为 29 = 0x19。
修改zynq 7010 的设备树文件 AX7010,在dts中,增加uio 中断。
uio@0{
compatible="generic-uio";
status="okay";
interrupt-controller;
interrupt-parent=<0x4>;
interrupts=<0x0 0x1d 0x1>;
};
有些设备树版本不同,需要增加 reg参数,所以uio 的描述多增加一行 reg = <0 0>:
uio@0{
reg = <0 0>
compatible="generic-uio";
status="okay";
interrupt-controller;
interrupt-parent=<0x4>;
interrupts=<0x0 0x1d 0x1>;
};
另外,增加命令行参数,加上 uio的参数 uio_pdrv_genirq.of_id=generic-uio
chosen {
bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=1 uio_pdrv_genirq.of_id=generic-uio";
};
如下是修改后的 dts 文件,一共开了4个uio 中断,因为有一些中断号被占用,故没使用 62 中断:
/dts-v1/;
/ {
#address-cells = <0x1>;
#size-cells = <0x1>;
compatible = "xlnx,zynq-7000";
model = "ALINX-AX7010";
chosen {
bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=1 uio_pdrv_genirq.of_id=generic-uio";
};
aliases {
serial0 = "/amba/serial@e0001000";
ethernet0 = "/amba/ethernet@e000b000";
spi0 = "/amba/spi@e000d000";
};
memory {
device_type = "memory";
reg = <0x0 0x20000000>;
};
cpus {
#address-cells = <0x1>;
#size-cells = <0x0>;
cpu@0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0x0>;
clocks = <0x1 0x3>;
clock-latency = <0x3e8>;
cpu0-supply = <0x2>;
operating-points = <0x9eb10 0xf4240 0x4f588 0xf4240>;
};
cpu@1 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0x1>;
clocks = <0x1 0x3>;
};
};
pmu {
compatible = "arm,cortex-a9-pmu";
interrupts = <0x0 0x5 0x4 0x0 0x6 0x4>;
interrupt-parent = <0x3>;
reg = <0xf8891000 0x1000 0xf8893000 0x1000>;
};
fixedregulator@0 {
compatible = "regulator-fixed";
regulator-name = "VCCPINT";
regulator-min-microvolt = <0xf4240>;
regulator-max-microvolt = <0xf4240>;
regulator-boot-on;
regulator-always-on;
linux,phandle = <0x2>;
phandle = <0x2>;
};
amba {
compatible = "simple-bus";
#address-cells = <0x1>;
#size-cells = <0x1>;
interrupt-parent = <0x3>;
ranges;
//u-boot,dm-pre-reloc;
adc@f8007100 {
compatible = "xlnx,zynq-xadc-1.00.a";
reg = <0xf8007100 0x20>;
interrupts = <0x0 0x7 0x4>;
interrupt-parent = <0x3>;
clocks = <0x1 0xc>;
};
can@e0008000 {
compatible = "xlnx,zynq-can-1.0";
status = "disabled";
clocks = <0x1 0x13 0x1 0x24>;
clock-names = "can_clk", "pclk";
reg = <0xe0008000 0x1000>;
interrupts = <0x0 0x1c 0x4>;
interrupt-parent = <0x3>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
can@e0009000 {
compatible = "xlnx,zynq-can-1.0";
status = "disabled";
clocks = <0x1 0x14 0x1 0x25>;
clock-names = "can_clk", "pclk";
reg = <0xe0009000 0x1000>;
interrupts = <0x0 0x33 0x4>;
interrupt-parent = <0x3>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
gpio@e000a000 {
compatible = "xlnx,zynq-gpio-1.0";
#gpio-cells = <0x2>;
clocks = <0x1 0x2a>;
gpio-controller;
interrupt-parent = <0x3>;
interrupts = <0x0 0x14 0x4>;
reg = <0xe000a000 0x1000>;
emio-gpio-width = <0x40>;
gpio-mask-high = <0x0>;
gpio-mask-low = <0x5600>;
linux,phandle = <0x6>;
phandle = <0x6>;
};
i2c@e0004000 {
compatible = "cdns,i2c-r1p10";
status = "okay";
clocks = <0x1 0x26>;
interrupt-parent = <0x3>;
interrupts = <0x0 0x19 0x4>;
reg = <0xe0004000 0x1000>;
#address-cells = <0x1>;
#size-cells = <0x0>;
clock-frequency = <0x61a80>;
};
i2c@e0005000 {
compatible = "cdns,i2c-r1p10";
status = "okay";
clocks = <0x1 0x27>;
interrupt-parent = <0x3>;
interrupts = <0x0 0x30 0x4>;
reg = <0xe0005000 0x1000>;
#address-cells = <0x1>;
#size-cells = <0x0>;
clock-frequency = <0x61a80>;
linux,phandle = <0x8>;
phandle = <0x8>;
edt_ft5x0