利用 PlxSdk 工具包开发 Linux 下 PCI 设备驱动

最近实验室需要做一个 Linux 与 FPGA 之间的快速接口,考虑高速的特性,选择了 PCI 接口实现。

FPGA 选择 altera 的 EP2C20F484C8

PCI 接口芯片选择 PLX8311

操作系统选择 ubuntu10.04


1、Linux 检测 PCI

将板卡插入到主机 PCI 插槽内,开机,通过 lspci 命令可以检测到当前系统下所有的 PCI 设备。


02:00.0 PCI bridge: PLX Technology, Inc. PEX 8111 PCI Express-to-PCI Bridge (rev 21)
03:04.0 Bridge: PLX Technology, Inc. PCI9056 32-bit 66MHz PCI <-> IOBus Bridge (rev ba)

通过返回结果,可以知道 PLX8311 实际上是由 PEX8111 实现 PCI-E 到 PCI 的转换,并且通过 PCI9056 实现 PCI 到 IOBus 的转换。


所以,我们要在 Linux 下实现的设备驱动就是 PLX9056。


2、下载 PlxSdk 工具包

直接进入 PLX 官网,下载满足要求的 linux 发行版 SDK 工具包。

SDK 官网下载地址:http://www.plxtech.com/products/sdk/pde


我选择下载的版本是:PLX_SDK_Linux_v7_11_Final_2014-03-04.zip
注意下载的时候需要注册。


3、SDK 主要特性

  • Support for all PLX PCI & PCIe (PEX) products
  • All Windows flavors XP and later, and Linux Kernel 2.6 / 3.x
  • 64-bit OS environments are supported
  • Kernel level Service & End-point drivers with source code
  • User level API Library with source code
  • Important command line applications with source code
  • Separate GUI Applications for PCI & PCIe
  • PLX SDK User‘s Manual & Release Notes
  • Support for Non-PLX devices

4、SDK 文件结构

PlxSdk/Include
PLX SDK include files,编译时依赖的头文件
PlxSdk/PlxApi
PLX Host API Library source,编译后产生所需的库
PlxSdk/Driver
Various PLX device drivers,驱动所在文件
PlxSdk/Samples
Sample applications,所有示例
PlxSdk/Samples/PlxCm
A command-line application, which is useful when working with PLX devices,所有的命令行文件
PlxSdk/Makefiles
Shared makefile components used to build PLX applications, libraries, and drivers,makefile 文件
PlxSdk/Bin
Scripts to load, unload, and assist in debug of the driver/module,用于加载,卸载驱动,打印日志的脚本


5、安装 SDK

1) Copy the PLX Linux TAR file to the desired working directory, e.g. the user’s home directory or /usr/linux/src.


把下载得到的 *.zip 使用 uzip 命令解压以后,会得到一个 PlxSdk.tar 包,将这个 tar 包拷贝到你的工作目录下,我选择了 /usr/src/ 下面,这个可以根据自己的需要,设置到不同的目录下。

2) If the PLX file contains a .gz extension, the file must first be unzipped, as follows: gunzip PlxSdk.tar.gz

如果文件被进一步打包成 .gz 包的话,就需要使用 gunzip 命令来解压压缩包。我在这里没有遇到,这个根据下载到的安装包自己选择操作方式。

3) Use a TAR file extractor or open a terminal window and type the following command: tar -xvf PlxSdk.tar

解压 tar 包,使用命令 tar -xvf PlxSdk.ta

4) This will create a folder called PlxSdk with all PLX supplied files and folders inside.

解压以后得到 PlxSdk 文件夹。

root@abscom-desktop:/usr/src# ls
linux-headers-2.6.32-38          linux-source-2.6.32.tar.bz2  PlxSdk.tar
linux-headers-2.6.32-38-generic  PlxSdk
root@abscom-desktop:/usr/src# 

root@abscom-desktop:/usr/src/PlxSdk# ls
Bin  Driver  Include  Makefile  Makefiles  PlxApi  Samples
root@abscom-desktop:/usr/src/PlxSdk#



5) In order to build the files supplied, the shell environment variable PLX_SDK_DIR must be set. This should be set to the root location of where the PlxSdk folder is created. This can be set with the export command and may be placed in the shell initialization script (e.g. “.bashrc”) so that it is automatically set when a new terminal session is started.


Examples: export PLX_SDK_DIR=$HOME/PlxSdk

export PLX_SDK_DIR=/usr/src/PlxSdk


使用 root 身份,设置 PLX_SDK_DIR 环境变量,用于制定安装目录。可以在 .bashrc 下面设置,我选择在 enviroment 下设置。

root@abscom-desktop:/usr/src/PlxSdk# vi /etc/environment 
root@abscom-desktop:/usr/src/PlxSdk# source /etc/environment 
root@abscom-desktop:/usr/src/PlxSdk#


通过 vi /etc/environment 添加如下命令:

export PLX_SDK_DIR=/usr/src/PlxSdk

通过 source 命令使得环境变量生效。

root@abscom-desktop:/usr/src/PlxSdk# echo $PLX_SDK_DIR
/usr/src/PlxSdk



6、机器配置

PLX only tests the Linux package for Intel x86 compatible platforms. The PLX makefiles attempt to auto-detect other platforms to set the Big/Little Endian & 32/64-bit options. If this package is used with an unsupported CPU, the PLX makefile will halt with an error. To resolve the issue, follow the steps below:

此 SDK 是在 Intel X86 机器上试验的,对于其他的机器需要配置,比如大小端、32/64 位机器。


1). Open PlxSdk/Makefiles/Common.def.
2). Find the CPU properties section at the top
3). Add an entry for your architecture & set PLX_CPU_BITS & PLX_CPU_ENDIAN variables accordingly, following the example of existing entries.
For example:
ifeq ($(ARCH),mips64)
PLX_CPU_BITS = 64
PLX_CPU_ENDIAN = Big
endif


使用 uname 命令查看自己机器的信息:

root@abscom-desktop:/usr/src/PlxSdk# uname -a
Linux abscom-desktop 2.6.32-38-generic #83-Ubuntu SMP Wed Jan 4 11:13:04 UTC 2012 i686 GNU/Linux

通过分析命令返回的结果,知道我们系统的内核是 2.6 的,是因特尔的 i686 架构机器。由于因特尔都是小端模式的,因此不需要再设置这一变量。


如果是大端的机器,需要设置如下环境变量:

export PLX_CPU_BIG_ENDIAN=1


使用 file 命令,查看机器位数:

root@abscom-desktop:/usr/src/PlxSdk# file /sbin/init
/sbin/init: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, stripped

通过分析返回结果,可以知道我的机器是 32 位的,因此不必设置位数环境变量。


如果是 64 为机器,需要设置如下环境变量:

export PLX_CPU_BITS=64


7、编译库函数

To build user-level components (API library or applications), change to the desired component directory and type ‘make’. Makefiles are included in the package. Depending upon the installation location, the Makefile environment variables may need to be modified to avoid build errors.


To build the API library, type the following commands in a terminal window:
prompt> cd PlxSdk/PlxApi
prompt> make

编译 API 库


To build a sample application, type the following commands in a terminal window:
prompt> cd PlxSdk/Samples/ApiTest
prompt> make

编译一个案例


To build a Debug version instead of the default Release version, type the following command in a terminal window:
prompt> make PLX_DEBUG=1

如果要编译 DEBUG 版本,就添加 PLX_DEBUG=1 参数,不添加默认生成 RELEASE 版本


To see the complete command-line during the build of each component, add ‘V=1’ to the make parameters:
prompt> make PLX_DEBUG=1 V=1

如果想要看到编译时的全部命令,可以添加 V=1 参数


To clean a build, change to the desired directory and type one of the following commands in a terminal window:
prompt> make clean (Removes all object and intermediate build files, but not final image)
prompt> make cleanall (Removes all build files, including final image)

清理编译结果


8、编译驱动

下表用于参考,选择自己要编译哪个设备的驱动。



The build of drivers involves the use of a PLX-provided script file (builddriver), which is located in the PlxSdk/Driver directory.  This is provided to simplify the build of multiple drivers, which share a common code base.  The builddriver script will build a debug or release version of the driver for a desired PLX chip.  Its usage is as follows:


进入到 Driver 文件夹,进行驱动的编译,其中 builddriver 用于编译某个特定的驱动, builddriverall 用于编译所有的驱动。

root@abscom-desktop:/usr/src/PlxSdk/Driver# ls
buildalldrivers  Plx8311            Source.Plx8000_DMA  Source.PlxSvc
builddriver      Plx9056            Source.Plx8000_NT
Makefile         Source.Plx6000_NT  Source.Plx9000

如下显示不同编译选项:

  Usage: builddriver {Driver} [DebugOption] [CleanOption]
 
     Driver      = 8000n      : PLX 8000 NT-mode driver
                   8000d      : PLX 8000 DMA Controller driver
                   9050       : PLX 9050/9052 driver
                   9030       : PLX 9030 driver
                   9080       : PLX 9080 driver
                   9054       : PLX 9054 driver
                   9056       : PLX 9056 driver
                   9656       : PLX 9656 driver
                   8311       : PLX 8311 driver
                   6000n      : PLX 6254/6540/6466 NT-mode driver
                   Svc        : PLX PCI/PCIe Service driver
 
     DebugOption = <none>     : Build Release build of module
                   'd'        : Build Debug build of module
 
     CleanOption = <none>     : Build the driver
                   'clean'    : Remove intermediate build files
                   'cleanall' : Remove all build files
 
  E.g.: builddriver 9054 d      - Build 9054 module debug version
        builddriver Svc         - Build PlxSvc service module release version
        builddriver 8000n clean - Remove intermediate build files of 8000-NT module

如下展示不同的编译方法:

Some examples of using the script are:

promptcd PlxSdk/Driver                             (Change to the driver directory)

prompt./builddriver 8000n d                       (Build debug version of the 8000 NT driver)

prompt./builddriver Svc                              (Build release version of the PLX Service driver)

prompt> ./builddriver 9054 d clean               (Remove intermediate build files only for the debug version of the 9054 driver – does not delete driver binary, Plx9054_dbg.ko)

prompt./builddriver 6000 cleanall              (Remove all build files for the 6000 NT driver)


这边我需要的是 PLX9056 的驱动,所以我只要编译 9056 的驱动就可以。

Build: Plx9056

- PLA: Linux, version ???
- KER: 2.6.32-38-generic
- INC: /lib/modules/2.6.32-38-generic/build/include
- CPU: i386 (32-bit Little Endian)
- CMP: Gcc
- TYP: Driver
- PLX: 9056
- CFG: Release

make[1]: Entering directory `/usr/src/linux-headers-2.6.32-38-generic'
  Building modules, stage 2.
  MODPOST 1 modules
make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-38-generic'

Driver "Plx9056/Plx9056.ko" built sucessfully

编译后,会在当前目录生成一个 Plx9056 文件夹:

root@abscom-desktop:/usr/src/PlxSdk/Driver/Plx9056# ls
Obj  Plx9056.ko

这里的 Plx9056.ko 就是我们需要的驱动了。


9、加载设备驱动

PLX device drivers are implemented as installable modules and scripts are provided to load and unload them. The scripts are located in the <PlxSdk/Bin> directory and are listed below. Please use the provided PLX scripts to load/unload drivers instead of the Linux insmod/rmmod utilities.

进入 Bin 目录,这里驱动的加载方式与 Linux 自带的 insmod/rmmod 不同,而是选择通过它自己的脚本来实现。

Plx_load 

Script to load a module,加载驱动

Plx_unload 

Script to unload a module,卸载驱动

startlog 

Sample script which sets up a terminal to display driver debug output,显示驱动 debug 输出


通过 Plx_load 命令加载驱动:

root@abscom-desktop:/usr/src/PlxSdk/Bin# ./Plx_load 9056

Install: Plx9056
  Load module......... Ok (Plx9056.ko)
  Verify load......... Ok
  Get major number.... Ok (MajorID = 250)
  Create node path.... Ok (/dev/plx)
  Create nodes........ Ok (/dev/plx/Plx9056)


查看设备驱动:

root@abscom-desktop:/usr/src/PlxSdk/Bin# ls /dev/plx/
Plx9056    Plx9056-10  Plx9056-13  Plx9056-16  Plx9056-4  Plx9056-7
Plx9056-0  Plx9056-11  Plx9056-14  Plx9056-2   Plx9056-5  Plx9056-8
Plx9056-1  Plx9056-12  Plx9056-15  Plx9056-3   Plx9056-6  Plx9056-9

通过 Plx_unload 命令卸载驱动:

root@abscom-desktop:/usr/src/PlxSdk/Bin# ./Plx_unload 9056

Remove: Plx9056
  Unload module................... Ok (Plx9056)
  Clear device nodes.............. Ok (/dev/plx/Plx9056)
  Delete device node path......... Ok (/dev/plx)


10、运行测试程序

运行 Sample 文件夹下面的 ApiTest 程序。

首先编译得到运行程序 make:

Build: ApiTest

- PLA: Linux, version ???
- KER: 2.6.32-38-generic
- CPU: i386 (32-bit Little Endian)
- CMP: Gcc
- TYP: App
- CFG: Release

Link: ApiTest

Application "App/ApiTest" built successfully

编译会在当前目录创建一个 App 目录,可执行程序就在里面,运行结果如下:

                       PLX API Test
    =================================================

Selected: 9056 10b5 [b:03  s:04  f:0]


PlxPci_ChipTypeGet():
  Getting PLX Chip Type.......... Ok
    Chip type:  9056
    Revision :    BA
                                                
PlxPci_PlxRegisterXxx():
  Reading PLX-specific reg....... Ok (Reg 78 = 00000000)
  Write to PLX reg............... Ok (Wrote 1235A5A5)
  Verifying register write....... Ok (Reg 78 = 1235A5A5)
  Restore original value......... Ok (Wrote 00000000)
  Read mem-mapped PLX reg........ Ok (Reg 78 = 00000000)
  Write to mem-mapped PLX reg.... Ok (Wrote 1235A5A5)
  Verifying mapped reg write..... Ok (Reg 78 = 1235A5A5)
  Restore original mapped value.. Ok (Wrote 00000000)
                                                
PlxPci_PciBarMap()...
  Mapping PCI BAR 0........ ApiSuccess (VA=0xb77a3c00  512 bytes)
  Mapping PCI BAR 1........ ApiInvalidPciSpace (VA=(nil)  256 bytes)
  Mapping PCI BAR 2........ ApiSuccess (VA=0xb7696000  1024 KB)
  Mapping PCI BAR 3........ ApiSuccess (VA=0xb7596000  1024 KB)
  Mapping PCI BAR 4........ ApiInvalidPciSpace (VA=(nil)  0 bytes)
  Mapping PCI BAR 5........ ApiInvalidPciSpace (VA=(nil)  0 bytes)

  Unmapping PCI BAR 0...... Ok (rc = ApiSuccess)
  Unmapping PCI BAR 1...... Ok (rc = ApiInvalidAddress)
  Unmapping PCI BAR 2...... Ok (rc = ApiSuccess)
  Unmapping PCI BAR 3...... Ok (rc = ApiSuccess)
  Unmapping PCI BAR 4...... Ok (rc = ApiInvalidAddress)
  Unmapping PCI BAR 5...... Ok (rc = ApiInvalidAddress)
                                                
PlxPci_CommonBufferXxx():
  Get Common buffer properties....... Ok
  Map Common buffer to user space.... Ok
      Bus Physical Addr: 0x31100000
      CPU Physical Addr: 0x31100000
      Virtual Address  : 0x0xb7786000
      Buffer Size      : 64 Kb
  Unmap Common buffer................ Ok
                                                
PlxPci_PhysicalMemoryXxx():
  Allocate buffer...... Ok
  Map buffer........... Ok
      Bus Physical Addr: 0x31200000
      CPU Physical Addr: 0x31200000
      Virtual Address  : 0x0xb7696000
      Buffer Size      : 1024 Kb

  Unmap buffer......... Ok (rc=ApiSuccess)
  Free buffer.......... Ok
                                                
PlxPci_EepromXxx():
  Checking if EEPROM present..... Ok (No EEPROM Present)
  Probing for EEPROM............. Ok (EEPROM not detected)
      -- EEPROM not detected, skipping remaing tests --
                                                
PlxPci_NotificationXxx()...
  - Unsupported PLX chip type (9056), skipping tests
                                                
PlxPci_GetPortInfo()...
  Get Port properties................ Ok
      Port Type  : 01 (Endpoint)
- Device does not support PCI Express Capabilities -


至此,PLX9056 的设备驱动已经生成完毕,设备能够正常工作了,下一步就是设计 FPGA 程序,实现  FPGA 与 linux 之间通过 DMA 实现数据交互。最后附上设备图片。


利用 PlxSdk 工具包开发 Linux 下 PCI 设备驱动,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。