PCI moden卡开发问题.及自已的总结开发流程

zhoujianfeng   2008-7-24 00:02 楼主
1.在PNP的start_device例程中可以获取硬件的相关资源如:I/0,内存,中断号,硬件的DMA等.     
是不是就在这里作所谓的"I/0端口映射,内存映射".如果不是,那在哪里处理.     

2.如果1是进行映射,那么我怎么来使用这个映射是xxx.outb(地址,值)这样用吗?这些映射是不是就是所谓的"操作寄存器"。还有I/0空间,存储空间,中断、DMA寄存器。这些名词有点乱帮忙理下。正常:硬件(芯片)上应该叫“寄存器”吧,PC上叫“内存”吧。     

3.对硬件操作要知道它芯片的寄存器地址(对硬件不是很了解……)那些硬件的信息能从硬件中写代码取到吗?因为我手上就只有硬件没有文档。。。哪个寄存器的哪个位是干什么用的等等(难道真的要有硬件的说明文档!!)     

4.(重点)中断有哪几种,当中断发生时是哪一种中断,我要作怎么样的处理,中断发生时能获得多少有用的信息。     

中断处理(网上找的):   

1、中断都是分优先级的,一定要根据具体的项目,分配合理的优先级;   
2、51中,优先级和优先顺序是不同的概念,一般初学者分不清。我的博客里面已经有相关的文章介绍过这两者的区别,不再赘述;   
3、中断响应函数尽量短小,不要进行数据处理和函数调用;   
4、51的串口发送数据、接收数据都调用同一个中断,但是一般的程序中,为了提高系统的实时性,接收数据采用中断方式。因为在发送数据的时候,发送的时刻、发送数据的长度都是已知的,没有必要调用中断。我在串口中断响应函数中先判断是接收中断还是发送中断。如果是发送中断,直接挑出,不进行任何处理;如果是接收中断,进行相应的处理;   
5、串口中断只负责接收数据,并将数据存入缓存,不要进行数据。在中断中,将数据保存在“环“的数据结构中。环只要设置两个指针“头”“尾”,我一般将环的长度设为255,这样,“头”“尾”两者指针都可以是Unsigned Char,指针只要进行自加操作,就可以实现计数的自动循环,就是指针加到255后,自动回到0;不做这么过有一个前提条件,就是程序读“环”中数据的速度要大于串口中断响应函数中向“环”写数据的速度,避免数据覆盖;   
6、有时候系统的状态会随着中断的到来改变,这是,我是通过全局变量检测状态的变化,在中断里面给全局变量赋值,主程序中检测变量的值,进行相应的操作,操作完成之后,将全局变量赋初值,等待下一次中断;   
7、使用定时器中断的时候要注意,必要的时候停止定时器,可能会给开发带来想不到的好处。   
总体来说,单片机的资源有限,如果系统没有什么算法的话,底层开发不难,重要的是系统程序的结构要合理,思路要清晰。   

如何判断一个中断是不是自己发的?  
答:读你自己卡的中断寄存器,中断寄存器是映射在内存中的 ,你读寄存器,   
就是操作内存。  


5.这两星期学习的总结供大家分享,初学者的东西(个人的理解),不对之处的请原谅。   

1.初始化:   
驱动入口例程(对驱动程序的初始化):   
DirverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)     

注册表的处理(相当于驱动程序的数据库)   
系统派遣例程的初始化:   
DriverObject->DriverUnload = DriverUnload   
必有,释放DirverEntry里分配的资源,   
,DriverObject->DriverExtension->AddDevice = AddDevice   
必有,创建设备对象、初始化设备扩展,为设备命名、设置GUID、初始化自旋锁,事件,DCP等(大部分初始化多在这或者IRP_MN_START_DEVICE请求的Dispatch例程,按需求操作)   
,DriverObject->DriverStartIo = StartIo   
串行处理IO(重要!使用DMA传输)   
,DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp   
处理至少8个设备状态如:启动,关闭,关系等。。。   
,DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower   
--电源管理   
,DriverObject->MajorFunction[IRP_MJ_CREATE] = FakeModemOpen;   
//创建设备的派遣函数   
,DriverObject->MajorFunction[IRP_MJ_CLOSE] = FakeModemClose;   
//关闭设备的派遣函数   
,DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FakeModemCleanup;   
//清除设备   
,DriverObject->MajorFunction[IRP_MJ_WRITE] = FakeModemWrite;/   
/写入设备数据的派遣函数   
,DriverObject->MajorFunction[IRP_MJ_READ] = FakeModemRead;   
//读取设备数据的派遣函数   
,DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FakeModemIoControl;/   
/其他Irp派遣函数   
.   
2.进入下一步:   
设备初始化例程:   
AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT pdo)   

,IoCreateDevice(...)--创建设备对象   
,初始化设备扩展   
,FakeModemHandleSymbolicLink(...)--创建符号联接名(设备命名)、GUID--供应用程序调用   
,KeInitializeSpinLock(...)--初始化自旋锁   
下面是排队机制   
InitializeListHead(&DeviceExtension->ReadQueue);//初始化读堆栈争链表头   
DeviceExtension->CurrentReadIrp=NULL;//当前的读堆栈节点设置为空   
InitializeListHead(&DeviceExtension->WriteQueue);//初始化写堆栈争链表头   
DeviceExtension->CurrentWriteIrp=NULL;//当前的写堆栈节点设置为空   
InitializeListHead(&DeviceExtension->MaskQueue);//当前任务堆栈   
DeviceExtension->CurrentMaskIrp=NULL;//当前的任务堆栈节点设置为空   

3.进入下一步:   
如果支持PNP则进入PNP例程:   
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp        
注:在这里就开始用到同步机制(自旋锁、事件)   
里面有好几种状态,当插入硬件时,会发出一个IRP_MN_START_DEVICE(设备启动)的Irp在这里可以进行和addDevice相同的初始化,不过这里主要作硬件资源的映射   

这里要处理的状态有:   
IRP_MN_START_DEVICE //设备启动   
IRP_MN_QUERY_DEVICE_RELATIONS   
IRP_MN_QUERY_REMOVE_DEVICE //询问是否移除设备在不产生中断的情况下   
IRP_MN_CANCEL_REMOVE_DEVICE //不移除设备 IRQL PASSIVE_LEVEL   
IRP_MN_SURPRISE_REMOVAL   
IRP_MN_REMOVE_DEVICE //移除设备   
IRP_MN_QUERY_STOP_DEVICE   
IRP_MN_CANCEL_STOP_DEVICE   
IRP_MN_STOP_DEVICE   
IRP_MN_QUERY_CAPABILITIES   

注:这里主要有向下屋(DPO)发送Irp   
        
IRP_MN_START_DEVICE //设备启动初始化哪些东西。。   

映射内存地址——可以取得内存地址范围   
映射I/O端口——可以取得端口范围   
初始化MDA   
初始化中断——可以取得中断号   
注:这里使用前面初始化的设备扩展结构体进行存储。。。。重要!   
所有初始化在以上完成.........   

难处理又难理解的地方:   
1.驱动有时要多线程(相当于异步),有时又必需同步(使用自旋锁、事件进行同步)   
2.一个Irp的到来需要判断很多种情况。比如一个Read的Irp过来要判断设备当前有没有在工作,缓冲区是否已满,有没有中断发生,中断发生后要怎么处理等。。。   
3.中断有一个中断例程,还有一个DPC延时调用例程(在中断完成后调用大部份处理多在这里)不知道什么时候需要中断,还有中断发生时我要怎么判断是哪一种中断我需要作哪一些处理 ;还有IRQL级别的运用   
4.DMA(还不是很理解)这里有有关串行调度,中断,DCP,同步等。。   
5.对DDK的文档不熟,驱动程序里用到许多内核函数。。。   

KDeriver   

硬件访问编程, 中断处理编程, DMA编程   
KIoRange       KInterrupt     KDmaAdapter   
KMemoryRange                  KDmaTransfer   
                              KCommonDmaBuffer   


应用程序访问:   
打开设备OpenByInterface(...)这里参数有个GUID是驱动初始化时定义的用来标识一个设备   
DeviceIoControl(...)对应驱动程序里的   
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FakeModemIoControl;/     
CreateFile(…)对应驱动程序里的DriverObject->MajorFunction[IRP_MJ_CREATE] = FakeModemIoControl   
ReadFile(…)对应驱动程序里的DriverObject->MajorFunction[IRP_MJ_READ] = FakeModemIoControl

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复