<form id="xtxpd"></form>

<address id="xtxpd"><nobr id="xtxpd"><progress id="xtxpd"></progress></nobr></address>

    <noframes id="xtxpd">

    歡迎來到坤馳科技官方網站!
    掃描二維碼

    全國咨詢電話:
    400-000-4026

    當前位置:首頁 » 技術支持 » 基于PCI總線的高速數據采集卡的linux驅動

    基于PCI總線的高速數據采集卡的linux驅動

    文章出處:坤馳科技網責任編輯:坤馳科技研發部作者:坤馳科技人氣:-發表時間:2015-05-06 09:13:00

      一、PCI總線系統體系結構

      PCI是外圍設備互連(PeripheralComponentInterconnect)的簡稱,作為一種通用的總線接口標準,它在目前的計算機系統中得到了非常廣泛的應用。PCI提供了一組完整的總線接口規范,其目的是描述如何將計算機系統中的外圍設備以一種結構化和可控化的方式連接在一起,同時它還刻畫了外圍設備在連接時的電氣特性和行為規約,并且詳細定義了計算機系統中的各個不同部件之間應該如何正確地進行交互。

      無論是在基于Intel芯片的PC機中,或是在基于Alpha芯片的工作站上,PCI毫無疑問都是目前使用廣泛的一種總線接口標準。同舊式的ISA總線不同,PCI將計算機系統中的總線子系統與存儲子系統完全地分開,CPU通過一塊稱為PCI橋(PCI-Bridge)的設備來完成同總線子系統的交互,如圖1所示。
     



      圖1PCI子系統的體系結構


      由于使用了更高的時鐘頻率,因此PCI總線能夠獲得比ISA總線更好的整體性能。PCI總線的時鐘頻率一般在25MHz到33MHz范圍內,有些甚至能夠達到66MHz或者133MHz,而在64位系統中則高能達到266MHz。盡管目前PCI設備大多采用32位數據總線,但PCI規范中已經給出了64位的擴展實現,從而使PCI總線能夠更好地實現平臺無關性,現在PCI總線已經能夠用于IA-32、Alpha、PowerPC、SPARC64和IA-64等體系結構中。

      PCI總線具有三個非常顯著的優點,使得它能夠完成終取代ISA總線這一歷史使命:

      在計算機和外設間傳輸數據時具有更好的性能;

      能夠盡量獨立于具體的平臺;

      可以很方便地實現即插即用。

      圖2是一個典型的基于PCI總線的計算機系統邏輯示意圖,系統的各個部分通過PCI總線和PCI-PCI橋連接在一起。從圖中不難看出,CPU和RAM需要通過PCI橋連接到PCI總線0(即主PCI總線),而具有PCI接口的顯卡則可以直接連接到主PCI總線上。PCI-PCI橋是一個特殊的PCI設備,它負責將PCI總線0和PCI總線1(即從PCI主線)連接在一起,通常PCI總線1稱為PCI-PCI橋的下游(downstream),而PCI總線0則稱為PCI-PCI橋的上游(upstream)。圖中連接到從PCI總線上的是SCSI卡和以太網卡。為了兼容舊的ISA總線標準,PCI總線還可以通過PCI-ISA橋來連接ISA總線,從而能夠支持以前的ISA設備。圖中ISA總線上連接著一個多功能I/O控制器,用于控制鍵盤、鼠標和軟驅。
     


      圖2PCI系統示意圖



      在此我只對PCI總線系統體系結構作了概括性介紹,如果讀者想進一步了解,DavidARusling在TheLinuxKernel(http://tldp.org/LDP/tlk/dd/pci.html)中對Linux的PCI子系統有比較詳細的介紹。

      二、Linux驅動程序框架

      Linux將所有外部設備看成是一類特殊文件,稱之為“設備文件”,如果說系統調用是Linux內核和應用程序之間的接口,那么設備驅動程序則可以看成是Linux內核與外部設備之間的接口。設備驅動程序向應用程序屏蔽了硬件在實現上的細節,使得應用程序可以像操作普通文件一樣來操作外部設備。

      1.字符設備和塊設備

      Linux抽象了對硬件的處理,所有的硬件設備都可以像普通文件一樣來看待:它們可以使用和操作文件相同的、標準的系統調用接口來完成打開、關閉、讀寫和I/O控制操作,而驅動程序的主要任務也就是要實現這些系統調用函數。Linux系統中的所有硬件設備都使用一個特殊的設備文件來表示,例如,系統中的個IDE硬盤使用/dev/hda表示。每個設備文件對應有兩個設備號:一個是主設備號,標識該設備的種類,也標識了該設備所使用的驅動程序;另一個是次設備號,標識使用同一設備驅動程序的不同硬件設備。設備文件的主設備號必須與設備驅動程序在登錄該設備時申請的主設備號一致,否則用戶進程將無法訪問到設備驅動程序。

      在Linux操作系統下有兩類主要的設備文件:一類是字符設備,另一類則是塊設備。字符設備是以字節為單位逐個進行I/O操作的設備,在對字符設備發出讀寫請求時,實際的硬件I/O緊接著就發生了,一般來說字符設備中的緩存是可有可無的,而且也不支持隨機訪問。塊設備則是利用一塊系統內存作為緩沖區,當用戶進程對設備進行讀寫請求時,驅動程序先查看緩沖區中的內容,如果緩沖區中的數據能滿足用戶的要求就返回相應的數據,否則就調用相應的請求函數來進行實際的I/O操作。塊設備主要是針對磁盤等慢速設備設計的,其目的是避免耗費過多的CPU時間來等待操作的完成。一般說來,PCI卡通常都屬于字符設備。

      所有已經注冊(即已經加載了驅動程序)的硬件設備的主設備號可以從/proc/devices文件中得到。使用mknod命令可以創建指定類型的設備文件,同時為其分配相應的主設備號和次設備號。例如,下面的命令:

      [root@garyroot]#mknod/dev/lp0c60

      將建立一個主設備號為6,次設備號為0的字符設備文件/dev/lp0。當應用程序對某個設備文件進行系統調用時,Linux內核會根據該設備文件的設備類型和主設備號調用相應的驅動程序,并從用戶態進入到核心態,再由驅動程序判斷該設備的次設備號,終完成對相應硬件的操作。

      2.設備驅動程序接口

      Linux中的I/O子系統向內核中的其他部分提供了一個統一的標準設備接口,這是通過include/linux/fs.h中的數據結構file_operations來完成的:

      structfile_operations{

      structmodule*owner;

      loff_t(*llseek)(structfile*,loff_t,int);

      ssize_t(*read)(structfile*,char*,size_t,loff_t*);

      ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);

      int(*readdir)(structfile*,void*,filldir_t);

      unsignedint(*poll)(structfile*,structpoll_table_struct*);

      int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);

      int(*mmap)(structfile*,structvm_area_struct*);

      int(*open)(structinode*,structfile*);

      int(*flush)(structfile*);

      int(*release)(structinode*,structfile*);

      int(*fsync)(structfile*,structdentry*,intdatasync);

      int(*fasync)(int,structfile*,int);

      int(*lock)(structfile*,int,structfile_lock*);

      ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);

      ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);

      ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);

      unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,

      unsignedlong,unsignedlong,unsignedlong);

      };

      當應用程序對設備文件進行諸如open、close、read、write等操作時,Linux內核將通過file_operations結構訪問驅動程序提供的函數。例如,當應用程序對設備文件執行讀操作時,內核將調用file_operations結構中的read函數。

      2.設備驅動程序模塊

      Linux下的設備驅動程序可以按照兩種方式進行編譯,一種是直接靜態編譯成內核的一部分,另一種則是編譯成可以動態加載的模塊。如果編譯進內核的話,會增加內核的大小,還要改動內核的源文件,而且不能動態地卸載,不利于調試,所有推薦使用模塊方式。

      從本質上來講,模塊也是內核的一部分,它不同于普通的應用程序,不能調用位于用戶態下的C或者C++庫函數,而只能調用Linux內核提供的函數,在/proc/ksyms中可以查看到內核提供的所有函數。

      在以模塊方式編寫驅動程序時,要實現兩個必不可少的函數init_module()和cleanup_module(),而且至少要包含 兩個頭文件。在用gcc編譯內核模塊時,需要加上-DMODULE-D__KERNEL__-DLINUX這幾個參數,編譯生成的模塊(一般為.o文件)可以使用命令insmod載入Linux內核,從而成為內核的一個組成部分,此時內核會調用模塊中的函數init_module()。當不需要該模塊時,可以使用rmmod命令進行卸載,此進內核會調用模塊中的函數cleanup_module()。任何時候都可以使用命令來lsmod查看目前已經加載的模塊以及正在使用該模塊的用戶數。

      3.設備驅動程序結構

      了解設備驅動程序的基本結構(或者稱為框架),對開發人員而言是非常重要的,Linux的設備驅動程序大致可以分為如下幾個部分:驅動程序的注冊與注銷、設備的打開與釋放、設備的讀寫操作、設備的控制操作、設備的中斷和輪詢處理。

      驅動程序的注冊與注銷

      向系統增加一個驅動程序意味著要賦予它一個主設備號,這可以通過在驅動程序的初始化過程中調用register_chrdev()或者register_blkdev()來完成。而在關閉字符設備或者塊設備時,則需要通過調用unregister_chrdev()或unregister_blkdev()從內核中注銷設備,同時釋放占用的主設備號。

      設備的打開與釋放

      打開設備是通過調用file_operations結構中的函數open()來完成的,它是驅動程序用來為今后的操作完成初始化準備工作的。在大部分驅動程序中,open()通常需要完成下列工作:

      檢查設備相關錯誤,如設備尚未準備好等。

      如果是次打開,則初始化硬件設備。

      識別次設備號,如果有必要則更新讀寫操作的當前位置指針f_ops。

      分配和填寫要放在file->private_data里的數據結構。

      使用計數增1。

      釋放設備是通過調用file_operations結構中的函數release()來完成的,這個設備方法有時也被稱為close(),它的作用正好與open()相反,通常要完成下列工作:

      使用計數減1。

      釋放在file->private_data中分配的內存。

      如果使用計算為0,則關閉設備。

      設備的讀寫操作

      字符設備的讀寫操作相對比較簡單,直接使用函數read()和write()就可以了。但如果是塊設備的話,則需要調用函數block_read()和block_write()來進行數據讀寫,這兩個函數將向設備請求表中增加讀寫請求,以便Linux內核可以對請求順序進行優化。由于是對內存緩沖區而不是直接對設備進行操作的,因此能很大程度上加快讀寫速度。如果內存緩沖區中沒有所要讀入的數據,或者需要執行寫操作將數據寫入設備,那么就要執行真正的數據傳輸,這是通過調用數據結構blk_dev_struct中的函數request_fn()來完成的。

      設備的控制操作

      除了讀寫操作外,應用程序有時還需要對設備進行控制,這可以通過設備驅動程序中的函數ioctl()來完成。ioctl()的用法與具體設備密切關聯,因此需要根據設備的實際情況進行具體分析。

      設備的中斷和輪詢處理

      對于不支持中斷的硬件設備,讀寫時需要輪流查詢設備狀態,以便決定是否繼續進行數據傳輸。如果設備支持中斷,則可以按中斷方式進行操作。

      三、PCI驅動程序實現

      1.基本框架

      在實現PCI驅動程序時,通常要實現以下幾個部分:初始化設備模塊,打開設備模塊,中斷處理模塊,讀取寄存器模塊,以及設備加載與卸載模塊。

      /*中斷處理函數*/

      voiddemo_irqhandler()

      {

      /*中斷處理函數*/

      }

      /*寄存器讀寫操作*/

      voidReadReg(u32dw_offset)

      {

      ret=readl(basevirt+dwoffset*4);

      }

      voidWriteReg(u32dw_offset,u32val)

      {

      writel(val,(basevirt+dw_offset*4));

      }

      intdemo_ioctl(structinode*inode,structfile*filp,unsignedcmd,unsignedlongreg)

      {

      switch(cmd)

      {

      case:

      break;

      }

      }

      /*設備操作接口*/

      staticstructfile_operationsdemo_fops={

      owner:THIS_MODULE,/*demo_fops所屬的設備模塊*/

      read:demo_read,/*讀設備操作*/

      write:demo_write,/*寫設備操作*/

      open:demo_open,/*打開設備操作*/

      release:demo_release,/*關閉設備操作*/

      ......

      }

      /*初始化設備*/

      staticintdemo_init(void)

      {

      gdev=pci_find_device(VENDOR_ID,DEVICE_ID,gdev);/*不同版本的內核這個函數是不一樣的*/

      demo_basehdwr=pci_resource_start(gdev,bar);/*申請bar地址*/

      ......

      demo_basehdwr=ioremap(demo_basehdwr,demo_basehdlen);/*映射bar地址*/

      ........

      register_chrdev();

      }

      /*設備卸載模塊*/

      staticvoiddemo_exit(void)

      {

      /*釋放內存,卸載設備*/

      }

      四、小結

      PCI總線不僅是目前應用廣泛的計算機總線標準,而且是一種兼容性強、功能全的計算機總線。而Linux作為一種新的操作系統,其發展前景是無法估量的,同時也為PCI總線與各種新型設備互連成為可能。由于Linux源碼開放,因此給連接到PCI總線上的任何設備編寫驅動程序變得相對容易。本文介紹如何編譯Linux下的PCI驅動程序,針對的內核版本是2.4。

     

     

      若您有高速數據采集板卡定制需求,請聯系我們:400-000-4026
     

      關于坤馳科技:
      坤馳科技是專注于
    高速數據采集與信號處理、高速數據存儲與記錄的高科技公司。坤馳科技為用戶提供成熟的標準高速數據采集產品與技術,也可為用戶提供定制化的高速信號采集解決方案。目前坤馳科技服務過的研究所、科研單位已達近百家。高速數據采集產品線涵蓋PCIExpress、cPCI、PXIe、VPX、USB等總線,包含高速AD、DA平臺、FPGA、DSP處理平臺,SATA/SSD、Flash存儲平臺等。
      全國咨詢電話:400-000-4026
     

      公司官方網站:http://www.jiguang-aurora.com.cn  

     

    一级黄色录像影片 - 视频 - 在线观看 - 影视资讯 - 品爱网