一个简单的PCIE驱动到设备的通信协议

        本文主要介绍一个简单的单一设备PCIE驱动程序和设备的通信协议,从上到下大致分为三层:应用层、驱动层和设备层。其中,应用层和驱动层通过系统总线(win32 API调用)实现通信,驱动层和设备层通过PCI总线(地址空间映射)进行通信。


一、Driver和Device的数据交互方式

        Driver和Device的通信主要是通过地址空间映射来实现。操作系统将Device的物理地址映射为系统虚拟地址,Driver可以直接读写;Driver也可以分配一段内存,映射为PCI地址,供Device读写。后面将这种映射的内存称为buffer,Driver和Device的数据交互就是通过这种读写共享buffer的方式实现的。大致可以分为以下几种类型:

        WRITE_CMD方式:Driver写Device的buffer
        READ_CMD方式:Driver读Device的buffer
        DMA_WRITE方式:Device读Driver的buffer
        DMA_READ方式:Device写Driver的buffer



二、Buffer划分

        Driver开辟两块4Mbytes的buffer,用于DMA读写,读写的时候,数据按4Mbytes对齐,不足4Mbytes的数据块按填零处理。
Device映射3块BAR空间到Driver,BA0为标准的PCI配置空间,大小为4K字节。BAR1和BAR2作为数据交互buffer,大小为4M字节。其中,BAR1用于Driver发信息给Device,BAR2用于Device返回信息给Driver。按byte计算,两个buffer的offset范围是:0 ~ 4*1024*1024 – 1。
在实际使用中,我们一般以32bits来表示一个信息单元,即转化为一个ULONG值。因此,实际上,我们是以4bytes为单元,用index来定位。但又一个例外——frame数据,后续讲到了再展开说。以4bytes为单元,按index划分buffer,它的index范围是:0 ~ 1024*1024 – 1。
注:后续没有特殊说明,buffer内部都按index计算。

一个简单的PCIE驱动到设备的通信协议_第1张图片

同样,Bar2的前4个index全部保留。从index4起,作为response的content,其中包括response typeId、the number of returned values和returned values。


四、数据交互过程

各flag初始态都是0。


WRITE_CMD的steps:
1)Device循环读major flag,等待1。
2)Driver将数据填入bar1的数据域,然后对major flag置1。
3)Driver开循环读major flag,等待0。
4)Device等到1,取走bar1数据域中的数据。
5)Device将返回值填入bar2的数据域,然后对major flag置0。(Device侧该次交互结束)
6)Driver等到0,取走bar2数据域中的数据,返回应用层;


对于Driver和Device的交互来说,READ_CMD的steps与WRITE_CMD的steps相同,这里区分开来是便于应用层理解。


DMA_READ的steps:
1)Device循环读major flag,等待1。
2)Driver将数据填入bar1的数据域,然后对major flag置1。
3)Driver开循环读major flag,等待0。
4)Device等到1,取走bar1数据域中的数据,然后对major flag置0。
5)Device从数据中获知DMA,开启DMA循环计数,并在循环体中读minor flag,等待1。
6)Driver等到major flag的0,返回应用层;
以上过程完成命令交互,下面开始DMA数据交互
应用层开启一个for循环,执行N次DMA数据交互。
7)Driver收到应用层的dma read请求,对minor flag置1。
8)Driver开循环读minor flag,等待0。
9)Device等到minor flag的1,将数据填入read buffer,然后对major flag置0。(Device侧的一次DMA数据传输结束,进入下一次小循环)
10)Driver等到minor flag的0,将数据取回,然后返回应用层;(应用层的一次DMA数据read结束,进入下一次小循环)
11)……
12)PC侧和Device侧的DMA循环计数结束,完成整个DMA过程。


从以上过程来看,DMA_READ其实分为两大步,首先是PC给Device发一个“DMA预备”的命令,然后双方都进入实际的DMA循环过程。
DMA_WRITE与DMA_READ类似,不再另书。
注:在“DMA预备”命令中,包含这一次DMA传输的总数据量,以字节为单位, Device需要换算成循环次数。




你可能感兴趣的:(一个简单的PCIE驱动到设备的通信协议)