在LC480T上部署xapp1052

实验环境:LC480T加速卡

开发环境:windows11+vivado2020
运行环境:ubuntu22.04
硬件电路:LC480T加速卡(xc7k480tffg1156-2)
vivado工程文件下载:https://download.csdn.net/download/xiaolangyangyang/91349686
驱动及应用代码下载:https://download.csdn.net/download/xiaolangyangyang/91349692
LC480T引脚说明下载:https://download.csdn.net/download/xiaolangyangyang/91350582
xapp1052_xbmd寄存器说明下载:https://download.csdn.net/download/xiaolangyangyang/91350584

一、说明

        xilinx官网xapp1052例程是基于Kintex-7 KC705 Evaluation Platform (xc7k325tffg900-2)开发板,使用7 Series FPGAs Integrated Block for PCI Express ip核,如果直接将项目修改成device为xc7k480tffg1156-2生成bit文件过程会报错,所以重新构建工程,将官网xapp1052例程的xbmd文件夹拷贝到工程,修改顶层文件及约束文件,生成bit文件。

        xilinx官网xapp1052例程软件基于Fedora-10操作系统,内核很旧,代码在ubuntu22.04上编译不过,所以考虑从新编写驱动及应用代码。

二、构建vivado项目并生成bin文件

        打开工程,生成bit即可,约束文件如下:

##-----------------------------------------------------------------------------
##
## (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved.
##
## This file contains confidential and proprietary information
## of Xilinx, Inc. and is protected under U.S. and
## international copyright and other intellectual property
## laws.
##
## DISCLAIMER
## This disclaimer is not a license and does not grant any
## rights to the materials distributed herewith. Except as
## otherwise provided in a valid license issued to you by
## Xilinx, and to the maximum extent permitted by applicable
## law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
## WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
## AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
## BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
## INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
## (2) Xilinx shall not be liable (whether in contract or tort,
## including negligence, or under any other theory of
## liability) for any loss or damage of any kind or nature
## related to, arising under or in connection with these
## materials, including for any direct, or any indirect,
## special, incidental, or consequential loss or damage
## (including loss of data, profits, goodwill, or any type of
## loss or damage suffered as a result of any action brought
## by a third party) even if such damage or loss was
## reasonably foreseeable or Xilinx had been advised of the
## possibility of the same.
##
## CRITICAL APPLICATIONS
## Xilinx products are not designed or intended to be fail-
## safe, or for use in any application requiring fail-safe
## performance, such as life-support or safety devices or
## systems, Class III medical devices, nuclear facilities,
## applications related to the deployment of airbags, or any
## other applications that could lead to death, personal
## injury, or severe property or environmental damage
## (individually and collectively, "Critical
## Applications"). Customer assumes the sole risk and
## liability of any use of Xilinx products in Critical
## Applications, subject only to applicable laws and
## regulations governing limitations on product liability.
##
## THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
## PART OF THIS FILE AT ALL TIMES.
##
##-----------------------------------------------------------------------------
## Project    : Series-7 Integrated Block for PCI Express
## File       : xilinx_pcie_7x_ep_x8g2.xdc
## Version    : 3.3
#
###############################################################################
# User Configuration 
# Link Width   - x8
# Link Speed   - gen2
# Family       - kintex7
# Part         - xc7k480t
# Package      - ffg1156
# Speed grade  - -2
# PCIe Block   - X0Y0
###############################################################################
#
###############################################################################
# User Time Names / User Time Groups / Time Specs
##############################################################################################################################################################
# User Physical Constraints
##############################################################################################################################################################
# Pinout and Related I/O Constraints
################################################################################
# SYS reset (input) signal.  The sys_reset_n signal should be
# obtained from the PCI Express interface if possible.  For
# slot based form factors, a system reset signal is usually
# present on the connector.  For cable based form factors, a
# system reset signal may not be available.  In this case, the
# system reset signal must be generated locally by some form of
# supervisory circuit.  You may change the IOSTANDARD and LOC
# to suit your requirements and VCCO voltage banking rules.
# Some 7 series devices do not have 3.3 V I/Os available.
# Therefore the appropriate level shift is required to operate
# with these devices that contain only 1.8 V banks.
#set_property PULLUP true [get_ports sys_rst_n]###############################################################################
# Physical Constraints
###############################################################################
#
# SYS clock 100 MHz (input) signal. The sys_clk_p and sys_clk_n
# signals are the PCI Express reference clock. Virtex-7 GT
# Transceiver architecture requires the use of a dedicated clock
# resources (FPGA input pins) associated with each GT Transceiver.
# To use these pins an IBUFDS primitive (refclk_ibuf) is
# instantiated in user's design.
# Please refer to the Virtex-7 GT Transceiver User Guide
# (UG) for guidelines regarding clock resource selection.
#set_property LOC IBUFDS_GTE2_X0Y9 [get_cells refclk_ibuf]###############################################################################
# Timing Constraints
###############################################################################
#
create_clock -name sys_clk -period 10 [get_ports sys_clk_p]
#
# 
set_false_path -to [get_pins {pcie_7x_0_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/S0}]
set_false_path -to [get_pins {pcie_7x_0_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/S1}]
#
#
create_generated_clock -name clk_125mhz_x0y0 [get_pins pcie_7x_0_support_i/pipe_clock_i/mmcm_i/CLKOUT0]
create_generated_clock -name clk_250mhz_x0y0 [get_pins pcie_7x_0_support_i/pipe_clock_i/mmcm_i/CLKOUT1]
create_generated_clock -name clk_125mhz_mux_x0y0 \ -source [get_pins pcie_7x_0_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/I0] \-divide_by 1 \[get_pins pcie_7x_0_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/O]
#
create_generated_clock -name clk_250mhz_mux_x0y0 \ -source [get_pins pcie_7x_0_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/I1] \-divide_by 1 -add -master_clock [get_clocks -of [get_pins pcie_7x_0_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/I1]] \[get_pins pcie_7x_0_support_i/pipe_clock_i/pclk_i1_bufgctrl.pclk_i1/O]
#
set_clock_groups -name pcieclkmux -physically_exclusive -group clk_125mhz_mux_x0y0 -group clk_250mhz_mux_x0y0#
# Timing ignoring the below pins to avoid CDC analysis, but care has been taken in RTL to sync properly to other clock domain.
#
#
##############################################################################
# Tandem Configuration Constraints
###############################################################################set_false_path -from [get_ports sys_rst_n]set_property PACKAGE_PIN J8 [get_ports sys_clk_p]
set_property IOSTANDARD LVCMOS33 [get_ports sys_rst_n]
set_property PACKAGE_PIN Y26 [get_ports sys_rst_n]set_property LOC GTXE2_CHANNEL_X0Y23 [get_cells {pcie_7x_1_support_i/pcie_7x_1_i/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[0].gt_wrapper_i/gtx_channel.gtxe2_channel_i}]
set_property PACKAGE_PIN F2 [get_ports {pci_exp_txp[0]}]
set_property LOC GTXE2_CHANNEL_X0Y22 [get_cells {pcie_7x_1_support_i/pcie_7x_1_i/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[1].gt_wrapper_i/gtx_channel.gtxe2_channel_i}]
set_property PACKAGE_PIN H2 [get_ports {pci_exp_txp[1]}]
set_property LOC GTXE2_CHANNEL_X0Y21 [get_cells {pcie_7x_1_support_i/pcie_7x_1_i/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[2].gt_wrapper_i/gtx_channel.gtxe2_channel_i}]
set_property PACKAGE_PIN K2 [get_ports {pci_exp_txp[2]}]
set_property LOC GTXE2_CHANNEL_X0Y20 [get_cells {pcie_7x_1_support_i/pcie_7x_1_i/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[3].gt_wrapper_i/gtx_channel.gtxe2_channel_i}]
set_property PACKAGE_PIN M2 [get_ports {pci_exp_txp[3]}]
set_property LOC GTXE2_CHANNEL_X0Y19 [get_cells {pcie_7x_1_support_i/pcie_7x_1_i/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[4].gt_wrapper_i/gtx_channel.gtxe2_channel_i}]
set_property PACKAGE_PIN N4 [get_ports {pci_exp_txp[4]}]
set_property LOC GTXE2_CHANNEL_X0Y18 [get_cells {pcie_7x_1_support_i/pcie_7x_1_i/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[5].gt_wrapper_i/gtx_channel.gtxe2_channel_i}]
set_property PACKAGE_PIN P2 [get_ports {pci_exp_txp[5]}]
set_property LOC GTXE2_CHANNEL_X0Y17 [get_cells {pcie_7x_1_support_i/pcie_7x_1_i/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[6].gt_wrapper_i/gtx_channel.gtxe2_channel_i}]
set_property PACKAGE_PIN T2 [get_ports {pci_exp_txp[6]}]
set_property LOC GTXE2_CHANNEL_X0Y16 [get_cells {pcie_7x_1_support_i/pcie_7x_1_i/inst/inst/gt_top_i/pipe_wrapper_i/pipe_lane[7].gt_wrapper_i/gtx_channel.gtxe2_channel_i}]
set_property PACKAGE_PIN U4 [get_ports {pci_exp_txp[7]}]###############################################################################
# End
###############################################################################

三、代码列表

        头文件:

//--------------------------------------------------------------------------------
//-- Filename: xbmd.h
//--
//-- Description: Main header file for kernel driver
//--              
//-- XBMD is an example Red Hat device driver which exercises XBMD design
//-- Device driver has been tested on Red Hat Fedora FC9 2.6.15.
//--------------------------------------------------------------------------------
// Define Result values
#define SUCCESS                    0
#define CRIT_ERR                  -1// Debug - define will output more info
#define Verbose 1// Max DMA Buffer Size
#define BUF_SIZE                  (4096 * 2)enum {INITCARD,INITRST,DISPREGS,RDDCSR,RDDDMACR,RDWDMATLPA,RDWDMATLPS,RDWDMATLPC,RDWDMATLPP,RDRDMATLPP,RDRDMATLPA,RDRDMATLPS,RDRDMATLPC,RDWDMAPERF,RDRDMAPERF,RDRDMASTAT,RDNRDCOMP,RDRCOMPDSIZE,RDDLWSTAT,RDDLTRSSTAT,RDDMISCCONT,RDDMISCONT,RDDLNKC,DFCCTL,DFCPINFO,DFCNPINFO,DFCINFO,WRDDMACR,WRWDMATLPS,WRWDMATLPC,WRWDMATLPP,WRRDMATLPS,WRRDMATLPC,WRRDMATLPP,WRDMISCCONT,WRDDLNKC,NUMCOMMANDS};

        linux驱动代码:


#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>
#include <linux/device.h>#include "xbmd.h"#define CLASS_NAME "xbmd"
#define DEVICE_NAME "xbmd"static int major_number = 530;
static struct cdev *xbmd_cdev;
void __iomem *regs;
struct pci_dev *gDev = NULL;
static struct class *xbmd_class = NULL;
static struct device *xbmd_device = NULL;
char *gReadBuffer = NULL;
char *gWriteBuffer = NULL;
dma_addr_t gReadHWAddr;
dma_addr_t gWriteHWAddr;
int gIrq;static const struct pci_device_id xbmd_ids[] = {{ PCI_DEVICE(0x10ee, 0x7028) },{ 0, }
};dev_t devno = MKDEV(295, 0);MODULE_DEVICE_TABLE(pci, xbmd_ids);u32 XPCIe_ReadReg (u32 dw_offset)
{u32 ret = 0;ret = ioread32(regs + (4 * dw_offset));printk("XPCIe_ReadReg @0x%x = 0x%x", regs + (4 * dw_offset), ret);return ret; 
}void XPCIe_WriteReg (u32 dw_offset, u32 val)
{printk("XPCIe_WriteReg @0x%x = 0x%x", regs + (4 * dw_offset), val);iowrite32(val, (regs + (4 * dw_offset)));
}u32 XPCIe_ReadCfgReg (u32 byte)
{u32 pciReg;if (pci_read_config_dword(gDev, byte, &pciReg) < 0) {printk("%s: XPCIe_ReadCfgReg: Reading PCI interface failed.", DEVICE_NAME);return (-1);}return (pciReg);
}u32 XPCIe_WriteCfgReg (u32 byte, u32 val)
{if (pci_write_config_dword(gDev, byte, val) < 0) {printk("%s: XPCIe_Read Device Control: Reading PCI interface failed.", DEVICE_NAME);return (-1);}return 1;
}void XPCIe_InitCard(void)
{XPCIe_WriteReg(0, 1);               // Write: DCSR (offset 0) with value of 1 (Reset Device)XPCIe_WriteReg(0, 0);               // Write: DCSR (offset 0) with value of 0 (Make Active)XPCIe_WriteReg(1, 0);XPCIe_WriteReg(2, gWriteHWAddr);    // Write: Write DMA TLP Address register with starting addressXPCIe_WriteReg(3, 0x20);            // Write: Write DMA TLP Size register with default value (32dwords)XPCIe_WriteReg(4, 0x2000);          // Write: Write DMA TLP Count register with default value (2000)XPCIe_WriteReg(5, 0x00000000);      // Write: Write DMA TLP Pattern register with default value (0x0)XPCIe_WriteReg(6, 0xfeedbeef);      // Write: Read DMA Expected Data Pattern with default value (feedbeef)XPCIe_WriteReg(7, gReadHWAddr);     // Write: Read DMA TLP Address register with starting address.XPCIe_WriteReg(8, 0x20);            // Write: Read DMA TLP Size register with default value (32dwords)XPCIe_WriteReg(9, 0x2000);          // Write: Read DMA TLP Count register with default value (2000)printk("XPCIe_InitCard ok");
}void XPCIe_InitiatorReset(void)
{XPCIe_WriteReg(0, 1);                   // Write: DCSR (offset 0) with value of 1 (Reset Device)XPCIe_WriteReg(0, 0);                   // Write: DCSR (offset 0) with value of 0 (Make Active)printk("XPCIe_InitiatorReset ok");
}static int xbmd_open(struct inode *inode, struct file *file)
{printk(KERN_INFO "Device opened\n");return 0;
}static int xbmd_release(struct inode *inode, struct file *file)
{printk(KERN_INFO "Device released\n");return 0;
}static ssize_t xbmd_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
{copy_to_user(buffer, gWriteBuffer, length);printk(KERN_INFO "%s: XPCIe_Read: %d bytes have been read...\n", DEVICE_NAME, length);return 0;
}static ssize_t xbmd_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset)
{int ret = SUCCESS;copy_from_user(gReadBuffer, buffer, length);printk(KERN_INFO "%s: XPCIe_Write: %d bytes have been written...\n", DEVICE_NAME, length);return ret;
}long xbmd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{u32 regx;long ret = SUCCESS;switch (cmd) {case INITCARD:                    // Initailizes XBMD applicationXPCIe_InitCard();memset(gReadBuffer, 0x0, sizeof(gReadBuffer));memset(gWriteBuffer, 0x0, sizeof(gWriteBuffer));break;case INITRST:                     // Resets XBMD applicationsXPCIe_InitiatorReset();break;case DISPREGS:break;case RDDCSR:                     // Read: Device Control Status Registerregx = XPCIe_ReadReg(0);__put_user(regx, (int *)arg);break;case RDDDMACR:                   // Read: DMA Control Status Registerregx = XPCIe_ReadReg(1);__put_user(regx, (int *)arg);break;case RDWDMATLPA:                 // Read: Write DMA TLP Address Registerregx = XPCIe_ReadReg(2);__put_user(regx, (int *)arg);break;case RDWDMATLPS:                 // Read: Write DMA TLP Size Registerregx = XPCIe_ReadReg(3);__put_user(regx, (int *)arg);break;case RDWDMATLPC:                 // Read: Write DMA TLP Count Registerregx = XPCIe_ReadReg(4);__put_user(regx, (int *)arg);break;case RDWDMATLPP:                 // Read: Write DMA TLP Pattern Registerregx = XPCIe_ReadReg(5);__put_user(regx, (int *)arg);break;case RDRDMATLPP:                 // Read: Read DMA TLP Pattern Registerregx = XPCIe_ReadReg(6);__put_user(regx, (int *)arg);break;case RDRDMATLPA:                 // Read: Read DMA TLP Address Registerregx = XPCIe_ReadReg(7);  __put_user(regx, (int *)arg);break;case RDRDMATLPS:                 // Read: Read DMA TLP Size Registerregx = XPCIe_ReadReg(8);__put_user(regx, (int *)arg);break;case RDRDMATLPC:                 // Read: Read DMA TLP Count Registerregx = XPCIe_ReadReg(9);__put_user(regx, (int *)arg);break;case RDWDMAPERF:                 // Read: Write DMA Performance Registerregx = XPCIe_ReadReg(10);__put_user(regx, (int *)arg);break;case RDRDMAPERF:                 // Read: Read DMA Performance Registerregx = XPCIe_ReadReg(11);__put_user(regx, (int *)arg);break;case RDRDMASTAT:                 // Read: Read DMA Status Registerregx = XPCIe_ReadReg(12);__put_user(regx, (int *)arg);break;case RDNRDCOMP:                  // Read: Number of Read Completion w/ Data Registerregx = XPCIe_ReadReg(13);__put_user(regx, (int *)arg);break;case RDRCOMPDSIZE:               // Read: Read Completion Size Registerregx = XPCIe_ReadReg(14);__put_user(regx, (int *)arg);break;case RDDLWSTAT:                  // Read: Device Link Width Status Registerregx = XPCIe_ReadReg(15);__put_user(regx, (int *)arg);break;case RDDLTRSSTAT:                // Read: Device Link Transaction Size Status Registerregx = XPCIe_ReadReg(16);__put_user(regx, (int *)arg);break;case RDDMISCCONT:                // Read: Device Miscellaneous Control Registerregx = XPCIe_ReadReg(17);__put_user(regx, (int *)arg);break;case RDDMISCONT:                // Read: Device MSI Controlregx = XPCIe_ReadReg(18);__put_user(regx, (int *)arg);break;case RDDLNKC:                   // Read: Device Directed Link Change Registerregx = XPCIe_ReadReg(19);__put_user(regx, (int *)arg);break;case DFCCTL:                    // Read: Device FC Control Registerregx = XPCIe_ReadReg(20);__put_user(regx, (int *)arg);break;case DFCPINFO:                  // Read: Device FC Posted Informationregx = XPCIe_ReadReg(21);__put_user(regx, (int *)arg);break;case DFCNPINFO:                 // Read: Device FC Non Posted Informationregx = XPCIe_ReadReg(22);__put_user(regx, (int *)arg);break;case DFCINFO:                  // Read: Device FC Completion Informationregx = XPCIe_ReadReg(23);__put_user(regx, (int *)arg);break;case WRDDMACR:                 // Write: DMA Control Status Register__get_user(regx, (int *)arg);XPCIe_WriteReg(1, regx);break;case WRWDMATLPS:               // Write: Write DMA TLP Size Register__get_user(regx, (int *)arg);XPCIe_WriteReg(3, regx);break;case WRWDMATLPC:               // Write: Write DMA TLP Count Register__get_user(regx, (int *)arg);XPCIe_WriteReg(4, regx);break;case WRWDMATLPP:               // Write: Write DMA TLP Pattern Register__get_user(regx, (int *)arg);XPCIe_WriteReg(5, regx);break;case WRRDMATLPS:               // Write: Read DMA TLP Size Register__get_user(regx, (int *)arg);XPCIe_WriteReg(8, regx);break;case WRRDMATLPC:               // Write: Read DMA TLP Count Register__get_user(regx, (int *)arg);XPCIe_WriteReg(9, regx);break;case WRRDMATLPP:               // Write: Read DMA TLP Pattern Register__get_user(regx, (int *)arg);XPCIe_WriteReg(6, regx);break;case WRDMISCCONT:              // Write: Device Miscellaneous Control Register__get_user(regx, (int *)arg);XPCIe_WriteReg(18, regx);break;case WRDDLNKC:                 // Write: Device Directed Link Change Register__get_user(regx, (int *)arg);XPCIe_WriteReg(19, regx);break;default:break;}return ret;
}static struct file_operations xbmd_fops = {.owner = THIS_MODULE,.open = xbmd_open,.release = xbmd_release,.read = xbmd_read,.write = xbmd_write,.unlocked_ioctl = xbmd_ioctl,
};irqreturn_t XPCIe_IRQHandler(int irq, void *dev_id)
{u32 i, regx;printk(KERN_WARNING"%s: Interrupt Handler Start ..", DEVICE_NAME);for (i = 0; i < 32; i++) {regx = XPCIe_ReadReg(i);printk(KERN_WARNING"%s : REG<%d> : 0x%X\n", DEVICE_NAME, i, regx);}printk(KERN_WARNING"%s Interrupt Handler End ..\n", DEVICE_NAME);return IRQ_NONE;
}static int xbmd_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{int ret;gDev = pdev;ret = pci_enable_device(pdev);if (ret) {printk(KERN_ERR "Failed to enable PCI device\n");return ret;}ret = pci_request_regions(pdev, "xbmd_driver");if (ret) {printk(KERN_ERR "Failed to request regions\n");goto err_disable;}regs = pci_ioremap_bar(pdev, 0);	// BAR0if (!regs) {printk(KERN_ERR "Failed to map BAR0\n");ret = -ENOMEM;goto err_release;}//u32 value = ioread32(regs);//printk(KERN_INFO "Register @0x%x value: 0x%x\n", regs, value);gIrq = gDev->irq;printk(KERN_INFO"%s: Init: Device IRQ: %d\n",DEVICE_NAME, gIrq);printk(KERN_INFO"%s: ISR Setup..\n", DEVICE_NAME);if (0 > request_irq(gIrq, XPCIe_IRQHandler, IRQF_SHARED, DEVICE_NAME, gDev)) {printk(KERN_INFO"%s: Init: Unable to allocate IRQ",DEVICE_NAME);return (CRIT_ERR);}gReadBuffer = dma_alloc_coherent(&pdev->dev, BUF_SIZE, &gReadHWAddr, GFP_KERNEL);if (NULL == gReadBuffer) {printk(KERN_INFO"%s: Init: Unable to allocate gBuffer.\n", DEVICE_NAME);return (CRIT_ERR);}printk(KERN_INFO"%s: Read Buffer Allocation: %X->%X\n", DEVICE_NAME, (u32)gReadBuffer, (u32)gReadHWAddr);gWriteBuffer = dma_alloc_coherent(&pdev->dev, BUF_SIZE, &gWriteHWAddr, GFP_KERNEL);if (NULL == gWriteBuffer) {printk(KERN_INFO"%s: Init: Unable to allocate gBuffer.\n", DEVICE_NAME);return (CRIT_ERR);}printk(KERN_INFO"%s: Write Buffer Allocation: %X->%X\n", DEVICE_NAME, (u32)gWriteBuffer, (u32)gWriteHWAddr);XPCIe_InitCard();printk("xbmd_probe ok\n");return 0;err_release:pci_release_regions(pdev);
err_disable:pci_disable_device(pdev);return ret;
}static void xbmd_remove(struct pci_dev *pdev)
{free_irq(gIrq, gDev);pci_release_regions(pdev);pci_disable_device(pdev);dma_free_coherent(&gDev->dev, BUF_SIZE, gReadBuffer, gReadHWAddr);dma_free_coherent(&gDev->dev, BUF_SIZE, gWriteBuffer, gWriteHWAddr);if (NULL != gReadBuffer)(void) kfree(gReadBuffer);if (NULL != gWriteBuffer)(void) kfree(gWriteBuffer);gReadBuffer = NULL;gWriteBuffer = NULL;if (regs) {printk("Iounmap\n");iounmap(regs);}printk("xbmd_remove ok\n");
}static struct pci_driver xbmd_driver = {.name     = "xbmd_driver",.id_table = xbmd_ids,.probe    = xbmd_probe,.remove   = xbmd_remove,
};#if 1
static int __init xbmd_init(void)
{int ret;ret = pci_register_driver(&xbmd_driver);if (ret < 0)return ret;major_number = register_chrdev(0, DEVICE_NAME, &xbmd_fops);if (major_number < 0) {printk(KERN_ALERT "Registering char device failed with %d\n", major_number);goto out_pci_unregister_driver;}printk(KERN_INFO "Char device registered with major number %d\n", major_number);xbmd_class = class_create(CLASS_NAME);if (IS_ERR(xbmd_class)) {ret = PTR_ERR(xbmd_class);goto out_unregister_chedev;} xbmd_device = device_create(xbmd_class, NULL, MKDEV(major_number, 0), NULL, DEVICE_NAME);if (IS_ERR(xbmd_device)) {ret = PTR_ERR(xbmd_device);goto out_device_destroy;}printk("xbmd_init ok\n");return 0;out_device_destroy:class_destroy(xbmd_class);
out_unregister_chedev:unregister_chrdev(major_number, DEVICE_NAME);
out_pci_unregister_driver:pci_unregister_driver(&xbmd_driver);exit:return ret;
}
#else
static int __init xbmd_init(void)
{int ret;ret = pci_register_driver(&xbmd_driver);if (ret < 0)return ret;#if 0ret = alloc_chrdev_region(&devno, 0, 1, DEVICE_NAME);if (ret < 0) goto out_pci_unregister_driver;
#elseret = register_chrdev_region(devno, 1, DEVICE_NAME);if (ret < 0) goto out_pci_unregister_driver;
#endifxbmd_cdev = cdev_alloc();if (IS_ERR(xbmd_cdev)) {ret = PTR_ERR(xbmd_cdev);goto out_unregister_dev;}cdev_init(xbmd_cdev, &xbmd_fops);xbmd_cdev->owner = THIS_MODULE;ret = cdev_add(xbmd_cdev, devno, 1);    if (ret) goto out_free_cdev;xbmd_class = class_create(CLASS_NAME);if (IS_ERR(xbmd_class)) {ret = PTR_ERR(xbmd_class);goto out_unregister_cdev;} xbmd_device = device_create(xbmd_class, NULL, devno, NULL, DEVICE_NAME);if (IS_ERR(xbmd_device)) {ret = PTR_ERR(xbmd_device);goto out_del_class;}return 0;out_del_class:class_destroy(xbmd_class); 
out_unregister_cdev:cdev_del(xbmd_cdev);
out_free_cdev:kfree(xbmd_cdev);
out_unregister_dev:unregister_chrdev_region(devno, 1);
out_pci_unregister_driver:pci_unregister_driver(&xbmd_driver);return ret;
}
#endif#if 1
static void __exit xbmd_exit(void)
{if (xbmd_class) {printk("Destroy device and class\n");device_destroy(xbmd_class, MKDEV(major_number, 0));class_destroy(xbmd_class);}unregister_chrdev(major_number, DEVICE_NAME);pci_unregister_driver(&xbmd_driver);printk("xbmd_exit ok\n");
}
#else
static void __exit xbmd_exit(void)
{if (xbmd_class) {printk("Destroy device and class\n");device_destroy(xbmd_class, devno);class_destroy(xbmd_class);}cdev_del(xbmd_cdev);kfree(xbmd_cdev);unregister_chrdev_region(devno, 1);pci_unregister_driver(&xbmd_driver);printk("xbmd_exit ok\n");
}
#endifmodule_init(xbmd_init);
module_exit(xbmd_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("Charley Zhang");
MODULE_DESCRIPTION("Xilinx xbmd");

        linux应用层代码


#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include "xbmd.h"unsigned int rxBuffer[1024];
unsigned int txBuffer[1024];int main(int)
{int ret = 0;int devFd = 0;int i;for (i = 0; i < 1024; i++) {rxBuffer[i] = 0x0;txBuffer[i] = 0xfeedbeef;}devFd = open("/dev/xbmd", O_RDWR);if ( devFd < 0 )  {printf("Open /dev/xbmd failed!\n");return -1;}// initcardioctl(devFd, INITCARD, &ret);write(devFd, txBuffer, sizeof(txBuffer));// enable irq & start dmaret = 0x00810081;ioctl(devFd, WRDDMACR, &ret);// wait dma completeusleep(1000);ioctl(devFd, RDDDMACR, &ret);printf("RDDDMACR = 0x%x\n", ret);// check dataret = read(devFd, rxBuffer, sizeof(rxBuffer));printf("rxBuffer[0] = 0x%x\n", rxBuffer[0]);printf("rxBuffer[1] = 0x%x\n", rxBuffer[1]);return 0;
}

        Makefile

obj-m += xbmd.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) cleanrm -rf app

        测试脚本

dmesg -cmake clean
makegcc-12 -o app app.crmmod xbmd.ko
dmesg -c
insmod xbmd.ko
dmesg -c./app
dmesg -c

四、测试

# ./run_bmd.csh

五、测试结果

        实际运行dma没有启动,原因待分析。

六、固化bit文件

        使用BPI Flash,待研究。

七、疑问

        7 Series FPGAs Integrated Block for PCI Express 实现了CfgRd0 CfgRd1 CfgWr0 CfgWr1等配置TLP吗?还是xbmd代码实现的,如下的BMD_CFG_CTRL.v文件有什么作用?


FPGA再入门-1-480T板卡试用
YPCB-00338-1P1 FPGA 板卡 逆向 – TiferKing的学习笔记
PCIe应用实战

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90847.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90847.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TCP的socket编程

TCP客户端逻辑void Usage(const std::string & process) {std::cout << "Usage: " << process << " server_ip server_port" <<std::endl; } // ./tcp_client serverip serverport int main(int argc, char * argv[]) {if (ar…

【理念●体系】模板规范篇:打造可标准化复用的 AI 项目骨架

【理念●体系】从零打造 Windows WSL Docker Anaconda PyCharm 的 AI 全链路开发体系-CSDN博客 【理念●体系】Windows AI 开发环境搭建实录&#xff1a;六层架构的逐步实现与路径治理指南-CSDN博客 【理念●体系】路径治理篇&#xff1a;打造可控、可迁移、可复现的 AI 开…

Skia---渐变色着色器

今天介绍的是实际工作中最常用到的着色器&#xff1a;渐变色着色器。 渐变色着色器是一个从一种颜色平滑的过渡到另一种颜色的效果&#xff0c;渐变色着色器的作用主要是增强图形的视觉吸引力。 线性渐变 Skia 里的线性渐变色着色器是最简单的渐变色着色器&#xff0c;它用于…

2025.07.09华为机考真题解析-第二题200分

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 02. 地铁线路故障预警系统 问题描述 LYA 负责管理一个城市的地铁网络系统。地铁网络由 n n n

数学建模:非线性规划:凸规划问题

一、定义凸集定义​​&#xff1a;设Ω是n维欧氏空间的一点集&#xff0c;若任意两点x₁∈Ω&#xff0c;x₂∈Ω&#xff0c;其连线上的所有点αx₁(1-α)x₂∈Ω&#xff0c;(0≤α≤1)&#xff0c;则称Ω为凸集。​​凸函数定义​​&#xff1a;给定函数f(x)(x∈D⊂Rⁿ)&…

ISIS | 广播网络中的 ISIS 伪节点 LSP

注&#xff1a;本文为 “ISIS | 伪节点 LSP” 相关合辑。 英文引文&#xff0c;机翻未校。 中文引文&#xff0c;略作重排。 如有内容异常&#xff0c;请看原文。 ISIS in Broadcast Network and Pseudonode LSP 广播网络中 的 ISIS 伪节点 LSP ISIS in broadcast network is…

ARIA UWB安全雷达主要产品型号与核心功能全解析

ARIA UWB雷达拥有LT系列与AHM系列两大产品线。LT103 XBT、LT102 V2、LT103 OEM等代表型号具备高精度定位、低功耗和强穿透能力&#xff0c;适用于工业自动化与物联网。AHM3D、AHM2D、AHM3DSC则专注三维检测和智能计算&#xff0c;广泛服务于医疗健康、安防监控等场景。Hydrogen…

NLP自然语言处理04 transformer架构模拟实现

总体架构输入部分代码实现:导包# -*-coding:utf-8-*- import matplotlib.pyplot as plt import numpy as np import torch import torch.nn as nn # -*-coding:utf-8-*- import copy import torch.nn.functional as F import math位置编码器部分词嵌入WordEmbedding# todo 作用…

记录一本书: Python机器学习:基于PyTorch和Scikit-Learn

记录一本书&#xff1a; Python机器学习&#xff1a;基于PyTorch和Scikit-Learn 作者&#xff1a;&#xff08;美&#xff09;塞巴斯蒂安拉施卡(Sebastian Raschka)&#xff08;美&#xff09;刘玉溪&#xff08;海登&#xff09;(Yuxi(Hayden)Liu) &#xff08;美&#xff09;…

Datomic数据库简介(TBC)

Datomic 数据库详细介绍 Datomic 是一个由 Rich Hickey&#xff08;Clojure 语言创始人&#xff09;设计的 不可变、时间感知、分布式数据库&#xff0c;专为现代应用程序设计&#xff0c;强调 数据不变性&#xff08;immutability&#xff09;、查询灵活性和可审计性。它结合…

xformers 完整安装教程【pip conda】(解决 conda 版本 pytorch 自适应安装 xformers)

我个人喜欢用 mamba&#xff08;conda&#xff09;创建环境&#xff0c;然后用 mamba 安装 pytorch CUDA&#xff08;如果需要使用 CUDA 编译&#xff09;&#xff0c;还有一些比如 gcc/g 等与 python 无关的一些工具。 但是最近我在扩充环境的时候&#xff0c;发现需要额外安…

VM虚拟机全版本网盘+免费本地网络穿透端口映射实时同步动态家庭IP教程

VM虚拟机全版本秘钥&#xff0c;文章末尾。 首先网络穿透的意义是让公网可以直接访问家庭电脑&#xff0c;这样本地电脑的硬件性能得以完全发挥&#xff0c;特别是在云服务器贵性能又没家庭电脑好&#xff0c;专线宽带又贵&#xff0c;第三方网络穿透贵的场景下。一般第三方网…

C++ - 仿 RabbitMQ 实现消息队列--项目介绍与环境搭建

目录 项目介绍 开发环境 技术选型 环境搭建 安装 wget(一般情况下默认会自带) 更换国内软件源 安装 lrzsz 传输工具 安装编译器 安装项目构建工具 make 安装调试器 安装 git 安装 cmake 安装 Protobuf 安装 Muduo 安装 SQLite3 安装 Gtest 项目介绍 首先说一下…

《目标检测模块实践手册:从原理到落地的尝试与分享》第一期

大家好&#xff0c;欢迎来到《目标检测模块实践手册》系列的第一篇。从今天开始&#xff0c;我想以一种 “实践记录者” 的身份&#xff0c;和大家聊聊在目标检测任务中那些形形色色的模块。这些内容没有权威结论&#xff0c;更多的是我在实际操作中的一些尝试、发现和踩过的坑…

C++11笑传之引用

C11前言列表初始化{}进行初始化initializer_list右值引用和移动语义左值与右值左值引用与右值引用引用延长生命周期右值引用和移动语义的使用场景左值引用移动构造和移动赋值右值引用在容器插入的提效引用折叠万能折叠完美转发前言 C11是C继98后的更新&#xff0c;其更新了许多…

瀚高数据库提交数据后,是否需要COMMIT(APP)

文章目录环境症状问题原因解决方案报错编码环境 系统平台&#xff1a; 版本&#xff1a;5.6.5,4.5 症状 瀚高数据库提交数据后&#xff0c;是否需要commit&#xff0c;瀚高数据库是否有配置项。 问题原因 瀚高数据库默认自动COMMIT&#xff08;提交数据&#xff09;&#…

深大计算机游戏开发实验三

主要步骤主角飞船的创建和移动边界设置以及护盾设置创建敌机自动生成敌机图层设置弹丸设置武器创建不同发射模式管理竞态条件击败敌机掉落升级道具不同敌机的生成分值显示实现退出游戏界面之后进入游戏的最高记录重置游戏界面失败后重新加载最记录不会重置任何时候在游戏界面按…

详解缓存淘汰策略:LRU

文章目录缓存淘汰策略LRU核心结构核心操作流程局限性源码走读AddGet缓存淘汰策略 缓存淘汰策略的存在是为了解决 缓存容量有限性 和 高缓存命中率 之间的矛盾。其核心目标是在有限的缓存空间内&#xff0c;尽可能提高缓存命中率 缓存容量有限性&#xff1a;缓存&#xff08;例…

什么是 Bootloader?怎么把它移植到 STM32 上?

一、Bootloader 是啥&#xff1f;它都干了些啥&#xff1f;想象一下你的 MCU&#xff08;比如 STM32&#xff09;是一个小机器人&#xff0c;上电之后第一件事&#xff0c;它不会立马开始“干正事”&#xff08;运行你的主程序&#xff09;&#xff0c;而是先去运行一个“开场引…

无人机避障——感知篇(Ego_Planner_v2中的滚动窗口实现动态实时感知建图grid_map ROS节点理解与参数调整影响)

处理器&#xff1a;Orin nx 双目视觉传感器&#xff1a;ZED2 实时感知建图方法&#xff1a;Vins Fusion Raycast &#xff08;VIO与射线投影法感知定位加建图方法&#xff09; 项目地址&#xff1a;https://github.com/ZJU-FAST-Lab/EGO-Planner-v2 【注意】&#xff1a;建…