国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Linux下PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解(五)

這篇具有很好參考價(jià)值的文章主要介紹了Linux下PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解(五)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

Linux下PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解(五)

本章及其以后的幾章,我們將從用戶態(tài)軟件、內(nèi)核態(tài)驅(qū)動(dòng)、FPGA邏輯介紹一個(gè)通過(guò)PCI Express總線實(shí)現(xiàn)CPU和FPGA數(shù)據(jù)通信的簡(jiǎn)單框架。

這個(gè)框架就是開(kāi)源界非常有名的RIFFA(reuseable integration framework for FPGA accelerators),它是一個(gè)FPGA加速器的一種可重用性集成框架,是一個(gè)第三方開(kāi)源PCIe框架。

該框架要求具備一個(gè)支持PCIe的工作站和一個(gè)帶有PCIe連接器的FPGA板卡。RIFFA支持windows、linux,altera和xilinx,可以通過(guò)c/c++、python、matlab、java驅(qū)動(dòng)來(lái)實(shí)現(xiàn)數(shù)據(jù)的發(fā)送和接收。驅(qū)動(dòng)程序可以在linux或windows上運(yùn)行,每一個(gè)系統(tǒng)最多支持5個(gè)FPGA device。

在用戶端有獨(dú)立的發(fā)送和接收端口,用戶只需要編寫(xiě)幾行簡(jiǎn)單代碼即可實(shí)現(xiàn)和FPGA IP內(nèi)核通信。

riffa使用直接存儲(chǔ)器訪問(wèn)(DMA)傳輸和中斷信號(hào)傳輸數(shù)據(jù)。這實(shí)現(xiàn)了PCIe鏈路上的高帶寬,運(yùn)行速率可以達(dá)到PCIe鏈路飽和點(diǎn)。

開(kāi)源地址:https://github.com/KastnerRG/riffa

一、riffa體系結(jié)構(gòu)

riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

在硬件方面,簡(jiǎn)化了接口,以便通過(guò)FIFO簡(jiǎn)便的將數(shù)據(jù)取出或存入。數(shù)據(jù)的傳輸由riffa的rx和tx DMA engine模塊用分散聚合方法來(lái)實(shí)現(xiàn)。rx engine模塊收集上位機(jī)來(lái)的有效數(shù)據(jù),收集完成發(fā)給channel模塊,tx engine收集channel模塊傳送來(lái)的數(shù)據(jù),打包發(fā)給PCI express端點(diǎn)。

在軟件方面,PC接收FPGA板卡數(shù)據(jù)是用戶應(yīng)用程序調(diào)用庫(kù)函數(shù)fpga_recv,然后由FPGA端啟動(dòng)。用戶應(yīng)用程序線程進(jìn)入內(nèi)核驅(qū)動(dòng)程序,然后開(kāi)始接收上游FPGA的讀請(qǐng)求,將數(shù)據(jù)分包發(fā)送,如果沒(méi)收到請(qǐng)求,將會(huì)等待它達(dá)到。

啟動(dòng)發(fā)送函數(shù)后,服務(wù)器將建立一個(gè)散列收集元素的列表,將數(shù)據(jù)存儲(chǔ)地址和長(zhǎng)度等信息放入其中,將其寫(xiě)入共享緩沖區(qū)。用戶應(yīng)用程序?qū)⒕彌_區(qū)地址和數(shù)據(jù)長(zhǎng)度等信息發(fā)送給FPGA。FPGA讀取散射收集數(shù)據(jù),然后發(fā)出相應(yīng)地址的數(shù)據(jù)寫(xiě)入請(qǐng)求,如果散列收集元素列表的地址有多個(gè),F(xiàn)PGA將通過(guò)中斷發(fā)出多次請(qǐng)求。

TX搬移的數(shù)據(jù)全部寫(xiě)入緩存區(qū)后,驅(qū)動(dòng)程序讀取FPGA寫(xiě)入的字節(jié)數(shù),確認(rèn)是否與發(fā)送數(shù)據(jù)長(zhǎng)度一致。這樣就完成了傳輸。其過(guò)程如下圖所示:

riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

PC機(jī)發(fā)送數(shù)據(jù)到FPGA板卡過(guò)程與PC機(jī)接收FPGA板卡數(shù)據(jù)過(guò)程相似,下圖說(shuō)明了該流程。 剛開(kāi)始也是用戶應(yīng)用程序調(diào)用庫(kù)函數(shù)fpga_send,傳輸線程進(jìn)入內(nèi)核驅(qū)動(dòng)程序,然后FPGA啟動(dòng)傳輸。

啟動(dòng)fpga_send,服務(wù)器將申請(qǐng)一些空間,將要發(fā)送的數(shù)據(jù)寫(xiě)入其中,然后建立一個(gè)分散收集列表,將存儲(chǔ)數(shù)據(jù)的地址和長(zhǎng)度放入其中,并將分散收集列表的地址和要發(fā)生的數(shù)據(jù)長(zhǎng)度等信息發(fā)給FPGA。FPGA 收到列表地址后,讀取該列表的信息,然后發(fā)出相應(yīng)地址和長(zhǎng)度的讀請(qǐng)求,然后將數(shù)據(jù)存儲(chǔ),最后一起發(fā)給FPGA板卡。

riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

驅(qū)動(dòng)程序首先調(diào)用pci_present()檢查PCI總線是否被linux內(nèi)核支持,如果系統(tǒng)支持PCI總線結(jié)構(gòu),這個(gè)函數(shù)的返回值為0,如果驅(qū)動(dòng)程序在調(diào)用這個(gè)函數(shù)時(shí)得到一個(gè)非0的返回值,那么驅(qū)動(dòng)程序就必須得中止自己的任務(wù)。調(diào)用pci_register_driver()函數(shù)來(lái)注冊(cè)PCI設(shè)備的驅(qū)動(dòng)程序,此時(shí)需要提供一個(gè)“demo_pci_driver”結(jié)構(gòu),在該結(jié)構(gòu)中給出的probe探測(cè)例程負(fù)責(zé)完成對(duì)硬件的檢測(cè)工作。

下面將從user logic -> PCIe IP -> 驅(qū)動(dòng)層 -> library-> 用戶態(tài)C++/C按照實(shí)例一一進(jìn)行分析,包括理論基礎(chǔ)、實(shí)際操作、源代碼分析。

首先我們先從FPGA xilinx integrated block for PCI express分析,因?yàn)檫@個(gè)有承上啟下的作用。

二、PCIe hard IP分析

1. PCIE IP 核配置

AXI總線時(shí)鐘選擇62.5M,AXI總線接口位寬設(shè)置為64bit。
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

在IDs界面是PCIe設(shè)備的相關(guān)信息,主機(jī)在上電時(shí)BIOS系統(tǒng)中識(shí)別到的PCIe設(shè)備,就是通過(guò)這些ID號(hào)來(lái)進(jìn)行識(shí)別的。

在本實(shí)驗(yàn)中,關(guān)于ID的設(shè)定全部保持為默認(rèn)值即可,若用戶對(duì)ID進(jìn)行了更改,可能導(dǎo)致計(jì)算機(jī)在啟動(dòng)時(shí)不能正確識(shí)別設(shè)備從而導(dǎo)致藍(lán)屏死機(jī)。

Vendor ID是廠商ID,本實(shí)驗(yàn)中的廠商ID代值的就是Xilinx;

Device ID代表了PCIe設(shè)備,其中7指的是Xilinx 7 系列FPGA,02指的是使用的PCIe 2.0的協(xié)議,1指的是含有一個(gè)PCIe的傳輸lane;

Base class Menu指的是PCIe設(shè)備的種類,常見(jiàn)的有聲卡、顯卡、網(wǎng)卡等,各種不同種類的設(shè)備都有其對(duì)應(yīng)的驅(qū)動(dòng),若驅(qū)動(dòng)與其PCIe的種類不對(duì)應(yīng),就會(huì)導(dǎo)致系統(tǒng)的內(nèi)存訪問(wèn)錯(cuò)誤,從而導(dǎo)致藍(lán)屏。
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

在PCIe的bars配置界面對(duì)PCIe的bar進(jìn)行設(shè)置,BAR空間對(duì)應(yīng)的就是在內(nèi)存中開(kāi)辟一段空間用于存放PCIe設(shè)備的信息。只使用到一個(gè)bar0一個(gè)bar且將其內(nèi)存空間的大小設(shè)置為1k。
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

IP核的負(fù)載選擇最大負(fù)載長(zhǎng)度為512字節(jié),勾選對(duì)數(shù)據(jù)進(jìn)行緩沖。
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

在中斷配置界面,取消勾選傳統(tǒng)類型的中斷,只選擇消息類型的中斷。
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

在share logic界面取消勾選包含其他邏輯,這樣在PCIe的IP核中就包含了全部功能。
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

在IP核接口參數(shù)配置界面,只選擇其中用于配置核控制的參數(shù),這是由于riffa框架的特性所提供的。
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

下面代碼是實(shí)際的top level,

PCIeGen1x4If64 PCIeGen1x4If64_i
        (//---------------------------------------------------------------------
         // PCI Express (pci_exp) Interface                                     
         //---------------------------------------------------------------------
         // Tx
         .pci_exp_txn                               ( PCI_EXP_TXN ),
         .pci_exp_txp                               ( PCI_EXP_TXP ),        
         // Rx
         .pci_exp_rxn                               ( PCI_EXP_RXN ),
         .pci_exp_rxp                               ( PCI_EXP_RXP ),        
         //---------------------------------------------------------------------
         // AXI-S Interface                                                     
         //---------------------------------------------------------------------
         // Common
         .user_clk_out                              ( user_clk ),
         .user_reset_out                            ( user_reset ),
         .user_lnk_up                               ( user_lnk_up ),
         .user_app_rdy                              ( user_app_rdy ),
         // TX
         .s_axis_tx_tready                          ( s_axis_tx_tready ),
         .s_axis_tx_tdata                           ( s_axis_tx_tdata ),
         .s_axis_tx_tkeep                           ( s_axis_tx_tkeep ),
         .s_axis_tx_tuser                           ( s_axis_tx_tuser ),
         .s_axis_tx_tlast                           ( s_axis_tx_tlast ),
         .s_axis_tx_tvalid                          ( s_axis_tx_tvalid ),
         // Rx
         .m_axis_rx_tdata                           ( m_axis_rx_tdata ),
         .m_axis_rx_tkeep                           ( m_axis_rx_tkeep ),
         .m_axis_rx_tlast                           ( m_axis_rx_tlast ),
         .m_axis_rx_tvalid                          ( m_axis_rx_tvalid ),
         .m_axis_rx_tready                          ( m_axis_rx_tready ),
         .m_axis_rx_tuser                           ( m_axis_rx_tuser ),
         .tx_cfg_gnt                                ( tx_cfg_gnt ),
         .rx_np_ok                                  ( rx_np_ok ),
         .rx_np_req                                 ( rx_np_req ),
         .cfg_trn_pending                           ( cfg_trn_pending ),
         .cfg_pm_halt_aspm_l0s                      ( cfg_pm_halt_aspm_l0s ),
         .cfg_pm_halt_aspm_l1                       ( cfg_pm_halt_aspm_l1 ),
         .cfg_pm_force_state_en                     ( cfg_pm_force_state_en ),
         .cfg_pm_force_state                        ( cfg_pm_force_state ),
         .cfg_dsn                                   ( cfg_dsn ),
         .cfg_turnoff_ok                            ( cfg_turnoff_ok ),
         .cfg_pm_wake                               ( cfg_pm_wake ),
         .cfg_pm_send_pme_to                        ( 1'b0 ),
         .cfg_ds_bus_number                         ( 8'b0 ),
         .cfg_ds_device_number                      ( 5'b0 ),
         .cfg_ds_function_number                    ( 3'b0 ),
         //---------------------------------------------------------------------
         // Flow Control Interface                                              
         //---------------------------------------------------------------------
         .fc_cpld                                   ( fc_cpld ),
         .fc_cplh                                   ( fc_cplh ),
         .fc_npd                                    ( fc_npd ),
         .fc_nph                                    ( fc_nph ),
         .fc_pd                                     ( fc_pd ),
         .fc_ph                                     ( fc_ph ),
         .fc_sel                                    ( fc_sel ),
         //---------------------------------------------------------------------
         // Configuration (CFG) Interface                                       
         //---------------------------------------------------------------------
         .cfg_device_number                         ( cfg_device_number ),
         .cfg_dcommand2                             ( cfg_dcommand2 ),
         .cfg_pmcsr_pme_status                      ( cfg_pmcsr_pme_status ),
         .cfg_status                                ( cfg_status ),
         .cfg_to_turnoff                            ( cfg_to_turnoff ),
         .cfg_received_func_lvl_rst                 ( cfg_received_func_lvl_rst ),
         .cfg_dcommand                              ( cfg_dcommand ),
         .cfg_bus_number                            ( cfg_bus_number ),
         .cfg_function_number                       ( cfg_function_number ),
         .cfg_command                               ( cfg_command ),
         .cfg_dstatus                               ( cfg_dstatus ),
         .cfg_lstatus                               ( cfg_lstatus ),
         .cfg_pcie_link_state                       ( cfg_pcie_link_state ),
         .cfg_lcommand                              ( cfg_lcommand ),
         .cfg_pmcsr_pme_en                          ( cfg_pmcsr_pme_en ),
         .cfg_pmcsr_powerstate                      ( cfg_pmcsr_powerstate ),
         //------------------------------------------------//
         // EP Only                                        //
         //------------------------------------------------//
         .cfg_interrupt                             ( cfg_interrupt ),
         .cfg_interrupt_rdy                         ( cfg_interrupt_rdy ),
         .cfg_interrupt_assert                      ( cfg_interrupt_assert ),
         .cfg_interrupt_di                          ( cfg_interrupt_di ),
         .cfg_interrupt_do                          ( cfg_interrupt_do ),
         .cfg_interrupt_mmenable                    ( cfg_interrupt_mmenable ),
         .cfg_interrupt_msienable                   ( cfg_interrupt_msienable ),
         .cfg_interrupt_msixenable                  ( cfg_interrupt_msixenable ),
         .cfg_interrupt_msixfm                      ( cfg_interrupt_msixfm ),
         .cfg_interrupt_stat                        ( cfg_interrupt_stat ),
         .cfg_pciecap_interrupt_msgnum              ( cfg_pciecap_interrupt_msgnum ),
         //---------------------------------------------------------------------
         // System  (SYS) Interface                                             
         //---------------------------------------------------------------------
         .sys_clk                                    ( pcie_refclk ),
         .sys_rst_n                                  ( pcie_reset_n )
         );

從頂層代碼接口可以看出來(lái),TX/RX差分信號(hào)、AXIS數(shù)據(jù)common接口信號(hào)、tx/rx數(shù)據(jù)面信號(hào)、FC流控信號(hào)、configuration(CFG)interface、EP中斷信號(hào)、系統(tǒng)時(shí)鐘/復(fù)位信號(hào)。

詳細(xì)使用參考xilinx PCIe spec官方文檔。

PCIe IP位于整個(gè)設(shè)計(jì)架構(gòu)的這個(gè)位置:
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

2. tx_engine和rx_engine

下面我們分析一下tx_engine和rx_engine這兩個(gè)核心模塊,這兩個(gè)模塊負(fù)責(zé)轉(zhuǎn)換axis data和tlp data。

我們先看一下top level的源代碼:

riffa_wrapper_ac701
        #(/*AUTOINSTPARAM*/
          // Parameters
          .C_LOG_NUM_TAGS               (C_LOG_NUM_TAGS),
          .C_NUM_CHNL                   (C_NUM_CHNL),
          .C_PCI_DATA_WIDTH             (C_PCI_DATA_WIDTH),
          .C_MAX_PAYLOAD_BYTES          (C_MAX_PAYLOAD_BYTES))
    riffa
        (
         // Outputs
         .CFG_INTERRUPT                 (cfg_interrupt),
         .M_AXIS_RX_TREADY              (m_axis_rx_tready),
         .S_AXIS_TX_TDATA               (s_axis_tx_tdata[C_PCI_DATA_WIDTH-1:0]),
         .S_AXIS_TX_TKEEP               (s_axis_tx_tkeep[(C_PCI_DATA_WIDTH/8)-1:0]),
         .S_AXIS_TX_TLAST               (s_axis_tx_tlast),
         .S_AXIS_TX_TVALID              (s_axis_tx_tvalid),
         .S_AXIS_TX_TUSER               (s_axis_tx_tuser[`SIG_XIL_TX_TUSER_W-1:0]),
         .FC_SEL                        (fc_sel[`SIG_FC_SEL_W-1:0]),
         .RST_OUT                       (rst_out),
         .CHNL_RX                       (chnl_rx[C_NUM_CHNL-1:0]),
         .CHNL_RX_LAST                  (chnl_rx_last[C_NUM_CHNL-1:0]),
         .CHNL_RX_LEN                   (chnl_rx_len[(C_NUM_CHNL*`SIG_CHNL_LENGTH_W)-1:0]),
         .CHNL_RX_OFF                   (chnl_rx_off[(C_NUM_CHNL*`SIG_CHNL_OFFSET_W)-1:0]),
         .CHNL_RX_DATA                  (chnl_rx_data[(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0]),
         .CHNL_RX_DATA_VALID            (chnl_rx_data_valid[C_NUM_CHNL-1:0]),
         .CHNL_TX_ACK                   (chnl_tx_ack[C_NUM_CHNL-1:0]),
         .CHNL_TX_DATA_REN              (chnl_tx_data_ren[C_NUM_CHNL-1:0]),
         // Inputs
         .M_AXIS_RX_TDATA               (m_axis_rx_tdata[C_PCI_DATA_WIDTH-1:0]),
         .M_AXIS_RX_TKEEP               (m_axis_rx_tkeep[(C_PCI_DATA_WIDTH/8)-1:0]),
         .M_AXIS_RX_TLAST               (m_axis_rx_tlast),
         .M_AXIS_RX_TVALID              (m_axis_rx_tvalid),
         .M_AXIS_RX_TUSER               (m_axis_rx_tuser[`SIG_XIL_RX_TUSER_W-1:0]),
         .S_AXIS_TX_TREADY              (s_axis_tx_tready),
         .CFG_BUS_NUMBER                (cfg_bus_number[`SIG_BUSID_W-1:0]),
         .CFG_DEVICE_NUMBER             (cfg_device_number[`SIG_DEVID_W-1:0]),
         .CFG_FUNCTION_NUMBER           (cfg_function_number[`SIG_FNID_W-1:0]),
         .CFG_COMMAND                   (cfg_command[`SIG_CFGREG_W-1:0]),
         .CFG_DCOMMAND                  (cfg_dcommand[`SIG_CFGREG_W-1:0]),
         .CFG_LSTATUS                   (cfg_lstatus[`SIG_CFGREG_W-1:0]),
         .CFG_LCOMMAND                  (cfg_lcommand[`SIG_CFGREG_W-1:0]),
         .FC_CPLD                       (fc_cpld[`SIG_FC_CPLD_W-1:0]),
         .FC_CPLH                       (fc_cplh[`SIG_FC_CPLH_W-1:0]),
         .CFG_INTERRUPT_MSIEN           (cfg_interrupt_msienable),// TODO: Rename
         .CFG_INTERRUPT_RDY             (cfg_interrupt_rdy),
         .USER_CLK                      (user_clk),
         .USER_RESET                    (user_reset),
         .CHNL_RX_CLK                   (chnl_rx_clk[C_NUM_CHNL-1:0]),
         .CHNL_RX_ACK                   (chnl_rx_ack[C_NUM_CHNL-1:0]),
         .CHNL_RX_DATA_REN              (chnl_rx_data_ren[C_NUM_CHNL-1:0]),
         .CHNL_TX_CLK                   (chnl_tx_clk[C_NUM_CHNL-1:0]),
         .CHNL_TX                       (chnl_tx[C_NUM_CHNL-1:0]),
         .CHNL_TX_LAST                  (chnl_tx_last[C_NUM_CHNL-1:0]),
         .CHNL_TX_LEN                   (chnl_tx_len[(C_NUM_CHNL*`SIG_CHNL_LENGTH_W)-1:0]),
         .CHNL_TX_OFF                   (chnl_tx_off[(C_NUM_CHNL*`SIG_CHNL_OFFSET_W)-1:0]),
         .CHNL_TX_DATA                  (chnl_tx_data[(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0]),
         .CHNL_TX_DATA_VALID            (chnl_tx_data_valid[C_NUM_CHNL-1:0]),
         .RX_NP_OK                      (rx_np_ok),
         .TX_CFG_GNT                    (tx_cfg_gnt),
         .RX_NP_REQ                     (rx_np_req)
         /*AUTOINST*/);

這個(gè)模塊可以通過(guò)C_NUM_CHNL配置通道個(gè)數(shù),C_PCI_DATA_WIDTH配置PCIe data的位寬,C_LOG_NUM_TAGS配置PCIe tag的個(gè)數(shù)。

module riffa_wrapper_ac701負(fù)責(zé)將xilinx PCIe IP的TX、RX、Configuration、flow control、中斷信號(hào)轉(zhuǎn)換為riffa的輸入輸出信號(hào)。

閱讀riffa_wrapper_ac701.v源代碼發(fā)現(xiàn)這個(gè)模塊分為兩個(gè)模塊:

· translation_xilinx
· engine_layer
· riffa

transtion_xilinx:負(fù)責(zé)提供統(tǒng)一的PCIe接口信息,比如altera、xilinx;

engine_layer:負(fù)責(zé)封裝了tx_engine和rx_engine。其中tx engine負(fù)責(zé)上傳DMA通道(寫(xiě)通道),即Interface: TX Classic;rx engine負(fù)責(zé)下發(fā)DMA通道(讀通道),即Interface: RX Classic;

riffa:負(fù)責(zé)將tx/rx engine的信號(hào)轉(zhuǎn)換為user logic的通道信號(hào),方便我們使用,接口代碼如下:

     input [C_NUM_CHNL-1:0]                     CHNL_RX_CLK, 
     output [C_NUM_CHNL-1:0]                    CHNL_RX, 
     input [C_NUM_CHNL-1:0]                     CHNL_RX_ACK, 
     output [C_NUM_CHNL-1:0]                    CHNL_RX_LAST, 
     output [(C_NUM_CHNL*32)-1:0]               CHNL_RX_LEN, 
     output [(C_NUM_CHNL*31)-1:0]               CHNL_RX_OFF, 
     output [(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0] CHNL_RX_DATA, 
     output [C_NUM_CHNL-1:0]                    CHNL_RX_DATA_VALID, 
     input [C_NUM_CHNL-1:0]                     CHNL_RX_DATA_REN,
    
     input [C_NUM_CHNL-1:0]                     CHNL_TX_CLK, 
     input [C_NUM_CHNL-1:0]                     CHNL_TX, 
     output [C_NUM_CHNL-1:0]                    CHNL_TX_ACK,
     input [C_NUM_CHNL-1:0]                     CHNL_TX_LAST, 
     input [(C_NUM_CHNL*32)-1:0]                CHNL_TX_LEN, 
     input [(C_NUM_CHNL*31)-1:0]                CHNL_TX_OFF, 
     input [(C_NUM_CHNL*C_PCI_DATA_WIDTH)-1:0]  CHNL_TX_DATA, 
     input [C_NUM_CHNL-1:0]                     CHNL_TX_DATA_VALID, 
     output [C_NUM_CHNL-1:0]                    CHNL_TX_DATA_REN

對(duì)應(yīng)整個(gè)實(shí)際框架的這一部分,如下圖所示:
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

3. user logic

經(jīng)過(guò)tx engine和rx engine模塊,輸出CHNL_RX_*和CHNL_TX_*信號(hào),下面我們看一下user如何使用的,源代碼如下:

generate
    for (chnl = 0; chnl < C_NUM_CHNL; chnl = chnl + 1) begin : test_channels
        chnl_tester 
                #(
                  .C_PCI_DATA_WIDTH(C_PCI_DATA_WIDTH)
                  ) 
        module1 
                (.CLK(user_clk),
                 .RST(rst_out),    // riffa_reset includes riffa_endpoint resets
                 // Rx interface
                 .CHNL_RX_CLK(chnl_rx_clk[chnl]), 
                 .CHNL_RX(chnl_rx[chnl]), 
                 .CHNL_RX_ACK(chnl_rx_ack[chnl]), 
                 .CHNL_RX_LAST(chnl_rx_last[chnl]), 
                 .CHNL_RX_LEN(chnl_rx_len[32*chnl +:32]), 
                 .CHNL_RX_OFF(chnl_rx_off[31*chnl +:31]), 
                 .CHNL_RX_DATA(chnl_rx_data[C_PCI_DATA_WIDTH*chnl +:C_PCI_DATA_WIDTH]), 
                 .CHNL_RX_DATA_VALID(chnl_rx_data_valid[chnl]), 
                 .CHNL_RX_DATA_REN(chnl_rx_data_ren[chnl]),

                 // Tx interface
                 .CHNL_TX_CLK(chnl_tx_clk[chnl]), 
                 .CHNL_TX(chnl_tx[chnl]), 
                 .CHNL_TX_ACK(chnl_tx_ack[chnl]), 
                 .CHNL_TX_LAST(chnl_tx_last[chnl]), 
                 .CHNL_TX_LEN(chnl_tx_len[32*chnl +:32]), 
                 .CHNL_TX_OFF(chnl_tx_off[31*chnl +:31]), 
                 .CHNL_TX_DATA(chnl_tx_data[C_PCI_DATA_WIDTH*chnl +:C_PCI_DATA_WIDTH]), 
                 .CHNL_TX_DATA_VALID(chnl_tx_data_valid[chnl]), 
                 .CHNL_TX_DATA_REN(chnl_tx_data_ren[chnl])
                 );    
    end
endgenerate

這個(gè)模塊的用于執(zhí)行RIFFA TX 和 RX 接口。在RX接口上接收數(shù)據(jù)并保存最后接收的值。在TX接口上發(fā)送回相同數(shù)量的數(shù)據(jù)。返回的數(shù)據(jù)從接收到的最后一個(gè)值開(kāi)始,重置并遞增,直到等于TX接口上發(fā)回的(4字節(jié))字?jǐn)?shù)的值結(jié)束。
riffa: bad number of channels,PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解,linux,驅(qū)動(dòng)開(kāi)發(fā),fpga開(kāi)發(fā),c語(yǔ)言

三、總結(jié)

這篇文章通過(guò)經(jīng)典開(kāi)源項(xiàng)目RIIFA的FPGA部分,結(jié)合源代碼詳細(xì)分析了框架部分的Xilinx PCIe hard IP、TX/RX engine和RIFFA模塊,最后結(jié)合了user logic部分的chnl_tester,介紹了如何使用CHNL_TX_*和CHNL_RX_*接口。

四、未完待續(xù)

Linux下PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解(六),將結(jié)合經(jīng)典開(kāi)源項(xiàng)目RIIFA,詳細(xì)介紹內(nèi)核態(tài)驅(qū)動(dòng)的設(shè)計(jì)、開(kāi)發(fā)、安裝等。

五、參考資料

https://blog.csdn.net/qq_41332806/article/details/105864632文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-783896.html

到了這里,關(guān)于Linux下PCI設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解(五)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 宋寶華《Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解》 宋老師csdn上分享的網(wǎng)盤(pán)已失效,特意新增的。

    https://pan.baidu.com/s/1rCbRUmnDtjE4jHNB5eQ8CQ 提取碼:t12r 案例代碼: https://pan.baidu.com/s/1lSMGxLnEFwO0aJGORqx8Og 提取碼: bglj Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解:基于最新的Linux4.0內(nèi)核 (電子與嵌入式系統(tǒng)設(shè)計(jì)叢書(shū)) (宋寶華 著)電子書(shū): https://download.csdn.net/download/MINGTING1323/86831055

    2024年02月13日
    瀏覽(20)
  • Linux驅(qū)動(dòng)開(kāi)發(fā)筆記(四):設(shè)備驅(qū)動(dòng)介紹、熟悉雜項(xiàng)設(shè)備驅(qū)動(dòng)和ubuntu開(kāi)發(fā)雜項(xiàng)設(shè)備Demo

    Linux驅(qū)動(dòng)開(kāi)發(fā)筆記(四):設(shè)備驅(qū)動(dòng)介紹、熟悉雜項(xiàng)設(shè)備驅(qū)動(dòng)和ubuntu開(kāi)發(fā)雜項(xiàng)設(shè)備Demo

    若該文為原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明原文出處 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/134533533 紅胖子網(wǎng)絡(luò)科技博文大全:開(kāi)發(fā)技術(shù)集合(包含Qt實(shí)用技術(shù)、樹(shù)莓派、三維、OpenCV、OpenGL、ffmpeg、OSG、單片機(jī)、軟硬結(jié)合等等)持續(xù)更新中… 上一篇:《Linux驅(qū)動(dòng)開(kāi)發(fā)筆記(三

    2024年02月05日
    瀏覽(50)
  • 設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解

    設(shè)備驅(qū)動(dòng)程序是嵌入式系統(tǒng)中與硬件設(shè)備交互的關(guān)鍵部分。它負(fù)責(zé)將操作系統(tǒng)與硬件設(shè)備之間進(jìn)行有效的通信和數(shù)據(jù)交換。在本篇博客中,我們將詳細(xì)介紹設(shè)備驅(qū)動(dòng)開(kāi)發(fā)的過(guò)程,并提供C語(yǔ)言實(shí)例幫助理解。 1.1 設(shè)備驅(qū)動(dòng)概述 設(shè)備驅(qū)動(dòng)程序是在操作系統(tǒng)中實(shí)現(xiàn)設(shè)備與應(yīng)用程序之

    2024年02月04日
    瀏覽(50)
  • 4、Linux驅(qū)動(dòng)開(kāi)發(fā):設(shè)備-設(shè)備號(hào)&設(shè)備號(hào)注冊(cè)

    4、Linux驅(qū)動(dòng)開(kāi)發(fā):設(shè)備-設(shè)備號(hào)&設(shè)備號(hào)注冊(cè)

    ??點(diǎn)擊這里查看所有博文 ??隨著自己工作的進(jìn)行,接觸到的技術(shù)棧也越來(lái)越多。給我一個(gè)很直觀的感受就是,某一項(xiàng)技術(shù)/經(jīng)驗(yàn)在剛開(kāi)始接觸的時(shí)候都記得很清楚。往往過(guò)了幾個(gè)月都會(huì)忘記的差不多了,只有經(jīng)常會(huì)用到的東西才有可能真正記下來(lái)。存在很多在特殊情況下有

    2024年02月15日
    瀏覽(44)
  • Linux驅(qū)動(dòng)開(kāi)發(fā)實(shí)戰(zhàn)(一)——設(shè)備驅(qū)動(dòng)模型

    Linux驅(qū)動(dòng)開(kāi)發(fā)實(shí)戰(zhàn)(一)——設(shè)備驅(qū)動(dòng)模型

    在早期的Linux內(nèi)核中并沒(méi)有為設(shè)備驅(qū)動(dòng)提供統(tǒng)一的設(shè)備模型。隨著內(nèi)核的不斷擴(kuò)大及系統(tǒng)更加復(fù)雜,編寫(xiě)一個(gè)驅(qū)動(dòng)程序越來(lái)越困難,所以在Linux2.6內(nèi)核中添加了一個(gè)統(tǒng)一的設(shè)備模型。這樣,寫(xiě)設(shè)備驅(qū)動(dòng)程序就稍微容易一些了。本章將對(duì)設(shè)備模型進(jìn)行詳細(xì)的介紹。 設(shè)備驅(qū)動(dòng)模型

    2024年02月16日
    瀏覽(26)
  • Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā) - 虛擬時(shí)鐘Clock驅(qū)動(dòng)示例

    Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā) - 虛擬時(shí)鐘Clock驅(qū)動(dòng)示例

    By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜歡的盆友歡迎點(diǎn)贊和訂閱! 你的喜歡就是我寫(xiě)作的動(dòng)力! 很多設(shè)備里面系統(tǒng)時(shí)鐘架構(gòu)極其復(fù)雜,讓學(xué)習(xí)Clock驅(qū)動(dòng)的盆友頭大。這里我參考S3C2440的clock驅(qū)動(dòng)寫(xiě)了一個(gè)virtual clock,即虛擬時(shí)鐘驅(qū)動(dòng),分別包含clock的provider和

    2023年04月21日
    瀏覽(27)
  • Linux -- 字符設(shè)備驅(qū)動(dòng)--LED的驅(qū)動(dòng)開(kāi)發(fā)(初級(jí)框架)

    Linux -- 字符設(shè)備驅(qū)動(dòng)--LED的驅(qū)動(dòng)開(kāi)發(fā)(初級(jí)框架)

    看原理圖確定引腳,確定引腳輸出什么電平才能點(diǎn)亮 / 熄滅 LED 看主芯片手冊(cè),確定寄存器操作方法:哪些寄存器?哪些位?地址是? 編寫(xiě)驅(qū)動(dòng):先寫(xiě)框架,再寫(xiě)硬件操作的代碼 注意 :在芯片手冊(cè)中確定的寄存器地址被稱為 物理地址 ,在 Linux 內(nèi)核中無(wú)法直接使用。 需要使

    2024年04月28日
    瀏覽(27)
  • 嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā) 04:基于設(shè)備樹(shù)的驅(qū)動(dòng)開(kāi)發(fā)

    嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā) 04:基于設(shè)備樹(shù)的驅(qū)動(dòng)開(kāi)發(fā)

    前面文章 《嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā) 03:平臺(tái)(platform)總線驅(qū)動(dòng)模型》 引入了資源和驅(qū)動(dòng)分離的概念,這篇文章將在前面基礎(chǔ)上更進(jìn)一步,引入設(shè)備樹(shù)的概念。 在平臺(tái)總線驅(qū)動(dòng)模型中資源和驅(qū)動(dòng)已經(jīng)從邏輯上和代碼組織上進(jìn)行了分離,但每次調(diào)整資源還是會(huì)涉及到內(nèi)核,所以現(xiàn)

    2024年02月16日
    瀏覽(27)
  • 正點(diǎn)原子嵌入式linux驅(qū)動(dòng)開(kāi)發(fā)——Linux 網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)

    正點(diǎn)原子嵌入式linux驅(qū)動(dòng)開(kāi)發(fā)——Linux 網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)

    網(wǎng)絡(luò)驅(qū)動(dòng)是linux里面驅(qū)動(dòng)三巨頭之一 ,linux下的網(wǎng)絡(luò)功能非常強(qiáng)大,嵌入式linux中也常常用到網(wǎng)絡(luò)功能。前面已經(jīng)講過(guò)了字符設(shè)備驅(qū)動(dòng)和塊設(shè)備驅(qū)動(dòng),本章就來(lái)學(xué)習(xí)一下linux里面的 網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng) 。 本次筆記中討論的都是有線網(wǎng)絡(luò)! 提起網(wǎng)絡(luò),一般想到的硬件就是“網(wǎng)卡”。在

    2024年01月17日
    瀏覽(25)
  • 嵌入式Linux系統(tǒng)中的設(shè)備驅(qū)動(dòng)開(kāi)發(fā):從設(shè)備樹(shù)到驅(qū)動(dòng)實(shí)現(xiàn)

    嵌入式Linux系統(tǒng)中的設(shè)備驅(qū)動(dòng)開(kāi)發(fā):從設(shè)備樹(shù)到驅(qū)動(dòng)實(shí)現(xiàn)

    大家好,今天給大家介紹 嵌入式Linux系統(tǒng)中的設(shè)備驅(qū)動(dòng)開(kāi)發(fā):從設(shè)備樹(shù)到驅(qū)動(dòng)實(shí)現(xiàn) ,文章末尾附有分享大家一個(gè)資料包,差不多150多G。里面學(xué)習(xí)內(nèi)容、面經(jīng)、項(xiàng)目都比較新也比較全! 可進(jìn)群免費(fèi)領(lǐng)取。 在嵌入式Linux系統(tǒng)中,設(shè)備驅(qū)動(dòng)是連接硬件設(shè)備和操作系統(tǒng)之間的橋梁。

    2024年02月19日
    瀏覽(25)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包