最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

LabVIEW FPGA PCIe開發(fā)講解-7.3節(jié):FPGA PCIe DMA總線通信開發(fā)過程(3個步驟)

2021-03-27 13:14 作者:神電測控  | 我要投稿

?????? ?要想開發(fā)出一個完整的基于PCIe通信的FPGA板卡,需要經(jīng)歷以下3個步驟才能算是完成。

?????? ?首先,用戶需要根據(jù)實際情況,編寫FPGA芯片里面的邏輯代碼,比如做一個基于PCIe傳輸?shù)腄AQ采集卡,那么用戶需要在FPGA里面利用LabVIEW編寫一個ADC采集程序,然后將采集到的數(shù)據(jù)通過FIFO轉(zhuǎn)移到我們封裝出來的PCIe CLIP對應(yīng)的上行通道里面,或者將上位機下發(fā)的數(shù)據(jù)從FPGA FIFO里面讀取出來。這部分代碼開發(fā),我們稱之為下位機FPGA程序編寫,采用LabVIEW進行開發(fā)。關(guān)于下位機LabVIEW FPGA程序開發(fā),也是貫徹本書的重點,前面每個實驗基本上都著重講解了LabVIEW開發(fā)FPGA下位機程序這部分。

?????? ?接下來,當我們利用LabVIEW編寫好FPGA程序(里面包含PCIe CLIP),編譯成bit文件,下載到FPGA芯片里面運行后,我們還需要通過重啟電腦來識別這個PCIe設(shè)備,如果是bit文件,必須熱重啟,不能通過關(guān)機重啟,如果是bin文件已經(jīng)固化到FPGA板子上的Flash芯片里面,可以熱重啟也可以冷重啟。重啟之后,如果是第一次接入,系統(tǒng)會將插入到機箱里面的FPGA硬件,在設(shè)備管理器里面識別成黃色感嘆號,此時用戶需要安裝一下Xillybus公司提供的PCIe驅(qū)動inf文件,這個文件是經(jīng)過微軟數(shù)字簽名的,不像Xilinx官方給的那個沒有經(jīng)過數(shù)字簽名的inf那樣,必須讓系統(tǒng)在測試模式下才能用,所以說,Xillybus提供的驅(qū)動inf文件更方便大家使用。當這個inf驅(qū)動加載成功后,用戶就可以盡情地在上位機享用FPGA PCIe通信了。

?????? ?最后,我們還需要編寫一個上位機應(yīng)用程序來跟下位機FPGA進行通信,為了方便用戶,我們封裝了一個8上8下的PCIe DMA DLL,這樣對于那些不會LabVIEW的用戶也可以使用C\C++\C#\Python等文本語言進行調(diào)用;如果用戶會用LabVIEW開發(fā)上位機應(yīng)用程序,我們參照NI FPGA板卡的工作方式,重新封裝了一個LabVIEW PCIe_DMA.lvlib庫,用戶直接拖拽就可以了,非常方便。

?????? ?至此,我們才把一個基于PCIe的FPGA項目或者產(chǎn)品做完了,然后就可以將FPGA板卡、FPGA程序框圖、中間層驅(qū)動文件和上位機應(yīng)用程序交付給最終用戶。其中,中間層驅(qū)動文件inf由Xillybus提供好了,中間層DLL我們神電測控也封裝好了,用戶只需要會LabVIEW開發(fā)FPGA芯片里面的代碼以及上位機PC端的程序就可以了,非常簡單省事。

?????? ?下面,我們分別對這3個步驟進行詳細的講解。

?? ?7.3.1、下位機FPGA PCIe固件程序開發(fā)(bit文件,用LabVIEW FPGA進行開發(fā))

?????? ?當我們做一個FPGA PCIe硬件時,首先需要準備好一個支持PCIe通信的FPGA板子,比如黑金的AX7103開發(fā)板,上面的ARTIX7 FPGA芯片本身就支持PCIe 2.0 X4通信。這塊FPGA開發(fā)板也就是本書配套的實驗平臺,關(guān)于這個板子各個功能模塊的講解,前面第6章每個實驗都詳解驗證過了。

?????? ?當FPGA硬件準備好之后,接下來,我們就可以大刀闊斧的按照我們實際的項目或者產(chǎn)品需求,在FPGA芯片里面利用LabVIEW進行編程了。這里用LabVIEW編寫的FPGA代碼,我們稱之為下位機FPGA程序開發(fā)。

?????? ?比如,我們要在FPGA里面開發(fā)一個DAQ采集程序,我們可以直接將前面第6章里面的各種ADC采集線程拷貝到本節(jié)實驗里面來,然后再配上PCIe DMA CLIP節(jié)點,就變成了一個帶PCIe傳輸接口的DAQ設(shè)備了;如果將前面的DAC信號輸出線程拷貝到本節(jié)實驗里面來,配上PCIe DMA CLIP,就變成了一個任意信號信號發(fā)生器板卡了;如果把前面的雙目攝像頭圖像采集框圖拷貝到本節(jié)實驗里面來,配上PCIe DMA CLIP,就變成了一個基于PCIe的圖像采集卡了。

?????? ?關(guān)于這個下位機FPGA里面的代碼編寫,相信用戶在學習了本書的第5章和第6章之后,就不會陌生了,而且很多下位機FPGA端的代碼都可以直接從前面第6章對應(yīng)的實驗里面進行拷貝,無需重頭編寫。

?????? ?當下位機FPGA端的LabVIEW程序框圖寫完之后,點擊運行可以生成對應(yīng)的FPGA bit文件和bin文件,我們把這個文件稱之為下位機可執(zhí)行文件或者固件程序。當然,如果用戶對VHDL或者Verilog十分精通的話,也可以用文本語言編程,但是我們推薦大家用LabVIEW開發(fā),效率更高。

?????? ?這里我們直接通過一個示意圖來表達一下下位機FPGA里面的代碼編寫過程,如圖7-9所示。其中,生成中間VHDL代碼和編譯成bit文件都是在后臺自動完成的,即使用戶完全不懂FPGA也沒有用過Xilinx任何IDE軟件,只要會LabVIEW就可以搞定一切!

圖7-9:LabVIEW下位機FPGA開發(fā)過程

? ? ? ??備注:詳細的LabVIEW FPGA CLIP代碼講解,可以參考后面7.4節(jié)的相關(guān)內(nèi)容。

?? ?7.3.2、中間層PCIe驅(qū)動程序安裝(inf文件,Xillybus官方提供)

?????? ?當我們把開發(fā)好的LabVIEW程序框圖編譯出來的FPGA bit下載到FPGA芯片里面運行之后,點擊windows系統(tǒng)開始菜單,選擇重啟(注意:不能選擇關(guān)機)。系統(tǒng)重啟之后,對于第一次接入到PC或者工控機機箱里面的PCIe板卡來說,在設(shè)備管理器里面會出現(xiàn)一個PCI設(shè)備黃色感嘆號,如圖7-10所示。有些系統(tǒng)在重啟的時候,右下角還會彈出一個提示框,提醒用戶,電腦上有個硬件驅(qū)動軟件沒有安裝成功,如圖7-11所示。

圖7-10:設(shè)備管理器出現(xiàn)未知PCI設(shè)備黃色感嘆號(沒有安裝Xillybus驅(qū)動之前)
圖7-11:重啟之后,系統(tǒng)右下角還會提示器件驅(qū)動沒有成功安裝

? ? ? ??接下來,我們需要安裝一下Xillybus公司提供的PCIe inf驅(qū)動文件,右擊設(shè)備管理器里面的黃色感嘆號,選擇瀏覽,如圖7-12所示。

圖7-12:右擊設(shè)備管理器,選擇瀏覽計算機上的inf驅(qū)動文件

? ? ? ??在彈出來的路徑選擇對話框里面,點擊右側(cè)的“Browse”瀏覽按鈕,然后找到本地計算機上的inf驅(qū)動文件,這個驅(qū)動文件用戶可以在Xillybus公司官網(wǎng)上找到,也可以在本書配套的云盤里面下載到,如圖7-13所示。選擇瀏覽之后,加載的路徑如圖7-14所示。然后點擊下面的“Next”下一步按鈕,又會彈出一個windows安全警告對話框,我們需要勾選“Always trust”總是相信,再點擊“Install”按鈕進行安裝,如圖7-15所示。如果不出意外的話,會彈出安裝成功提示框,如圖7-16所示。最后在設(shè)備管理器里面會出現(xiàn)一個名為“Xillybus driver for generic FPGA interface”的PCIe板卡,如圖7-17所示。

圖7-13:找到Xillybus公司提供的FPGA PCIe驅(qū)動文件inf(官網(wǎng)下載或者云盤下載)
圖7-14:選擇inf所在的文件夾路徑
圖7-15:勾選Always trust再點擊Install安裝
圖7-16:Xillybus FPGA PCIe驅(qū)動安裝成功對話框
圖7-17:安裝成功后的設(shè)備管理器PCIe設(shè)備名稱(Xillybus)

? ? ? ? 接下來,我們還需要檢驗一下系統(tǒng)是否正常加載了FPGA下位機里面添加的PCIe DMA通道號。比如我們在下位機FPGA里面封裝了8上8下的PCIe DMA CLIP節(jié)點,那么上位機PC端必須要識別出來所有的通道號名稱和具體路徑,這樣后續(xù)才能跟FPGA通信。

?????? ?具體怎么操作呢?用戶可以到微軟官方網(wǎng)站上,下載一個小工具“WinObj.exe”,直接雙擊運行,它可以將我們電腦上所有正常安裝的硬件,統(tǒng)統(tǒng)識別出來,比如我們平時常用的串口設(shè)備,如圖7-18所示。而我們剛剛加載安裝成功的Xillybus PCIe設(shè)備端口讀寫通道號也被枚舉出來了,如圖7-19所示。

圖7-18:通過WinObj工具可以查看計算機所有的串口設(shè)備號
圖7-19:通過WinObj工具可以查看計算機枚舉出來的Xillybus PCIe端口通道號

? ? ? ? 這些枚舉出來的端口通道名稱就是后續(xù)第三個步驟上位機應(yīng)用程序需要訪問的端口名稱,比如“xillybus_write_32_ch0”,意為下行(Host-->FPGA)的寫端口,位寬是32位,通道號是0。

?????? ?那么問題來了,這里面8上8下的設(shè)備端口名稱是不是固定的呢?還是人為可以修改的呢?實際上這些端口名稱就是前面我們展示的下位機FPGA CLIP里面的名稱,這些名稱是在Xillybus公司官網(wǎng)的IP核Web配置頁面里面提前寫好的,如前面的圖7-6所示。當我們在Web上生成PCIe IP核之后,加載到下位機LabVIEW FPGA CLIP里面之后,編譯成bit文件下載到FPGA芯片里面運行之后,主機端系統(tǒng)就會將FPGA Memory里面存放的這些端口號名稱通過中間層驅(qū)動全部識別枚舉出來,然后我們通過WinObj這個工具就能將其全部觀察到。一般情況下,我們建議用戶使用Xillybus官方推薦的命名規(guī)則,這樣不同的用戶生成的FPGA PCIe驅(qū)動對應(yīng)的端口號就會一目了然。

?????? ?到這里,說明我們的FPGA下位機運行正常,并且PCIe驅(qū)動也已成功安裝!

?? ?7.3.3、上位機PC端DMA FIFO應(yīng)用程序開發(fā)(LabVIEW/C調(diào)用DLL文件,神電提供lvlib庫)

?????? ?當FPGA硬件被系統(tǒng)識別成功后,我們就可以編寫一個上位機PC端的應(yīng)用程序來與之通信,進行數(shù)據(jù)交互了。為了方便廣大用戶的使用,我們將8上8下共計16個通道的中間層DMA高速傳輸封裝成了DLL動態(tài)鏈接庫,這樣對于使用不同編程語言(C\C++\C#\Python)開發(fā)上位機應(yīng)用程序的用戶來說,直接調(diào)用我們封裝好的DLL驅(qū)動就可以了。這個DLL位于本書配套的云盤里面,如圖7-20所示。

圖7-20:我們給用戶封裝好的8上8下共計16個通道的DLL動態(tài)鏈接庫

? ? ? ? 下面重點給用戶講解一下我們針對LabVIEW軟件封裝好的一個lvlib庫文件,對于熟悉LabVIEW編程的工程師來說,直接將lvlib里面的VI拖拽到自己的程序里面就可以完成跟下位機FPGA之間的PCIe通信了,一目了然。圖7-21顯示的是我們封裝好的上位機LabVIEW My FPGA PCIe Toolkit軟件工具包項目瀏覽器截圖。

圖7-21:封裝出來的FPGA PCIe DMA上位機LabVIEW項目庫

? ? ? ? 里面主要包含兩大塊,分別是PC端的FPGA PCIe上位機范例程序(Example-PC虛擬文件夾)和中間層的lvlib庫文件。其中PC端的范例程序在后續(xù)的PCIe基礎(chǔ)和高級實驗里面再給大家做詳細的講解;本節(jié)先著重介紹一下我們封裝的lvlib庫函數(shù)(VI)。

?????? ?首先,在參照了NI FPGA 板卡的DMA傳輸工作流程之后,我們特地有針對性的封裝,將一個上行(FPGA-->Host)DMA傳輸過程分成7個步驟,分別對應(yīng)7個子VI,下行則不需要DMA機制:

1) PCIe DMA通道初始化并開辟指定深度的緩沖區(qū)(PC_FIFO_DMA_Poly_Init_DLW30.vi)

2) PCIe DMA通道啟動傳輸(PC_FIFO_DMA_Poly_Start_DLW30.vi)

3)PCIe DMA通道緩沖區(qū)存在的字節(jié)數(shù)數(shù)量(PC_FIFO_Poly_Buffer_Length_DLW30.vi)

4) PCIe DMA通道緩沖區(qū)讀取指定長度的數(shù)據(jù)(PC_FIFO_DMA_Poly_Read_DLW30.vi)

5)?PCIe DMA通道停止傳輸(PC_FIFO_DMA_Poly_Stop_DLW30.vi)

6) PCIe DMA通道等待退出(PC_FIFO_DMA_Poly_Exit_Wait_DLW30.vi)

7) PCIe DMA通道銷毀(PC_FIFO_DMA_Poly_Destroy_DLW30.vi)

?????? ?注意:所有調(diào)用DLL的子VI都要設(shè)置成“任意線程”,切不可設(shè)置成“用戶線程”,如圖7-22所示。否則一旦DLL里面的函數(shù)出現(xiàn)讀寫阻塞之后,會導致LabVIEW界面無響應(yīng),卡死狀態(tài),更沒有辦法進行探針調(diào)試,切記!

圖7-22:LabVIEW調(diào)用底層有阻塞函數(shù)的DLL時,一定要設(shè)置成“任意線程運行”

? ? ? ? 下面我們對這7個多態(tài)子VI分別進行講解,之所以設(shè)計成多態(tài)VI,是為了方便用戶編程的時候,可以直接選擇切換通道。

?????? ?1)PC_FIFO_DMA_Poly_Init_DLW30.vi

?????? ?這個子VI可以用來完成對指定的FPGA PCIe通道進行初始化,同時還可以按照用戶輸入的數(shù)值向計算機申請開辟一個指定深度(長度或者大小,單位字節(jié))的緩沖區(qū),如圖7-22所示。圖中所示可以這樣理解:針對32位位寬的PCIe DMA ch0(通道0)向計算機(主機)申請開辟一個500M字節(jié)的緩沖區(qū),緩沖區(qū)首地址或者說指針放在第3個DMA引用當中,如果申請的緩沖區(qū)成功,那么對應(yīng)輸出的指示燈會點亮。

圖7-23:PCIe DMA上位機PC端通道初始化VI函數(shù)

? ? ? ??注意:初始化函數(shù)的緩沖區(qū)深度設(shè)置,跟后面的(PC_FIFO_DMA_Poly_Read_DLW30.vi)讀取長度之間需要滿足一定的關(guān)系,否則會出現(xiàn)讀取丟點的情況。原因是我們開辟的緩沖區(qū)(假設(shè)FIFO深度為M),實際上是一個異步的環(huán)形FIFO,F(xiàn)PGA端會把數(shù)據(jù)源源不斷的往這個FIFO里面寫,然后應(yīng)用層,比如LabVIEW會從這個FIFO里面取數(shù)據(jù),至于什么時候讀,讀多少?取決于這個FIFO里面現(xiàn)有的數(shù)據(jù)長度,一般的上位機讀取機制是:當上位機判斷到這個FIFO已經(jīng)有了至少N個點時,我們就調(diào)用這個函數(shù)(PC_FIFO_DMA_Poly_Read_DLW30.vi)把N個點讀取出來,余下的數(shù)據(jù)還會留在FIFO里面,由于開辟的是環(huán)形FIFO,所以讀取位置會不斷的從開頭到末尾掃描,因此,在跨越邊界長度的時候,會出現(xiàn)讀取截斷或者丟點的現(xiàn)象。結(jié)論是M要能整除N才行。

?????? ?舉例說明:比如我們開辟了一個500MByte深度的緩沖區(qū),然后每次讀取2048個Byte點,實際上500M/2048無法整除,這樣就會導致在讀取最后一幀的時候,讀出來的數(shù)據(jù)有問題,為了避免這個問題,我們有兩種解決方法:如果讀取的長度事先確定了,那么我們在申請開辟緩沖區(qū)長度的時候,將讀取長度乘上一個整數(shù)就可以了,比如開辟2048×100000=204.8MByte;如果讀取長度是變化的,那么需要滿足整除這個條件,比如我們開辟的環(huán)形FIFO大小是500M,那么讀取長度可以選擇5、10、100、1000之類的,不能選擇1024或者3之類的。上面講解的機制和原理,用戶一定要記在心里?。?!

?????? ?小心:在后續(xù)的PCIe+OV5640攝像頭例程里面,可以看到,720p RGB565格式下的每幀圖像字節(jié)是1280×720×2=1843200Byte,如果用戶想要每次讀取一幅圖像刷新顯示,那么在調(diào)用初始化函數(shù)(PC_FIFO_DMA_Poly_Init_DLW30.vi)開辟緩沖區(qū)長度的時候,一定要設(shè)置為1843200Byte的整數(shù)倍,比如184.32MByte或者368.64MByte。

?????? ?2)PC_FIFO_DMA_Poly_Start_DLW30.vi

?????? ?這個多態(tài)子VI的作用是用來控制上位機PC端的PCIe DMA FIFO通道是否接收下位機FPGA發(fā)送的數(shù)據(jù),相當于啟動了DMA傳輸,一旦調(diào)用了這個VI,那么只要下位機FPGA有數(shù)據(jù)在發(fā)送,通過任務(wù)管理器就能看到我們前面申請開辟的緩沖區(qū)里面就會有源源不斷的數(shù)據(jù)進來,如果下位機FPGA不發(fā)送上行數(shù)據(jù),那么這個DMA通道也會一直處于等待接收狀態(tài),相當于線程阻塞了。這個子VI不需要輸入?yún)?shù),如圖7-24所示。通過顯示控件“DMA啟動傳輸成功?”指示燈狀態(tài),可以判斷PCIe DMA通道是否成功開啟傳輸模式,由于我們支持8個DMA通道同時并行傳輸數(shù)據(jù),所以前面我們初始化了哪些DMA通道,這里我們就需要利用“PC_FIFO_DMA_Poly_Start_DLW30.vi”函數(shù)來開啟這些通道的數(shù)據(jù)傳輸使能。

圖7-24:PCIe DMA上位機PC端啟動通道數(shù)據(jù)傳輸VI函數(shù)

? ? ? ? 3)PC_FIFO_Poly_Buffer_Length_DLW30.vi

?????? ?這個子VI的功能跟我們平時常用的一個VISA屬性節(jié)點“串口緩沖區(qū)字節(jié)數(shù)”功能類似,就是用戶可以通過輪詢的方式,查看當前PC端DMA通道對應(yīng)的緩沖區(qū)里面存在多少字節(jié)的數(shù)據(jù),比如,當字節(jié)數(shù)量大于10KBytes的時候,我們再調(diào)用讀取VI將這些數(shù)據(jù)從FIFO緩沖區(qū)里面取走,這樣可以提高讀取效率,同時也能降低讀取頻率,釋放CPU給其他線程使用。通過調(diào)用這個子VI可以實時觀察到緩沖區(qū)里面的數(shù)據(jù)增加或者減少,對于不定長傳輸也會起到一定的作用。這個子VI返回的長度單位是Byte,通常會跟FIFO Read函數(shù)一起使用。

圖7-25:查詢PCIe DMA上位機PC端緩沖區(qū)里面存在的字節(jié)數(shù)量

? ? ? ? 4)PC_FIFO_DMA_Poly_Read_DLW30.vi

?????? ?當我們通過前面的“PC_FIFO_Poly_Buffer_Length_DLW30.vi”函數(shù)查詢到緩沖區(qū)里面已經(jīng)有了我們需要的數(shù)據(jù)時,接下來就可以利用這個“PC_FIFO_DMA_Poly_Read_DLW30.vi”函數(shù)從FIFO里面把數(shù)據(jù)讀取出來,給到我們的應(yīng)用程序進行處理、顯示或者流盤保存等操作了。如圖7-26所示,這個VI需要用戶給定讀取數(shù)據(jù)的長度值,單位是Byte字節(jié),指定讀取的長度不能超過緩沖區(qū)已有的數(shù)據(jù)長度;其次,從緩沖區(qū)里面讀取出來的數(shù)據(jù)都是最原始的字節(jié)數(shù)組或者說是字符串,用戶可以根據(jù)實際情況,利用數(shù)值選板里面的“強制類型轉(zhuǎn)換”函數(shù)將原始的字節(jié)數(shù)組轉(zhuǎn)成需要的數(shù)據(jù)類型,比如下位機FPGA發(fā)送的是有符號32位類型的波形數(shù)據(jù),那么我們可以參考圖7-26所示的那樣,將真實的數(shù)據(jù)轉(zhuǎn)換出來,如果用戶在界面上給定讀取的是數(shù)據(jù)是波形點數(shù),那么Size_Read應(yīng)該×4比較好,這樣轉(zhuǎn)換后的點數(shù)就跟實際的點數(shù)對應(yīng)上了。

圖7-26:從上位機PCIe DMA通道FIFO緩沖區(qū)里面讀取指定長度的字節(jié)數(shù)據(jù)

? ? ? ??注意:初始化函數(shù)的緩沖區(qū)深度設(shè)置,跟后面的(PC_FIFO_DMA_Poly_Read_DLW30.vi)讀取長度之間需要滿足一定的關(guān)系,否則會出現(xiàn)讀取丟點的情況。原因是我們開辟的緩沖區(qū)(假設(shè)FIFO深度為M),實際上是一個異步的環(huán)形FIFO,F(xiàn)PGA端會把數(shù)據(jù)源源不斷的往這個FIFO里面寫,然后應(yīng)用層,比如LabVIEW會從這個FIFO里面取數(shù)據(jù),至于什么時候讀,讀多少?取決于這個FIFO里面現(xiàn)有的數(shù)據(jù)長度,一般的上位機讀取機制是:當上位機判斷到這個FIFO已經(jīng)有了至少N個點時,我們就調(diào)用這個函數(shù)(PC_FIFO_DMA_Poly_Read_DLW30.vi)把N個點讀取出來,余下的數(shù)據(jù)還會留在FIFO里面,由于開辟的是環(huán)形FIFO,所以讀取位置會不斷的從開頭到末尾掃描,因此,在跨越邊界長度的時候,會出現(xiàn)讀取截斷或者丟點的現(xiàn)象。結(jié)論是M要能整除N才行。

?????? ?舉例說明:比如我們開辟了一個500MByte深度的緩沖區(qū),然后每次讀取2048個Byte點,實際上500M/2048無法整除,這樣就會導致在讀取最后一幀的時候,讀出來的數(shù)據(jù)有問題,為了避免這個問題,我們有兩種解決方法:如果讀取的長度事先確定了,那么我們在申請開辟緩沖區(qū)長度的時候,將讀取長度乘上一個整數(shù)就可以了,比如開辟2048×100000=204.8MByte;如果讀取長度是變化的,那么需要滿足整除這個條件,比如我們開辟的環(huán)形FIFO大小是500M,那么讀取長度可以選擇5、10、100、1000之類的,不能選擇1024或者3之類的。上面講解的機制和原理,用戶一定要記在心里?。?!

?????? ?小心:在后續(xù)的PCIe+OV5640攝像頭例程里面,可以看到,720p RGB565格式下的每幀圖像字節(jié)是1280×720×2=1843200Byte,如果用戶想要每次讀取一幅圖像刷新顯示,那么在調(diào)用初始化函數(shù)(PC_FIFO_DMA_Poly_Init_DLW30.vi)開辟緩沖區(qū)長度的時候,一定要設(shè)置為1843200Byte的整數(shù)倍,比如184.32MByte或者368.64MByte。

?????? ?5)PC_FIFO_DMA_Poly_Stop_DLW30.vi

?????? ?當我們不需要PCIe DMA通道或者退出應(yīng)用程序之前,用戶可以調(diào)用這里的“PC_FIFO_DMA_Poly_Stop_DLW30.vi”函數(shù)來關(guān)停上位機PC端的DMA通道的數(shù)據(jù)接收功能,此時,即使下位機FPGA還在發(fā)送數(shù)據(jù),上位機PC里面的FIFO緩沖區(qū)也不會接收任何數(shù)據(jù),處于關(guān)閉狀態(tài)。這個VI跟前面的第2個函數(shù)(PC_FIFO_DMA_Poly_Start_DLW30.vi)其實是一對功能互反的VI。用戶調(diào)用的時候,只需要選擇想要關(guān)閉的DMA通道就可以了,如圖7-27所示。

圖7-27:關(guān)閉PCIe DMA通道的數(shù)據(jù)傳輸

? ? ? ? 6)PC_FIFO_DMA_Poly_Exit_Wait_DLW30.vi

?????? ?雖然前面我們把上位機PC端的DMA緩沖區(qū)接收功能關(guān)閉了,但是中間層的驅(qū)動里面,還有一些人為開辟的線程沒有關(guān)掉,我們特地給用戶封裝了一個等待線程退出函數(shù)“PC_FIFO_DMA_Poly_Exit_Wait_DLW30.vi”,通過這個函數(shù)可以確保中間層的DLL里面所有線程都退出了,防止出現(xiàn)線程阻塞卡死等狀態(tài)。這個VI的調(diào)用非常簡單,用戶只需要選擇想要退出的DMA通道就可以了,如圖7-28所示。

圖7-28:等待中間層的DLL里面的PCIe DMA通道退出

? ? ? ? 7)PC_FIFO_DMA_Poly_Destroy_DLW30.vi

?????? ?當DLL里面的DMA Read線程退出之后,最后我們還需要調(diào)用一下這里的“PC_FIFO_DMA_Poly_Destroy_DLW30.vi”函數(shù)將DLL里面申請開辟的FIFO緩沖區(qū)句柄、讀取和狀態(tài)輪訓線程的引用以及對應(yīng)的句柄全部銷毀掉,防止出現(xiàn)內(nèi)存泄露導致系統(tǒng)崩潰。這個VI跟前面的第一個函數(shù)“PC_FIFO_DMA_Poly_Init_DLW30.vi”功能是反的,前面那個函數(shù)在DLL里面負責申請開辟資源,創(chuàng)建線程等等,這里的VI則負責將其全部銷毀,否則一旦發(fā)生內(nèi)存泄露,后果不堪設(shè)想。這個VI的用法也很簡單,用戶只需要選擇想要銷毀的DMA通道資源就可以了,如圖7-29所示。

圖7-29:銷毀中間層DLL里面開辟的FIFO緩沖區(qū)指針、引用句柄和線程句柄

? ? ? ??注意:最后這3個VI,一般是在退出應(yīng)用程序之前,連在一起使用的,如圖7-30所示。但是千萬需要注意的是,在執(zhí)行DMA停止、退出、銷毀這3個VI的時候,下位機FPGA里面的PCIe DMA Write不能停發(fā)數(shù)據(jù),也就是說,下位機FPGA要一直往PCIe DMA CLIP對應(yīng)的通道里面寫數(shù)據(jù),否則會造成中間層DLL里面的DMA緩沖區(qū)Read讀取線程處于-1,永不超時狀態(tài),也就是線程阻塞了,上位機應(yīng)用程序會陷入卡死狀態(tài)。因此,我們建議用戶,等到DLL里面的PCIe DMA FIFO和讀取線程銷毀之后,上位機再發(fā)送“停止寫入指令”給下位機FPGA,最后再關(guān)閉下行的PCIe通道資源。

圖7-30:退出應(yīng)用程序之前,依次調(diào)用FIFO停止、等待線程退出、銷毀FIFO和引用句柄

? ? ? ? 介紹完上行的PCIe DMA Read這7個函數(shù)之后,下面來看看我們給大家封裝的3個下行(PC-->FPGA)Write子VI,如圖7-31所示。這3個函數(shù)就可以實現(xiàn)把上位機PC端的數(shù)據(jù)或者指令或者參數(shù)直接通PCIe總線下發(fā)傳輸寫到FPGA芯片里面。

圖7-31:lvlib庫里面的3個下行PCIe通道寫函數(shù)

1)?FPGA_FIFO_Write_Pipe_Init_DLW30.vi

2) FPGA_FIFO_Write_Pipe_Send_DLW30.vi

3) FPGA_FIFO_Write_Pipe_Close_DLW30.vi

?????? ?下面我們逐一給大家講解一下這3個完成PCIe下行通信的VI含義和用法。

?????? ?1)FPGA_FIFO_Write_Pipe_Init_DLW30.vi

?????? ?這個VI可以打開用戶指定的PCIe下行(Host-->FPGA)通道并完成初始化工作,如圖7-32所示。因為我們給用戶封裝了8個下行寫通道(當然了,還有前面介紹的8個上行讀通道),因此,調(diào)用這個VI的時候,需要根據(jù)實際情況選擇一個合適的下行通道作為上位機PC發(fā)送數(shù)據(jù)給FPGA的Pipe管道,比如,我們發(fā)送的是一些指令形式的數(shù)據(jù),或者數(shù)據(jù)量非常小的一些參數(shù)等等,那么可以選擇低速的8位位寬的Channel4~7作為載體;如果我們需要快速下發(fā)一些諸如任意信號發(fā)生器的波形數(shù)據(jù),那么可以選擇吞吐率高的64位或者32位位寬的Channel0或者Channel1作為下行傳輸通道。如果下行寫通道初始化成功,這個VI會返回一個唯一的句柄“fd_write”,后面所有跟寫通道相關(guān)的函數(shù)VI都需要借助這個引用指針“fd_write”。

圖7-32:PCIe下行寫通道初始化VI

? ? ? ? 2)FPGA_FIFO_Write_Pipe_Send_DLW30.vi

?????? ?當下行的寫通道成功打開之后,我們就可以利用這里的“FPGA_FIFO_Write_Pipe_Send_DLW30.vi”函數(shù)將上位機PC端的數(shù)據(jù)下發(fā)給FPGA了,如圖7-33所示。需要注意的地方是,這個通道寫VI的數(shù)據(jù)輸入類型是字節(jié)數(shù)組,所以,如果外部的波形信號或者參數(shù)或者指令等數(shù)據(jù)類型不是字節(jié),那么我們需要通過數(shù)值選板里面的“強制類型轉(zhuǎn)換”VI先轉(zhuǎn)一下,圖7-33中顯示的是把上位機一個浮點型的正弦信號先通過I64轉(zhuǎn)成有符號64位整形數(shù)組,然后通過“強制類型轉(zhuǎn)換”變成U8字節(jié)數(shù)組給到我們的“FPGA_FIFO_Write_Pipe_Send_DLW30.vi”函數(shù),寫到FPGA芯片里面去。

圖7-33:PCIe下行通道數(shù)據(jù)發(fā)送VI(Host-->FPGA)

? ? ? ? 3)FPGA_FIFO_Write_Pipe_Close_DLW30.vi

?????? ?當我們需要退出上位機應(yīng)用程序之前,需要利用這里的“FPGA_FIFO_Write_Pipe_Close_DLW30.vi”函數(shù)來把先前打開的PCIe寫通道引用句柄指針關(guān)掉,如圖7-34所示。防止出現(xiàn)內(nèi)存泄露,更重要的是,如果不執(zhí)行關(guān)閉的話,下次再打開這個通道的時候,會提示這個通道被占用了,所以務(wù)必要檢查一下之前開啟的通道句柄是否銷毀了。

圖7-34:關(guān)閉PCIe下行寫通道引用句柄,釋放通道占用


?????? ?總結(jié):用戶在熟悉和掌握了上面介紹的這10個子函數(shù)(VI)的含義和用法之后,就可以大刀闊斧的開始編寫PCIe上位機應(yīng)用程序了。關(guān)于這部分內(nèi)容,我們會在后面的7.6和7.7節(jié)實驗部分,做詳細的講解。


LabVIEW FPGA PCIe開發(fā)講解-7.3節(jié):FPGA PCIe DMA總線通信開發(fā)過程(3個步驟)的評論 (共 條)

分享到微博請遵守國家法律
博野县| 翼城县| 石家庄市| 武夷山市| 武汉市| 延庆县| 齐河县| 尉犁县| 连南| 凤台县| 安多县| 额尔古纳市| 日照市| 昭平县| 石景山区| 江华| 衡南县| 乌兰浩特市| 黄冈市| 伊川县| 确山县| 洛浦县| 龙泉市| 万年县| 衡阳市| 永嘉县| 嘉善县| 峨山| 汪清县| 禹州市| 长春市| 石门县| 唐海县| 桂林市| 伊金霍洛旗| 从化市| 视频| 松原市| 原阳县| 南昌县| 宁德市|