在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
英文地址,請注明出處:http://en.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;建…