阅读:5790回复:25
好,实在是好!
ISA就不用了吧,太简单了.PCI不太清楚,好像PCI的特性很象模拟电路,没有专用的开发设备是不行的.但现在有专门的PCI桥接芯片,也许情况会好些吧.
哪位设计过PCI的,给点意见. |
|
最新喜欢:![]()
|
沙发#
发布于:2002-12-10 15:51
icefox
我同事从ALTERA网站上下了PCI借口的IP核,你去找找。 ;) |
|
板凳#
发布于:2002-12-10 14:02
对于在PCI总线上进行高速数据传输,通常采用直接数据存储(DMA)技术。在DMA方式下数据能够达到PCI总线规范的最大数据传输速率,所以在设备驱动程序的开发过程中,实现DMA的工作方式成为驱动程序的设计的重点。而对于DMA工作方式的设备驱动程序的开发又是设备驱动程序的难点,并且国内介绍这类的书籍又相对很少,给设计者带来很大困难。
内核(Kernel)模式的驱动程序可以应用于WINDOWS NT和WINDOWS 2000的操作系统中。它区别于WDM(Win32 Driver Model)模型,主要不支持即插即用,但对于编程的思想二者基本上一致,对于本文所述的DMA编程的方法在WDM模式的驱动程序中一样适合。 本文通过现有最常见的AMCC公司生产的AMCC S5933 PCI 控制芯片为例说明在WINDOWS NT平台下如何编写设备驱动程序以实现DMA传输方式。本文对基本的驱动程序设计技术不作详细的说明,重点介绍基于包的总线主控DMA方式的原理和对常见驱动程序例程的要求。并介绍这种模式下驱动程序的实现方法。文章从几个不同的方面进行全面的阐述。 1、AMCC S59333控制芯片PCI主控DMA功能概述 AMCC S5933控制芯片,它具有实现完整的PCI主控模块和目标模块的接口功能。将复杂的PCI总线接口转换为相对简单的用户接口,用户只需要设计转换后的总线接口即可 AMCC S5933有两个FIFO(先入先出)存储器,一个是PCI到ADD-ON(附加设备)的FIFO,另一个是从ADD-ON到PCI的FIFO。S5933通过它的FIFO接口在PCI总线上进行DMA传输(总线主控)。FIFO可以作为PCI的发起者也可以作为目标者。FIFO作为目标,PCI总线主控访问ADD-ON数据。FIFO作为发起者可以向PCI发送数据。 PCI发起的DMA传输:此时FIFO作为目标。PCI发起的DMA传输必须通过总线主控控制状态寄存器(MCSR)来使能,读写使能分别控制,在驱动程序适配器控制(AdapterControl)例程设定这个寄存器。另外在驱动程序的设计中必须设定AMCC S5933读写地址寄存器(MWAR/MRAR)以及读写传输数据计数器(MWTC/MRTC)的值。AMCC S5933的DMA中断有下列几种情况:读传输计数器计到 0,写传输计数到0,或在DMA传输过程中PCI总线上发生错误。 2、 内核式驱动程序的基本结构和编程技术 驱动程序与应用程序的最大差别之一是驱动程序的控制结构,应用程序一直用main或WinMain函数控制运行。而驱动程序没有main或WinMain函数。它是由I/O(输入输出)管理器在下列情况下调用一个程序例程: 1) 驱动程序被装入时。 2) 驱动程序被卸出或系统被关闭时。 3) 用户程序发出I/O系统服务调用时。 4) 共享硬件资源对驱动程序可用时。 5) 设备操作过程中的任何时候。 任何设备驱动程序都必须拥有一个DriverEntry例程为每个驱动程序的入口点。下面简要说明驱动程序的分类。 1)驱动程序初始化和清理例程:在任何时候开始处理I/O请求之前,它必须执行一些初始化任务。DriverEntry例程、Reinitialize例程、Unload例程、Shutdown例程和错误回调例程一般用来执行这些操作。 2) I/O系统服务Dispatch(分发)例程:I/O管理器得到一个请求时,它使用请求的函数代码调用驱动程序中几个Dispatch例程中的一个。 3)数据传输例程:根据设备的不同设备操作涉及到一些不同的例程,一般有Start I/O例程、中断服务(ISR)例程、延迟过程调用(DPC)例程 4)资源同步回调:I/O管理器提供使用各种同步回调例程,使驱动程序更容易处理这些问题。当驱动程序需要访问某个共享资源时,它为该资源排队一个请求。当资源变得可用时,I/O管理器激活与该请求关联的一个驱动程序例程。驱动程序可以调用3种同步回调例程:ControllerControl回调例程、AdapterControl例程、SynchCritSection例程。 5)其他的驱动例程:驱动程序可以包括下面的一些例程。Timer例程,在设备操作过程中跟踪时间的例程。Cancel I/O很长时间持有等待请求的任何驱动程序必须把一个Cancel I/O例程挂到该请求。如果请求被取消,I/O管理器调用Cancel I/O例程执行必要的清理操作。 3 基于包的总线控制器DMA方式对DriverEntry例程的要求 为了使设备能在WINDOWS NT操作系统下工作,我们必须编写设备驱动程序,在驱动程序中实现DMA的传输功能。我们采用基于包的总线控制器DMA方式进行数据传输。在这种工作模式下设计DriverEntry例程需要除了DriverEntry拥有通常的工作以外,DriverEntry例程还需要有下列额外的工作: 1) 找到设备使用的DMA通道,这可以来自注册表(Registry)中的自动检测硬件信息,或者是硬件驱动程序的服务键Parameters子键中的硬编码。 2) DriverEntry例程使用他的硬件信息构造DEVICE_DECRIPTION结构,并调用HalGetAdapter,找到与设备关联的Adapter对象。 3) 保存由HalGetAdapter返回的Adapter对象的地址和映射寄存器的数目,以便在以后使用,通常把这些值放在Device Extension中。 4) 设置所创建的任何Device对象的Flags域中的DO_DIRECT_IO位。引起I/O管理器锁定内存中的用户缓冲区,并为它们创建内存描述符(MDL)。下面部分代码为设备驱动程序DriverEntry例程的子程序,主要创建DMA对象的设备描述(DeviceDescription)。 ?NTSTATUS AmccCreateDevice ( IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceNumber, IN AMCC_PCI_Device_Info* device, IN PUNICODE_STRING RegistryPath ){ ??? ??? // Create a Device object for this device... status = IoCreateDevice(DriverObject, sizeof( AMCC_DEVICE_EXTENSION ), &deviceName, FILE_DEVICE_UNKNOWN,0,FALSE, &pDeviceObject ); if( !NT_SUCCESS( status )) { return status; } // end if ??? ??? // Now register the PCI DMA controller with NT // First create a Device Description for the Busmastering capability DeviceDescription=ExAllocatePool(PagedPool, sizeof(DEVICE_DESCRIPTION)); RtlZeroMemory(DeviceDescription,sizeof(DEVICE_DESCRIPTION)); // the description for DMA DeviceDescription->Version=DEVICE_DESCRIPTION_VERSION; DeviceDescription->Master=TRUE;//bus master mode DeviceDescription->ScatterGather=TRUE;// for scatterGather mode DeviceDescription->Dma32BitAddresses=TRUE;// 32-bit address bus transfer DeviceDescription->IgnoreCount=FALSE; DeviceDescription->BusNumber=device->bus_number;//get bus number DeviceDescription->InterfaceType=PCIBus;// transfer in pci_bus DeviceDescription->DmaWidth=Width32Bits;// 32-bit data DeviceDescription->MaximumLength= MAX_TRANSFER_SIZE; //the max transfer 2^26 // Now pass this description to NT for both the read and the write adapters pDeviceExt->ReadTransfer.NumberOfMapRegisters=160000;//map\'s register pDeviceExt->ReadTransfer.Adapter=HalGetAdapter(DeviceDescription, &pDeviceExt->ReadTransfer.NumberOfMapRegisters); pDeviceExt->WriteTransfer.NumberOfMapRegisters=160000; pDeviceExt->WriteTransfer.Adapter=HalGetAdapter(DeviceDescription, &pDeviceExt->WriteTransfer.NumberOfMapRegisters); ExFreePool(DeviceDescription); if(pDeviceExt->WriteTransfer.Adapter==NULL||pDeviceExt->ReadTransfer.Adapter==NULL) { IoDeleteSymbolicLink( &linkName ); IoDeleteDevice( pDeviceObject ); return STATUS_ADAPTER_HARDWARE_ERROR; } return status; }//end amccCreateDevice 4 基于包的总线控制器DMA方式对AdapterControl例程的要求 为了实现DMA的传输,这里不采用ReadFile和WriteFile来实现,而采用在分发例程中通过IOCTL的宏定义来实现DMA的读、写功能。当传输一个(I/O请求包)IRP的请求包到达驱动程序时,分发例程首先判断IRP堆中的控制代码的信息是否为DMA读和写的功能,如果为DMA的读写功能,判断在IRP堆中的输出缓存为零或Irp->MdlAddress中描述缓冲区的MDL的指针为空,返回错误的状态信息。否则驱动程序进入StartIo例程,在StartIo例程中判断是DMA的读还是写的方式。在这两种方式下,分别通过IoAllocateAdapterChannel传递到驱动程序的AdapterControl例程的MapRegisterBase句柄。 AdapterControl例程应做以下一些工作: 1)调用MmGetMdlVirtualAddress,调用它以得到进入MDL的索引,被要求作为MapTransfer的一个参数,MapTransfer调用它使得返还到IRP的缓冲区的系统物理内存变得可以访问。 2)调用MmGetMdlByteCount得到MDL请求传输数据的字节数,在DpcForIsr例程中利用这个参数与当前传输的字节相减得到当前传输的信息。 3) 保存DEVICE_EXTENSION中关于MDL的信息,保存必要的上下文信息 4) 调用IoMapTransfer以映射IRP缓冲区的系统物理地址范围到总线控制器适配器的逻辑地址,驱动程序能为传输操作创建适配器。 5) 启动设备,开始DMA传输。 6) 返回DeallocateObjectKeepRegister,当每个DMA传输操作被完成时,另一个驱动程序例程(如DpcForIsr)必须调用 FlushAdaperBuffer清仓Adapter对象的Cache中的任何剩余的数据。 通过对DEVICE_EXTENSION中PCI基地址信息和AMCC S5933中寄存器相应的偏移地址设置寄存器的值。它所包含的信息有:中断的设置,FIFO管理表、控制状态寄存器(MCSR)的设置、清写传输计数器(MWTC)和读传输计数器(MRTC)。当通过IoMapTransfer成功获取映射的物理地址,设置MWTC或MRTC,以及相应的映射的物理地址的起始地址,这样将成功启动DMA的传输。驱动程序运行Isr例程, Isr执行在高于DISPATCH_LEVEL的IRQL上。因此ISR中使用的所有代码和数据必须存在于非分页内存中,此外,ISR能调用的内核模式函数十分有限。 因为ISR执行在提升的IRQL上,所以它冻结了其CPU上所有低于或等于该IRQL的其它活动。为了提高系统性能,你的ISR应该尽可能快地执行。基本上,只做服务硬件所需的最小量的工作,然后立即返回。如果有额外的工作需要做(例如完成一个IRP),应该交给DPC来完成。 尽管ISR的代码应该尽可能地短,但你不要把这个想法运用到极端。例如,如果某设备的中断是表明它已经为接收下一个字节而准备就绪,你就应该在ISR中直接发出这个字节。为了传输一个字节而调用DPC是愚蠢的。在DMA传输时必须调用DPC例程。读者可以阅读参考文献1第225页有关的例程。 5 驱动程序以及I/O管理器的后处理 内核的DPC分发器最终调用DPC例程,执行驱动程序的后处理。在DMA的操作中,有更多的数据需要传输,它设置DMA硬件传输下一块数据,启动设备。如果有错误或超时,在系统的日志中看到它。释放驱动程序占用的任何DMA和控制资源,把传输的大小和最后的信息放进IRP中,最后告诉I/O管理器完成当前的请求。 一旦驱动程序的DPC例程释放了一个IRP,I/O执行各种设备无关的清理工作:在缓冲I/O操作时,释放在传输过程中使用的非分页池缓冲区;在直接I/O操作中,它解开用户缓冲区的页的锁。 |
|
地板#
发布于:2001-08-09 16:29
如何利用9054来实现DMA传输数据,有没有例子,给我讲一讲呀,多谢
|
|
|
地下室#
发布于:2001-08-08 13:39
小弟想知道那有PCI接口IP核下载(当然要免费的)
还有一事不明还请大虾指点:用CPLD怎样处理毛刺? |
|
|
5楼#
发布于:2001-07-05 13:31
cpld的最大优点就是系统的扩充性比较好,系统可以做得很活.成本有不算太贵.
|
|
6楼#
发布于:2001-07-04 09:23
1. 9054是9080的替代产品,9052是9050的替代产品。
2. 并不一定非用CPLD不可,只是用它可以减少其他元器件的使用,比较方便。如果比较简单的应用,只用74系列也可以的,但一定要选高速器件,比如ACT、HCT系列。 |
|
|
7楼#
发布于:2001-07-01 11:01
大家都畅所欲言,我也说两句,看来用IP实现是趋势,都讲未来的电子工程师都要求是EDA专家!不过一步成专家,大家成专家,也难点,希望大家立足现状,多做一些和自己水平相当地事情,因此,我羡慕上面所有同仁,同样的兴趣使我们相聚在同一话题中,大家都能把自己所知无私奉献,都是我学习中的老师!我将继续向大家学习PCI板卡开发,希望大家从硬件开发到软件开发(驱动程序设计)多方面着手,使如我之流的初级爱好者能有个系统学习的机会!
谢谢大家 |
|
8楼#
发布于:2001-07-01 09:56
Hi:
在某一项目中,并不是168个脚每个脚都要用上,有些项目甚至EPM7128都可以实现。这自然要看你做什么了。况且近来FGPA等,都在降价,例如与EPM7128相当的,由atmel公司生产的ATF1508SA只要63元!我们都在期待着更便宜。 |
|
9楼#
发布于:2001-06-30 20:11
这样是不是就要用fpga,cpld的触发器估计是不够使了,管脚是不是至少也要用到168条腿?因为你自己的逻辑还要用到?Atera 的 Flex10k40
在上星期3在中关村中发的报价是 840元,这样成本岂不是更高了? 因为在可编程逻辑器件里实现功能并不如批量生产的专有芯片成本低。正要是不是有点得不偿失呢?当然如果纯为学习的目的是可以的,但作为产品开发好像不是很好。也许我估计的有误。 [principal 编辑于 2001-06-30 20:15] |
|
10楼#
发布于:2001-06-30 11:28
我觉得两者的性能没有区别,pci9054新增加的功能主要是针对CompactPCI的。
另外pci9054只有一个DMA通道用于请求模式DMA,而pci9080有两个。 其他,pci9054基本上覆盖了pci9080的功能。 pci9054的工作电压为3.3V,但是IO兼容5V. |
|
|
11楼#
发布于:2001-06-30 11:21
用IP还得做ASIC,如果生产批量不大,是否不划算?
|
|
|
12楼#
发布于:2001-06-30 11:19
如果给PCI9054的LHOLDA无效就处于主方式,否则处于从方式
|
|
|
13楼#
发布于:2001-06-29 21:30
Hi:
IP就是生产可编程逻辑器件的厂家或第三方为某一功能的实现编制的硬件描述语言的程序,它不仅能实现PCI,而且能实现其它的逻辑功能,这样一来外部芯片就减少了,自然也就减少了PCB的布线量。有的可以免费下载,有的是需要付费的,若想进一步了解请到Atlare网站看一看,希望能相互交流,共同提高。谢谢 |
|
14楼#
发布于:2001-06-29 18:50
IP是什么?能说的详细点么?我没听说过。
希望你能够介绍一下,省得大家走弯路! |
|
15楼#
发布于:2001-06-27 21:10
Hi:
我感到奇怪,有相关的IP,这样可以做到一片搞定。你为什么还要用PCI专用芯片。 |
|
16楼#
发布于:2001-06-27 16:55
principal老兄:
真羡慕你呀,有那样的好老师,我很惨,天天在黑屋子里抓黑猫! |
|
|
17楼#
发布于:2001-06-27 14:52
聪明。我没想到!长江后浪推前浪!
|
|
18楼#
发布于:2001-06-26 08:44
Hi:
你真傻,用什么最旧最破的板试验PCI,坏了不是还要自己承担,其实你可买一块新板,出了问题,由厂家承担,这不是更好吗。这可是秘密,不要随便告诉别人。 |
|
19楼#
发布于:2001-06-25 21:39
该讨论一下谁作版主的事了吧?
|
|
|
上一页
下一页