目錄
1. 簡介
1.1 Data Mover
1.2 描述符
2. ZCU102
2.1 Ubuntu OS
2.2 USB Host
2.2.1 連接拓撲
2.2.2 設備類型
2.2.3?USB 跳帽設置
2.3 無線網卡
2.4 PCIe Info
2.4.1 Diagram
2.4.2?lspci -tv
2.4.3 lspci -v
2.4.2.1?設備基本信息
2.4.2.2?控制與狀態寄存器
2.4.2.3?中斷與總線拓撲
2.4.2.4?地址空間配置
2.4.2.5?橋接器控制與能力
2.4.2.6?內核驅動
2.4.4?setpci
2.4.5 命令匯總
3. ZCU102+KU5P
3.1 vivado 工程
3.1.1 Block Design
3.1.2?IBUFDS_GTE
3.1.3 XDMA PCIe
3.1.4 Address Editor
3.1.5 燒寫與固化
3.2 寄存器空間
3.2.1 寄存器地址格式
3.2.2?H2C 通道寄存器空間
3.2.3?C2H 通道寄存器空間
3.2.4 其他寄存器空間
3.2.5 舉例
4. Driver
4.1 PCIe 一些概念
4.1.1 BAR
4.1.2 中斷與輪詢
4.2?DMA?drivers
4.2.1 PCIe Device IDs
4.2.2 編譯并加載驅動
4.2.3 查看驅動信息
4.2.4 獲取通道標識符
4.2.5 xdma0_user 測試
4.2.6 xdma0_bypass 測試
4.2.7 xdma0_h2c_0 讀寫測試
4.3?調試方法
4.3.1 xdma cdev init
4.3.2 h2c status
4.3.3 xfer timed out
4.3.4 Debug Options
4.3.5 信號完整性問題
5. 總結
1. 簡介
1.1 Data Mover
DMA/Bridge Subsystem for PCIe 就是一個數據搬運器件,用于在主機內存和 DMA 子系統之間搬運數據。子系統通過處理一種叫做 “描述符” 的數據結構來完成在主機內存和 DMA 子系統之間移動數據的任務。
|------| |------------------------------FPGA-----------------------------|
| | | |---------------| |-------------------| |
| | | | | | | |
| Host | PCIe | | DMA/Bridge | M_AXI S_AXI | User Logic | |
| App |<---------->|<-->| for PCIe |<---------------->| e.g. | |
| | slot | | | | HW Accelerator | |
| | | | (AXI-master) | | (AXI-slave) | |
| | | |---------------| |-------------------| |
|------| |---------------------------------------------------------------|
連接不同的 AXI-slave,可以實現不同的功能:
- 連接 AXI BRAM 或 AXI DDR MC,則整個 FPGA 可以看作一個 PCIe 內存設備,Host-PC 可以讀寫該內存;
- 一個硬件加速器,則 Host-PC 可以通過 PCIe 調用該加速器;
- AXI 橋,下游掛多個 AXI slave ,可以同時實現更多功能。
1.2 描述符
你可以把 “描述符” 想象成一個包含了數據傳輸指令的小包裹。這個包裹里面明確地寫著:
- 源 (Source): 數據從哪里來(例如,主機內存中的某個具體地址)。
- 目標 (Destination): 數據要到哪里去(例如,DMA 子系統中的某個地址,或者反過來)。
- 要傳輸數據量 (Amount of data to transfer): 需要移動多少數據(例如,多少個字節)。
DMA 子系統會讀取并執行這些 “描述符” 中的信息,從而自動地將數據從源地址搬運到目標地址,而不需要 CPU 的直接干預。
簡單來說,DMA 子系統依靠這些 “描述符” 來了解它需要做什么樣的數據搬運工作。
2. ZCU102
2.1 Ubuntu OS
Install Ubuntu on AMD | Ubuntu Use Ubuntu on AMD for the familiar developer experience and an accelerated path to production.https://ubuntu.com/download/amd
2.2 USB Host
2.2.1 連接拓撲
PHY IC: USB3320 @U116
2.2.2 設備類型
?USB 設備類型
- A 類設備:指的是標準的 USB Host 設備,如計算機或筆記本電腦,它們提供電源并管理連接的 USB 設備。
- B 類設備:通常是外圍設備,如打印機、鼠標或鍵盤,它們從 A 類設備接收電源和數據。?
2.2.3?USB 跳帽設置
跳帽設置:
2.3 無線網卡
下載地址:
W311MI _Tenda-All For Better NetWorkingW311MIhttps://www.tendacn.com/product/overview/W311MIv6.html
W311MIv6.0 Driver (Ubuntu/UOS/Kylin OS) 可以給 KV260、ZCU102 的 Ubuntu 系統使用。
2.4 PCIe Info
2.4.1 Diagram
1)Diagram
Form factor for PCIe Gen2x4 Host, Micro-ATX chassis footprint
2.4.2?lspci -tv
顯示了系統的PCIe拓撲結構
>> lspci -tv
---
-[0000:00]---00.0-[01-0c]----00.0 Xilinx Corporation Device 9021
1)[0000:00]:是 PCIe 層級結構的根節點(Root Complex)
- 0000 是 PCI 域號(domain number),通常為 0000
- 00 是總線號(bus number),00 表示這是根總線
2)---00.0:是根端口(Root Port)的設備號和功能號
- 00 是設備號(device number)
- .0 是功能號(unction number)
3)-[01-0c]:表示這個根端口連接的下游設備所在的總線范圍
- 01-0c 表示總線號從 01 到 0c (十進制12)
- 這意味著這個根端口下可以有多達 12 個不同的總線
4)00.0 Xilinx Corporation Device 9021
- 00.0 是子 PCI 設備的設備和功能編號
- Xilinx Corporation Device 9021?是設備的供應商和型號
>> lspci -vt
-[0000:00]-+-00.0 Intel Corporation Device 9b53+-01.0-[01]----00.0 Xilinx Corporation Device 9021+-02.0 Intel Corporation Device 9bc8+-04.0 Intel Corporation Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem+-12.0 Intel Corporation Comet Lake PCH Thermal Controller+-14.0 Intel Corporation Comet Lake USB 3.1 xHCI Host Controller+-14.2 Intel Corporation Comet Lake PCH Shared SRAM+-16.0 Intel Corporation Comet Lake HECI Controller+-16.3 Intel Corporation Device 06e3+-17.0 Intel Corporation Device 06d2+-1b.0-[02]----00.0 SK hynix Device 1339+-1f.0 Intel Corporation Device 0687+-1f.3 Intel Corporation Comet Lake PCH cAVS+-1f.4 Intel Corporation Comet Lake PCH SMBus Controller+-1f.5 Intel Corporation Comet Lake PCH SPI Controller\-1f.6 Intel Corporation Ethernet Connection (11) I219-LM
這兩行:
+-01.0-[01]----00.0 Xilinx Corporation Device 9021
+-1b.0-[02]----00.0 SK hynix Device 1339
這兩行之所以看起來和別的不一樣,它們表示的是 PCI 橋(PCI Bridge) 以及連接在該橋后面的設備。
- 普通行 (例如 +-02.0 Intel Corporation Device 9bc8): 顯示的是直接連接在當前總線(這里是總線 00)上的終端設備(Endpoint Device),比如集成顯卡、USB 控制器、網卡等。它們不連接其它總線。
- 特殊行 (例如 +-01.0-[01]----00.0 Xilinx ...): 顯示的是一個 PCI 橋 (01.0) 以及通過這個橋連接到下一級(次級)總線 ([01]) 上的第一個設備 (00.0)。這種表示方法突出了設備間的層級和連接關系,顯示了哪些設備是掛載在橋下面的。
2.4.3 lspci -v
lspci 提供了系統中?PCIe 橋接設備(Xilinx Corporation 制造)的詳細信息:
ubuntu@zynqmp:~$ lspci -vv
---
00:00.0 PCI bridge: Xilinx Corporation Device d021 (prog-if 00 [Normal decode])Control: I/O- Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-Latency: 0Interrupt: pin A routed to IRQ 62Bus: primary=00, secondary=01, subordinate=0c, sec-latency=0I/O behind bridge: 00000000-00000fff [size=4K]Memory behind bridge: [disabled]Prefetchable memory behind bridge: [disabled]Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-BridgeCtl: Parity- SERR+ NoISA- VGA- VGA16- MAbort- >Reset- FastB2B-PriDiscTmr- SecDiscTmr- DiscTmrStat- DiscTmrSERREn-Capabilities: <access denied>Kernel driver in use: pcieport
2.4.2.1?設備基本信息
1)設備位置與類型
- 00:00.0 表示設備在 PCI 總線上的位置(總線 00,設備 00,功能 0)。
- 這是一個 PCI 橋接器(PCI bridge),型號為 Xilinx Corporation Device d021,用于連接主總線(00)和次級總線(01-0c)。
2)編程接口(prog-if)
- Normal decode 表示橋接器以標準方式解碼 PCI 地址。
2.4.2.2?控制與狀態寄存器
- 功能禁用(帶
-
),功能啟用(帶+)
1)Control 寄存器
- BusMaster+:橋接器可以發起總線請求(DMA 操作)。
- I/O- Mem-:橋接器未啟用 I/O 和內存空間訪問(可能未配置或未激活)。
- 其他標志(如 SERR-、FastB2B-)表示錯誤報告和快速傳輸功能未啟用。
2)Status 寄存器
- Cap+:設備支持 Capability List(擴展功能列表)。
- DEVSEL=fast:設備快速響應訪問請求。
- 無錯誤狀態(ParErr-、SERR- 等)。
2.4.2.3?中斷與總線拓撲
1)中斷路由:
- Interrupt: pin A routed to IRQ 62
- 橋接器的中斷引腳 A 連接到系統的 IRQ 62。
2)總線范圍:
- primary=00:主總線編號 00(連接 CPU)。
- secondary=01:次級總線起始編號 01。
- subordinate=0c:次級總線結束編號 0c(表示該橋接器下可管理總線 01-0c)。
- sec-latency=0:次級總線訪問延遲為 0。
2.4.2.4?地址空間配置
1)I/O 空間:
- 00000000-00000fff [size=4K]
- 橋接器后掛載的設備的 I/O 空間范圍為 4KB,但當前未啟用(I/O behind bridge 未分配實際地址)。
2)內存空間:
- Memory behind bridge: [disabled]
- 內存和預取內存空間均未啟用(可能需動態配置或未使用)。
2.4.2.5?橋接器控制與能力
1)Secondary Status
- 次級總線的狀態(類似主狀態寄存器),無錯誤或特殊配置。
2)BridgeCtl
- 控制橋接器行為的標志,例如:
- SERR+:啟用系統錯誤報告。
- NoISA-:允許 ISA 風格的訪問(已過時)。
- VGA-:不支持 VGA 兼容模式。
3)Capabilities:
- <access denied> 表示需要 root 權限才能查看擴展功能(如 PCIe 鏈路速度、電源管理等)。
2.4.2.6?內核驅動
- Kernel driver in use: pcieport
當前由 Linux 內核的 pcieport 驅動管理,該驅動負責處理 PCIe 端口和橋接器的通用功能(如熱插拔、錯誤處理等)。
2.4.4?setpci
1)COMMAND 寄存器
在 PCIe 設備中,COMMAND 寄存器是一個 16位寄存器,控制設備的基本操作權限,其低 8 位的標志位控制設備的核心功能:
Bit Name Function
--------------------------------------------------------------------------------
0 I/O Space 啟用設備對 I/O 端口 的訪問(如 in/out 指令)
1 Memory Space 啟用設備對 內存映射寄存器(MMIO) 的訪問(如 BAR0/BAR1)
2 Bus Mastering 允許設備發起 DMA 操作(直接讀寫主機內存)
3-15 Others 如中斷禁用、快速背靠背傳輸等(通常次要)
2)查看 Control 狀態
>> sudo lspci -vv -s 01:00.0 | grep Control
---
Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
說明當前設備?所有關鍵功能均未啟用,無法訪問它的內存或寄存器。
3)啟用功能
>> sudo setpci -s 01:00.0 COMMAND=0x07
0x07 的二進制是 00000111,它同時啟用:
- Bit 0 (I/O Space) = 1 → 允許 I/O 訪問
- Bit 1 (Memory Space) = 1 → 允許 MMIO 訪問
- Bit 2 (Bus Mastering) = 1 → 允許 DMA
為什么內核沒有自動啟用?
- 無專用驅動加載:內核檢測到設備但未綁定驅動時,可能不會主動啟用其功能。
- 安全策略限制:部分系統默認禁用未認證設備的 Bus Mastering(防 DMA 攻擊)。
4)查看驅動加載情況
>> sudo dmesg | grep 9021
---
[ 3.807355] pci 0000:01:00.0: [10ee:9021] type 00 class 0x058000
從 dmesg 輸出和之前的 lspci 信息來看,并沒有為這個 Xilinx 設備(9021)加載專用驅動。
2.4.5 命令匯總
用途 | 命令 |
快速查看設備 | lspci |
查看詳細信息 | lspci -vv |
查看拓撲結構 | lspci -tv |
查找 Xilinx 設備 | lspci -d 10ee |
檢查 PCIe 鏈路 | lspci -vv | grep -i "width|speed" |
查看內存映射 | lspci -v | grep -i memory |
檢查驅動綁定 | lspci -k |
>> lspci
---
00:00.0 PCI bridge: Xilinx Corporation Device d021
命名規則
<bus>:<device>.<function>
- 1. <bus> - 01,總線號(Bus Number) 。這里是 00,表示該設備連接到總線 0。
- 2. <device> - 00,設備號(Device Number) 。這里是 00,表示這是總線 0 上的第 1 個設備(設備號從 0 開始)。
- 3. <function> - 0,功能號(Function Number) 。這里是 0,表示這是該設備的第 1 個功能(功能號從 0 開始)。
3. ZCU102+KU5P
3.1 vivado 工程
3.1.1 Block Design
1)PCIe BRAM
?XDC:
set_property IOSTANDARD LVCMOS33 [get_ports led_0]
set_property PACKAGE_PIN J12 [get_ports led_0]set_property PACKAGE_PIN H14 [get_ports {led_1_tri_io[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_1_tri_io[0]}]set_property PACKAGE_PIN H12 [get_ports user_lnk_up_0]
set_property IOSTANDARD LVCMOS33 [get_ports user_lnk_up_0]set_property PACKAGE_PIN V7 [get_ports {pcie_cref_clk_p[0]}]set_property PACKAGE_PIN T19 [get_ports pcie_rst_n]
set_property IOSTANDARD LVCMOS18 [get_ports pcie_rst_n]set_property PACKAGE_PIN K22 [get_ports {sysclk_clk_p[0]}]
set_property IOSTANDARD DIFF_SSTL12 [get_ports {sysclk_clk_p[0]}]set_property PACKAGE_PIN J14 [get_ports ext_rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports ext_rst_n]create_clock -period 10.000 -name {pcie_cref_clk_p[0]} -waveform {0.000 5.000} [get_ports {pcie_cref_clk_p[0]}]set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 51.0 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub]
set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub]
set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub]
connect_debug_port dbg_hub/clk [get_nets clk]
2)PCIe DDR
?XDC?參見:
《?Vivado - JTAG to AXI Master (DDR4初始化讀寫測試)-CSDN博客?》
3.1.2?IBUFDS_GTE
Primitive: Gigabit Transceiver Buffer
對于高速 GT,需要使用 IBUFDS_GTE,如果使用 IBUFDS,在編譯或者生成 bit 時會報錯,提示該時鐘約束有問題。
3.1.3 XDMA PCIe
IP: DMA/Bride Subsystem for PCI Express v4.1
1)Basic Tab
2)PCIe ID Tab
Device ID(9021)含義:
- 9 - Ultrascale+ 系列
- 2 - PCIe 2.0(5Gbps)
- 1 - 通信鏈路 Lane = 1
3)PCIe:BARs Tab
4)PCIe:MISC?Tab
5)PCIe:DMA Tab
3.1.4 Address Editor
3.1.5 燒寫與固化
1)生成 bin 文件的相關配置
2) 配置 BITSTREAM 屬性
直接添加 XDC 約束:
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 51.0 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
或者通過 GUI 配置:
打開綜合后或實現后的設計,Tools -> Edit Device Properties:
3)添加 Flash 設備
4)執行燒寫
3.2 寄存器空間
3.2.1 寄存器地址格式
DMA/Bridge Subsystem for PCIe 寄存器可從主機或 AXI 從接口進行訪問。這些寄存器應用于 DMA 編程和狀態檢查。
3.2.2?H2C 通道寄存器空間
?
3.2.3?C2H 通道寄存器空間
3.2.4 其他寄存器空間
3.2.5 舉例
1)地址 0x0000_0040
表示 H2C 類別中,第一個通道,H2C Channel Status (0x40) 寄存器
2)地址 0x0000_1040
表示 C2H 類別中,第一個通道,H2C Channel Status (0x40) 寄存器
3)地址 0x0000_1100
表示 C2H 類別中,第二個通道,H2C Channel Identifier (0x00) 寄存器
4)0x0000_3000
表示配置塊寄存器 (0x3)中,Config Block Identifier (0x00)?寄存器
4. Driver
4.1 PCIe 一些概念
4.1.1 BAR
1)BAR的基本含義
BAR(Base Address Register)
BAR 是 PCIe 設備用來定義其內存空間或 I/O 空間在系統地址空間中的基地址(Base Address)的寄存器。每個 BAR 會映射到一個物理地址范圍,系統通過這個范圍訪問設備的資源(如內存、寄存器等)。
BAR 的大小和類型(內存空間或I/O空間)由 BAR 的配置決定。
在 PCIe 設備中,通常有多個 BAR(例如,6個BAR),每個 BAR 可以獨立配置。
2)BAR的作用
BAR 的用途是為 PCIe 設備提供一種與主機(Host)通信的機制:
內存空間映射:通過 BAR,操作系統或驅動程序可以訪問 FPGA 內部的內存或寄存器。
地址分配:在系統啟動時,BIOS 或操作系統會為每個 BAR 分配一個唯一的物理地址。
設備功能支持:不同的 BAR 可以用于不同的功能,例如數據傳輸、控制寄存器訪問等。
4.1.2 中斷與輪詢
1)切換為輪詢
默認情況下,驅動程序使用中斷來通知 DMA 傳輸完成。如何修改驅動程序以使用輪詢而不是中斷來確定 DMA 事務何時完成?
答:在插入內核模塊時,可以將驅動程序從中斷驅動(默認)更改為輪詢驅動(輪詢模式)。
sudo ./load_driver.sh 4
---
interrupt_selection 4.
xdma 98304 0
Loading driver...insmod xdma.ko poll_mode=1 ...The Kernel module installed correctly and the xmda devices were recognized.
DONE
注意:中斷模式與輪詢模式將應用于所有 DMA 通道。如果需要,可以修改驅動程序,使某些通道為中斷驅動,而其他通道為輪詢驅動。有關在輪詢模式下使用 PCIe DMA IP 的更多信息,請參閱 PG195 中的輪詢模式部分。
2)中斷
中斷需要周密的思考和規劃,因為它們在設備驅動程序中扮演著關鍵角色。中斷處理可能具有挑戰性,因為它們需要大量測試來驗證沒有問題;而當問題出現時(例如中斷丟失),調試起來可能非常困難。包含大量調試代碼的 Linux 驅動程序可能會改變其行為,以至于操作完全失效,或者運行極其緩慢,從而嚴重改變系統狀態。
有些中斷是電平觸發(level triggered),有些中斷是邊沿觸發(edge triggered)。這些中斷會被轉換為 PCIe 中斷。PCIe IP 的中斷輸入因具體 IP 而異,但通常是一個請求(request)隨后跟一個許可(grant),表示該 IP 已接受請求。可能需要進行一些從 IP 中斷到 PCIe 中斷的轉換。AXI IIC IP 核是電平觸發中斷,而 AXI QSPI IP 核是邊沿觸發中斷。對于電平觸發中斷,應在驅動程序中仔細檢查,以確保根據從 IP 域到 PCIe 域的轉換方式,中斷不會丟失。
在文檔中查找 IP 的中斷觸發類型可能很有挑戰性,但可以在 Vivado 中查看,如下所示。選中中斷引腳(interrupt pin),然后查看其配置,即可看到信號的敏感度(sensitivity)(邊沿或電平)。
3)整體思路
在主機 CPU 上運行的 DMA 驅動程序的目的是準備外設的 DMA 傳輸,因為只有操作系統(OS)才完全控制著內存系統、文件系統以及用戶空間進程。首先,需要對外設的 DMA 引擎進行編程,設置要復制的內存范圍的源地址和目標地址。其次,通知設備開始 DMA 傳輸。當傳輸完成時,設備通常會產生中斷,以通知 CPU 傳輸已結束。對于每個中斷,一個由驅動程序預先安裝的中斷處理程序會被調用,然后操作系統可以相應地確認已完成的傳輸。
4.2?DMA?drivers
4.2.1 PCIe Device IDs
如何修改內核模塊驅動識別的 PCIe 設備 ID?
參見 "dma_ip_drivers-master\XDMA\linux-kernel\readme.txt"
xdma/xdma_mod.c 文件中包含 pci_device_id 結構體,用于識別驅動支持的 PCIe 設備 ID,格式如下:
// Vendor ID, Device ID
{ PCI_DEVICE(0x10ee, 0x9021), },
根據需要添加、刪除或修改此結構體中的 PCIe Device ID。然后卸載現有的 xdma 內核模塊,重新編譯驅動,并使用 load_driver.sh 腳本重新安裝驅動。?
4.2.2 編譯并加載驅動
1)編譯 KO 模塊
>> cd <dma_ip_drivers-master>/XDMA/linux-kernel/xdma/
>> sudo make install
在 xdma 路徑下創建了兩個文件:xdma.mod.o、xdma.ko
-rw-rw-r-- 1 dd dd 4769480 April 4 17:22 xdma.ko
-rw-rw-r-- 1 dd dd 126880 April 4 17:22 xdma.mod.o
2)編譯測試工具(tools)
>> cd <dma_ip_drivers-master>/XDMA/linux-kernel/tools
>> make
會出現一些 warning,可以忽略。?
3)加載內核模塊驅動程序,有兩種方法:
- 通過 shell 命令直接加載
modprobe xdma
通過 script
>> sudo ./load_driver.sh
---
interrupt_selection .
xdma 98304 0
Loading driver...insmod xdma.ko interrupt_mode=2 ...The Kernel module installed correctly and the xmda devices were recognized.
DONE
4.2.3 查看驅動信息
1)加載驅動后
>> sudo lspci -vv -s 01:00.0 | grep Kernel
---
Kernel driver in use: xdma
Kernel modules: xdma
2)對應的設備節點
>> ll /dev/xdma*
---
/dev/xdma0_control
/dev/xdma0_h2c_0
/dev/xdma0_c2h_0
/dev/xdma0_bypass
/dev/xdma0_bypass_h2c_0
/dev/xdma0_bypass_c2h_0
/dev/xdma0_user
/dev/xdma0_xvc/dev/xdma0_events_0
/dev/xdma0_events_1
...
/dev/xdma0_events_15
3)查看驅動程序詳情
PS:無需指定路徑
>> modinfo xdma
---
filename: /lib/modules/5.15.0-126-generic/xdma/xdma.ko
license: Dual BSD/GPL
version: 2020.2.2
description: Xilinx XDMA Reference Driver
author: Xilinx, Inc.
srcversion: 2EEB4A2EC40A3FC02ABA554
alias: pci:v00001D0Fd0000F001sv*sd*bc*sc*i*
alias: pci:v00001D0Fd0000F000sv*sd*bc*sc*i*
alias: pci:v000010EEd00002808sv*sd*bc*sc*i*
...
...
depends:
retpoline: Y
name: xdma
vermagic: 5.15.0-126-generic SMP mod_unload modversions
parm: h2c_timeout:H2C sgdma timeout in seconds, default is 10 sec. (uint)
parm: c2h_timeout:C2H sgdma timeout in seconds, default is 10 sec. (uint)
parm: poll_mode:Set 1 for hw polling, default is 0 (interrupts) (uint)
parm: interrupt_mode:0 - Auto , 1 - MSI, 2 - Legacy, 3 - MSI-x (uint)
parm: enable_st_c2h_credit:Set 1 to enable ST C2H engine credit feature, default is 0 ( credit control disabled) (uint)
parm: desc_blen_max:per descriptor max. buffer length, default is (1 << 28) - 1 (uint)
4.2.4 獲取通道標識符
通過 Channel Identifier(通道標識符),可以得到通道屬性:
- Channel exist
- Channel Target(H2C / C2H)
- Stream / Mem map
- Channel ID
- Version
1)發送通道查詢指令
>> sudo ./reg_rw /dev/xdma0_control 0x0000
設備節點 /dev/xdma0_control 的寄存器描述《pg195-pcie-dma-en-us-4.1》:
|-----------|----------------|------------------------------------------------------------|
| Bit Index | Field | Description |
|-----------|----------------|------------------------------------------------------------|
| 15:12 | Target | The destination submodule within the DMA |
| | | 4'h0: H2C Channels |
| | | 4'h1: C2H Channels |
| | | 4'h2: IRQ Block |
| | | 4'h3: Config |
| | | 4'h4: H2C SGDMA |
| | | 4'h5: C2H SGDMA |
| | | 4'h6: SGDMA Common |
| | | 4'h8: MSI-X |
|-----------|----------------|------------------------------------------------------------|
| 11:8 | Channel ID[3:0]| This field is only applicable for H2C Channel, C2H Channel,|
| | | H2C SGDMA, and C2H SGDMA Targets. This field indicates |
| | | which engine is being addressed for these Targets. |
| | | For all other Targets this field must be 0. |
|-----------|----------------|------------------------------------------------------------|
| 7:0 | Byte Offset | The byte address of the register to be accessed within the |
| | | target. Bits[1:0] must be0. |
|-----------|----------------|------------------------------------------------------------|
例一,向 /dev/xdma0_control 寫入 0x0000 時,表示查詢 H2C 的第一個通道 identifier 信息:
- Target[15:12]: 0x0 - H2C Channels
- Channel[11:8]:? 0x0 - No 1.
- ByteOffset[7:0]: 0x00 -?Channel Identifier (0x00)
例二,向 /dev/xdma0_control 寫入 0x1003 時,表示查詢 C2H 第四個通道 identifier 信息:
- Target[15:12]: 0x0 - C2H Channels
- Channel[11:8]:? 0x0 - No 4.
- ByteOffset[7:0]: 0x00 -?Channel Identifier (0x00)
例三,向 /dev/xdma0_control 寫入 0x0040 時,表示查詢 H2C 的第一個通道 identifier 信息:
- Target[15:12]: 0x0 - H2C Channels
- Channel[11:8]:? 0x0 - No 1.
- ByteOffset[7:0]: 0x40 - Channel Status (0x40)
2)回讀信息解釋
>> sudo ./reg_rw /dev/xdma0_control 0x0000
---
device: /dev/xdma0_control, address: 0x0 (0x0+0x0), access read.
access width: word (32-bits)
character device /dev/xdma0_control opened.
Memory 0x0 mapped at address 0x7f924a39c000.
Read 32-bit value at address 0x0 (0x7f924a39c000): 0x1fc00006
返回值 0x1fc10006 表示:
- [31:20]: 12’h1fc - DMA Subsystem,該通道啟用,否則讀出?0
- [19:16]: 4'h0 -?H2C Channels
- [15]: 1'b0 -?AXI4 Memory Mapped Interface
- [11:8]: 4'h0 - Channel 1
- [7:0]: 8'h06 -?2017.1 to current release
《pg195-pcie-dma-en-us-4.1》
4.2.5 xdma0_user 測試
1)寫入設備節點 /dev/xdma0_user,地址為?0x4,數據為 0x0。
- 設備節點?/dev/xdma0_user 可以理解為?基地址,由 Host 分配。
- 地址 0x4 可以理解為?偏移地址。
sudo ./reg_rw /dev/xdma0_user 0x4 w 0x0 # axi_gpio out
---
device: /dev/xdma0_user, address: 0x4 (0x0+0x4), access write.
access width: word (32-bits)
character device /dev/xdma0_user opened.
Memory 0x0 mapped at address 0x7fac3e7c0000.
Write 32-bits value 0x00000000 to 0x4 (0x0x7fac3e7c0004)
設備節點 /dev/xdma0_user 可訪問的地址范圍:
PCIe to AXI Translation = 0x400000000
|
PCIe to AXI Translation + Size = 0x40000FFFF
我們實際先要操作的寄存器地址是 0x40000004,如下圖 Address Editor 所示:
通過 ILA 查看實際傳遞到 M_AXI_LITE 的地址:
sudo ./reg_rw /dev/xdma0_user 0x0 w 0x1 # axi_gpio Highsudo ./reg_rw /dev/xdma0_user 0x0 w 0x0 # axi_gpio Low
4.2.6 xdma0_bypass 測試
sudo ./reg_rw /dev/xdma0_bypass 0x4 w 0x0 # axi_gpio outsudo ./reg_rw /dev/xdma0_bypass 0x0 w 0x1 # axi_gpio Highsudo ./reg_rw /dev/xdma0_bypass 0x0 w 0x0 # axi_gpio Low
4.2.7 xdma0_h2c_0 讀寫測試
sudo ./dma_from_device -d /dev/xdma0_c2h_0 -f ./output_datafile0_4K.bin -s 1024 -c 1 &sudo ./dma_to_device -d /dev/xdma0_h2c_0 -f ./datafile0_4K.bin -s 1024 -a 0 -c 1
成功的標志:
>>sudo ./dma_to_device -d /dev/xdma0_h2c_0 -f ./datafile0_4K.bin -s 1024 -a 0 -c 1 -v
---
dev /dev/xdma0_h2c_0, addr 0x0, aperture 0x0, size 0x400, offset 0x0, count 1
host buffer 0x1400 = 0x557119548000
#0: CLOCK_MONOTONIC 0.000121792 sec. write 1024 bytes
** Avg time device /dev/xdma0_h2c_0, total time 121792 nsec, avg_time = 121792.000000, size = 1024, BW = 8.407777
/dev/xdma0_h2c_0 ** Average BW = 1024, 8.407777
4.3?調試方法
4.3.1 xdma cdev init
調查 ubuntu 啟動時,關于 xdma 的 Log:
sudo dmesg | grep xdma
---
[ 7.205815] xdma: loading out-of-tree module taints kernel.
[ 7.222642] xdma: module verification failed: signature and/or required key missing - tainting kernel
[ 7.224451] xdma:xdma_mod_init: Xilinx XDMA Reference Driver xdma v2020.2.2
[ 7.224453] xdma:xdma_mod_init: desc_blen_max: 0xfffffff/268435455, timeout: h2c 10 c2h 10 sec.
[ 7.226197] xdma:xdma_device_open: xdma device 0000:01:00.0, 0x00000000d756b14e.
[ 7.226331] xdma:map_single_bar: BAR0 at 0xe1100000 mapped at 0x0000000063e767e1, length=1048576(/1048576)
[ 7.226340] xdma:map_single_bar: BAR2 at 0xe1300000 mapped at 0x000000007347ea88, length=65536(/65536)
[ 7.226344] xdma:map_bars: config bar 2, pos 1.
[ 7.226349] xdma:map_single_bar: BAR4 at 0xe1200000 mapped at 0x0000000023370d3e, length=1048576(/1048576)
[ 7.226351] xdma:identify_bars: 3 BARs: config 1, user 0, bypass 4.
[ 7.228186] xdma:pci_keep_intx_enabled: 0000:01:00.0: clear INTX_DISABLE, 0x406 -> 0x6.
[ 7.228245] xdma:probe_one: 0000:01:00.0 xdma0, pdev 0x00000000d756b14e, xdev 0x000000002e86ec3b, 0x00000000fc2eb3b5, usr 16, ch 1,1.
[ 7.255484] xdma:cdev_xvc_init: xcdev 0x0000000045e9570d, bar 0, offset 0x40000.
日志關鍵信息的解讀:
1)xdma: loading out-of-tree module taints kernel.
- 表明 xdma 模塊正在被加載。它是一個 "out-of-tree" 模塊(不是內核自帶的),是另外編譯安裝的(非官方代碼),加載這類模塊會 "污染" (taint) 內核。
2)xdma:xdma_mod_init: Xilinx XDMA Reference Driver xdma v2020.2.2
- 驅動的初始化函數 xdma_mod_init 已經開始執行,并打印了驅動的版本號。
3)xdma:xdma_device_open: xdma device 0000:01:00.0, ...
- 成功檢測到了一個 PCI 設備,其地址為 0000:01:00.0。
4)xdma:map_single_bar: BAR0 ... mapped ...
- 驅動成功映射了設備的 PCI?BARs。
5)xdma:probe_one: 0000:01:00.0 xdma0, ...
- probe_one 函數成功完成了對設備 0000:01:00.0 的探測和初始化,并將其命名為 xdma0。
6)xdma:cdev_xvc_init: ...
- 其他初始化,創建字符設備接口 (cdev),用于用戶空間程序與驅動交互。
4.3.2 h2c status
查詢 H2C 的第一個通道 H2C Channel Status (0x40)?信息
>> sudo ./reg_rw /dev/xdma0_control 0x0040
---
access width: word (32-bits)
character device /dev/xdma0_control opened.
Memory 0x0 mapped at address 0x7f590b853000.
Read 32-bit value at address 0x40 (0x7f590b853040): 0x00000001
4.3.3 xfer timed out
發起 DMA 傳輸
sudo ./dma_to_device -d /dev/xdma0_h2c_0 -f ./datafile0_4K.bin -s 512 -a 0 -c 1
---
/dev/xdma0_h2c_0, write 0x200 @ 0x0 failed -1.
write file: Unknown error 512
查看調試信息
sudo dmesg | grep xdma
---
[ 83.849094] xdma:xdma_xfer_submit: xfer 0x00000000a31d2506,512, s 0x1 timed out, ep 0x200.
[ 83.849110] xdma:engine_reg_dump: 0-H2C0-ST: ioread32(0x000000007347ea88) = 0x1fc08006 (id).
[ 83.849118] xdma:engine_reg_dump: 0-H2C0-ST: ioread32(0x000000001f564581) = 0x00000000 (status).
[ 83.849124] xdma:engine_reg_dump: 0-H2C0-ST: ioread32(0x00000000300420f2) = 0x00f83e1e (control)
[ 83.849130] xdma:engine_reg_dump: 0-H2C0-ST: ioread32(0x00000000874345b5) = 0x0d7e0000 (first_desc_lo)
[ 83.849135] xdma:engine_reg_dump: 0-H2C0-ST: ioread32(0x000000002a6151a7) = 0x00000001 (first_desc_hi)
[ 83.849140] xdma:engine_reg_dump: 0-H2C0-ST: ioread32(0x0000000026f28b23) = 0x00000000 (first_desc_adjacent).
[ 83.849145] xdma:engine_reg_dump: 0-H2C0-ST: ioread32(0x00000000ccba4cf2) = 0x00000000 (completed_desc_count).
[ 83.849150] xdma:engine_reg_dump: 0-H2C0-ST: ioread32(0x00000000f18f3588) = 0x00f83e1e (interrupt_enable_mask)
[ 83.849157] xdma:engine_status_dump: SG engine 0-H2C0-ST status: 0x00000000:
[ 83.849161] xdma:transfer_abort: abort transfer 0x00000000a31d2506, desc 1, engine desc queued 0.
核心錯誤信息:
xdma:xdma_xfer_submit: xfer 0x.. ,512, s 0x1 timed out, ep 0x200.
- xdma_xfer_submit:驅動程序提交一個 DMA 傳輸請求,大小是 512 字節。
- timed out:傳輸超時。這是問題的核心。驅動程序啟動了傳輸,但在預設的時間內(默認為 10 秒)沒有收到來自硬件(FPGA)的完成信號。
- ep 0x200: 指示發生超時的引擎端點,對應于 H2C 通道 0 (/dev/xdma0_h2c_0)。
解決辦法:
添加時序約束,并使用 Performance_Explore 策略,確保沒有時序違例:
create_clock -period 10.000 -name {pcie_cref_clk_p[0]} -waveform {0.000 5.000} [get_ports {pcie_cref_clk_p[0]}]
不同于 DDR 的參考時鐘,vivado 工具會自動添加相關約束,xdma ip 并不會添加時鐘約束,及時雙擊信號已經顯示為 100MHz。可能是因為 xdma ip 的參考時鐘是可選的(100/125/250)。
4.3.4 Debug Options
參考:《XAPP1198》
- In-system IBERT?可提供?PCIe?鏈接眼圖。
- JTAG Debugger 和 In-system IBERT 功能結合在一起即可提供即時信息,用于判斷鏈接訓練錯誤的可能原因。
PCIe In-system IBERT 特點:
非侵入性檢測:運行眼圖掃描不影響鏈路完整性,保持信號裕量表征,結合收發器均衡器提供接收端信號裕量的最準確分析。
無需預設測試模式:PCI Express 鏈路很少使用環回模式,通常無預設測試模式,系統內眼圖掃描可直接應用于運行中的鏈路。
容忍比特錯誤:即使存在比特錯誤,PCI Express 鏈路仍可保持在 L0 狀態,通過 CRC 校驗和重放機制確保數據完整性(但重放機制可能影響吞吐量)。
快速定位問題通道:多通道實現中,眼圖掃描可快速識別信號裕量不足的具體通道,避免逐條排查的困難。
反映真實系統條件:掃描結果包含實際運行時依賴(如功耗、開關噪聲等),覆蓋空閑模式、DMA 模式等極端情況,無需人為啟用測試模式。
掃描條件:?
4.3.5 信號完整性問題
1)通過延長線進行連接
>> sudo lspci -vv -s 01:00.0
---
01:00.0 Serial controller: Xilinx Corporation Device 9034 (prog-if 01 [16450])Subsystem: Xilinx Corporation Device 0007Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-Interrupt: pin A routed to IRQ 16Region 0: Memory at e1100000 (32-bit, non-prefetchable) [virtual] [size=1M]Region 1: Memory at e1200000 (32-bit, non-prefetchable) [virtual] [size=64K]
...LnkSta: Speed 8GT/s (ok), Width x4 (ok)
...Capabilities: [1c0 v1] Secondary PCI ExpressLnkCtl3: LnkEquIntrruptEn-, PerformEqu-LaneErrStat: LaneErr at lane: 0 2Kernel modules: xdma
要點:
- 可以識別 9034
- 重要功能無法使用,Control: Mem- BusMaster-
- PCIe Lane通道錯誤,LaneErrStat: LaneErr at lane: 0 2
- 可以看到 Kernel modules: xdma
2)直接連接 PCIe 板卡到主板
>> sudo lspci -vv -s 01:00.0
---
01:00.0 Serial controller: Xilinx Corporation Device 9034 (prog-if 01 [16450])Subsystem: Xilinx Corporation Device 0007Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-Latency: 0Interrupt: pin A routed to IRQ 141Region 0: Memory at e1100000 (32-bit, non-prefetchable) [size=1M]Region 1: Memory at e1200000 (32-bit, non-prefetchable) [size=64K]
...LnkSta: Speed 8GT/s (ok), Width x4 (ok)
..Capabilities: [1c0 v1] Secondary PCI ExpressLnkCtl3: LnkEquIntrruptEn-, PerformEqu-LaneErrStat: 0Kernel driver in use: xdmaKernel modules: xdma
要點:
- 可以識別 9034
- 功能正常識別,Control: Mem+ BusMaster+
- 可以看到 Kernel driver in use: xdma
5. 總結
本文詳細介紹了基于 Xilinx ZCU102 開發板的 PCIe DMA 子系統設計與實現。
- DMA/Bridge Subsystem for PCIe 作為核心數據搬運引擎,通過描述符(Descriptor)實現主機內存與 FPGA 間的高效數據傳輸,支持連接不同AXI從設備(如 BRAM、DDR 或硬件加速器)。
- 在 ZCU102 平臺上,Ubuntu 系統通過 PCIe 驅動(xdma.ko)管理設備,利用 lspci、setpci 等工具進行拓撲分析和寄存器配置。
- Vivado 工程中,XDMA IP 核的配置需注意 BAR 空間分配、時鐘約束(如 IBUFDS_GTE 使用)及中斷模式選擇(輪詢/中斷)。
- 實際測試中,通過 reg_rw 和 dma_to_device 等工具驗證了 H2C/C2H 通道傳輸功能,并針對信號完整性(如 PCIe 鏈路眼圖掃描)和時序問題提供了調試方法。