PCI设备RTX驱动开发方法
PCI设备RTX驱动开发方法
[编辑简介]:本文简要介绍了PCI驱动程序的特点、RTX 驱动整体架构,并对基于反射内存卡的 RTX 驱动进行分析,给出RTX API 列表。
[摘要]:
[关键词]:PCI, 反射内存, RTX API,中断资源冲突
PCI 设备 RTX 驱动开发方法
- RTX 下操作外设时, 需要把设备从 Windows 移动到 RTX 下面,
具体移植方法可以参考 RTX Help 文档中间 Converting a Windows Device to an RTX Device 一节或者参考附件«串口设备移植向导.doc»
- PCI驱动程序的特点
在设计驱动程序之前,首先要对欲控制的硬件设备进行细致地分析,更需要详细了解硬件设备的特性。硬件设备的特性会对驱动程序设计产生重大的影响。需要了解的最主要的硬件特性包括:
(1) 设备的总线结构
设备采用什么总线结构非常关键,因为不同的总线类型(如ISA和PCI)在许多硬件工作机制上是不同的,所以驱动程序设计也不同。
(2) 寄存器
要了解设置的控制寄存器、数据寄存器和状态寄存器,以及这些寄存器工作的特性。
(3) 设备错误和状态
要了解如何判断设备的状态和错误信号,这些信号要通过驱动程序返回给用户。
(4) 中断行为
要了解设备产生中断的条件和使用中断的数量。
(5) 数据传输机制
最常见的数据传输机制是通过I/O端口(port),也就是通过CPU进行数据读写。PC的另一种重要的传输机制是DMA,但PCI规范不包括从属DMA的说明。
(6) 设备内存
许多设备自身带有内存,PCI设备大多是采用映射的方式映射到PC系统的物理内存。有的设备还要通过驱动程序设置设备的接口寄存器
- RTX 驱动整体架构
使用 RTX Device Driver 开发向导, 选择支持
(1) Interrupt Service Routine (ISR)
(2) Support for Sharing an Interrupt
(3) Basic Port I/O Support
(4) Basic Mapped Memory Support,
即可生成 RTX PCI 设备驱动程序框架。
该程序框架分成两个函数, Driver 文件和 DriverFunc 文件:
Driver 文件主要包括 main 函数,中断服务程序和中断服务线程;
DriverFunc 文件主要是对 PCI 设备的基本操作函数, 包括 PCI 设备搜索, PCI 设备初始化,使能或关闭中断, 处理 PCI 设备共享中断, 以及 PCI 驱动程序资源清理等函数。
- 完整的 RTX PCI驱动
基于RTX PCI 设备驱动程序框架, 用户需要添加相应的代码, 下面基于反射内存卡的 RTX 驱动进行分析。
反射内存卡的基本特点:
(1) PCI、PCIe、PMC、VME 外形, 节点之间组成环形连接或通过光纤 Hub 组成星型连接
(2) 节点之间数据确定性的传输延迟, 延迟小于 750us
PCI 反射内存卡的 RTX 驱动也分成 Driver 文件和DriverFunc 文件两个文件。Driver 文件主要包括 main 函数,中断服务程序和中断服务线程, 下面是详细的分析:
(1) Main 函数:
Main 函数并不是 RTX PCI 驱动程序的一部分, 准确的讲它是如何使用 RTX PCI驱动程序的流程。用户需要做的工作:
a. 在 RTX PCI 设备驱动程序框架生成的 main 函数需要在设备初始化 (DeviceInit()) 完成之后与使能 PCI 中断之前添加设备打开(open())函数, 该函数的功能主要是创建信号量和初始化板卡.
b. 使能 PCI 中断之后, 用户即可调用 PCI驱动程序里的读写等函数写一段简单的读写测试程序。
(2) 中断服务程序:
这个函数接收到中断后交给中断服务线程来处理, 用户一般不需要改动。
(3) 中断服务线程:
中断服务线程主要完成读取和记录 PCI 板卡的中断信息, 释放相关的信号量等工作, 一般不完成具体的中断处理工作。PCI 驱动程序一般还提供一个函数来捕捉这些释放的信号量, 完成中断具体含义的解析工作。
DriverFunc 文件主要是对 PCI 设备的基本操作函数, 包括 PCI 设备搜索, PCI 设备初始化,使能或关闭中断, 处理 PCI 设备共享中断, 以及 PCI 驱动程序资源清理, 数据读写, 发送和接收消息类中断等函数。下面是详细的分析:
(1) DeviceSearch 函数
这个函数根据 PCI 设备的 Vendor ID 和 Device ID 搜索 PCI 设备, 返回 PCI 配置信息和 slot Number. 用户修改 Vendor ID 和 Device ID 即可。
(2) DeviceInit 函数
PCI设备初始化函数. 该函数中间调用了两个RTX 系统函数RtTranslateBusAddress() 和 RtMapMemory(), RtTranslateBusAddress() 作用为把 PCI 设备地址转换为 CPU 可以直接访问的物理地址, RtMapMemory() 函数把物理地址映射到虚拟地址。映射到虚拟地址空间后 ring3用户即可以读写 PCI 内存空间或者 I/O 空间了。用户需要关注的是物理地址到虚拟地址映射的地址范围,一般设置为 4K Bytes. RtMapMemory() 函数默认最大可以映射的地址范围为 64M Bytes, 如果需要更大的范围, 可以参考内存管理一节。
(3) Enable/Disable Interrupts On Chip 函数
使能或者关闭 PCI 设备上的中断。用户根据 PCI 设备进行修改。
(4) IsMyInterrupt函数
RTX 下 PCI 设备中断号可以共享。如果有 RTX 下 PCI 设备共享, 需要在该函数中间区分是否是该设备的中断.
(5) DeviceCleanup 函数
该函数释放中断句柄和解除物理地址于虚拟地址之间的映射。用户基本不需要修改该函数。
(6) RFM2gOpen 函数
反射内存功能函数。该函数的功能主要是为 DMA 通道,发送和接收Event(反射内存的一种消息类中断)等硬件功能模块创建信号量和初始化板卡。为了防止对硬件资源的访问冲突, 使用这些硬件资源前需要先拿到信号量, 使用结束后释放这些信号量。
(7) RFM2gEnableEvent函数
反射内存功能函数。使能板卡接收消息类中断。
(8) RFM2gSendEvent 函数
反射内存功能函数。向其它节点发送消息类中断。
(9) RFM2gWaitForEvent函数
反射内存功能函数。该函数结束中断服务线程释放的信号量, 解析中断的具体含义, 记录接收到的信息类型, 根据返回值判断是否接收到信息。
(10) RFM2gWrite函数
反射内存功能函数。该函数把数据写入到本地节点, 通过光纤传输到其它节点, 通过 DMA 或者 CPU 进行读取。写入完成后, 一般发送消息中断通知其它节点。
(11) RFM2gRead函数
反射内存功能函数。该函数读取从其它节点通过光纤传输到本地的数据, 通过 DMA 或者 CPU 进行读取。该函数一般在接收到其它节点发送的消息中断后使用。
. 反射内存卡 RTX 驱动调用的 RTX API 列表
RtCreateSemaphore;
RtWaitForSingleObject;
RtReleaseSemaphore;
RtQueryPciMsiCapability;
RtGetCurrentProcessorNumber;
RtAttachInterrupt;
RtReleaseInterrupt;
RtAttachInterruptVectorEx;
RtReleaseInterruptVector;
RtGetBusDataByOffset;
RtSetBusDataByOffset
RtTranslateBusAddress
RtMapMemory
RtUnmapMemory
RtGetPhysicalAddress
RtCloseHandle
RtExitProcess
RtEnablePortIo
RtDisablePortIo
RtPrintf
RtSleep
- PCI 设备 RTX 驱动的发布形式
PCI 设备 RTX 驱动的发布形式包括 .rtss, .rtdll, rtss dll, .lib.
.rtss 驱动程序是一个包含 PCI 设备驱动 RTX 应用;
.rtdll 是常见的 RTX 驱动存在形式, 类似 Windows 下的 DLL.
使用 RTDLL 前需要注册 RTDLL, 可以使用 RTSSRun 对话框注册, 也可以使用命令行注册。当 RTDLL 需要被多个进程加载时, 需要在注册 RTDLL 时选中“Shared between processes”对话框, 或者使用命令行时增加 /s 参数。
命令行RTSSrun 参数如下:
RTSSrun 【/q /f】 /d 【/s /t】 filename.rtdll, 其中, /s 参数含义是:
This optional flag allows an RTDLL to be loaded by several processes at the same time.
详细可以参考 RTX help 文档«Registering an RTDLL» 一节.
. rtss dll 是以 RTX 应用程序存在的 DLL, 可以为其它应用程序提供函数, 必须先于其它 RTX 进程启动, 一般不推荐使用。
. lib 是静态函数库。
- RTDLL 使用方法
在 RTX 应用程序中使用 RTDLL 方法不在这里讨论。
- PCI 设备中断资源冲突
中断资源冲突是用户使用 PCI 设备时经常遇到的问题, 解决中断资源冲突的方法有以下三种:
(1) 禁用中断资源冲突的 PCI 设备
(2) 把 PCI 设备移动到其它 PCI 槽位
(3) 升级板卡支持 MSI 中断, 可以从根本上避免资源冲突
- RTX 驱动开发的一些技巧
a. 把其它操作系统下驱动源代码移植到 RTX 下是比较常见的 RTX 驱动开发思路。
b. Getlasterror() 函数对于定位错误比较有帮助。
补充:
RTX
是
Windows
的实时扩展,
RTX
的出现,使得用户既可以利用
Windows
的良好界面,又使应用具有了微秒级的实时特性。
RTX
不仅支持
PCI
,
ISA
总线的板块,也支持
PCI-E
总线板卡。在驱动开发上,
PCI
,
ISA
和
PCI-E
板卡开发方法没有任何区别,
RTX
提供了良好驱动开发框架,通过设置向导,用户可以选择需要的功能模块,如:内存映射,
I/O
映射,
ISR
,
IST
等。
RTX
对中断类型的支持,不仅包括
line-based
类型,还包括
MSI
和
MSI-X
中断类型。当然,对
MSI
和
MSI-X
中断类型,需要硬件板卡具有此中断功能。目前,符合
PCI2.2
协议的板卡和
PCI-E
板卡一般都支持
MSI
和
MSI-X
中断。
下面简单介绍
RTX
的驱动框架,
用
DeviceSearch( )
函数来搜索指定的设备,开发人员需要将 device ID 和 Vendor ID 指定。
用 DeviceInit( ) 函数来初始化搜索到的指定设备。
2.1
使能 I/O 。(如果在构建框架时选择了 I/O 映射)
2.2
将物理内存地址,寄存器地址进行映射,这杨,开发人员对设备寄存器的访问就如同对数组的访问一样简单。
2.3
根据需要,对设备寄存器进行相应的配置。
用 RtQueryPciMsiCapability( ) 函数来探测板卡是否支持 MSI 或 MSI-X 中断。
根据中断类型来设置参数,包括 IST 和 ISR 。
用 RtAttachInterrupt( ) 函数来挂接中断。
以上是驱动的大致框架,开发人员可以根据需要,封装成自己的函数,以方便应用层的开发。驱动程序可以被编译成 RTSS 文件或 RTDLL 文件。若不希望驱动代码泄露,可以编译成 RTDLL 文件,只需提供函数接口即可。
文献来源: