DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 847|回复: 0
打印 上一主题 下一主题

[待整理] Windows CE下驱动程序开发基础(二)

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-11 02:48:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
函数SerInit接着调用函数Ser_InternalMapRegisterAddresses转换IO地址并且映射地址,Ser_InternalMapRegisterAddresses在内部调用系统提供的HalTranslateBusAddress(Isa, 0, ioPhysicalBase, &inIoSpace, &ioPhysicalBase)函数将与总线相关的地址转换为系统地址,参数1为总线类型,参数2为总线号,参数3为要转换的地址(PHYSICAL_ADDRESS类型,实际是LARGE_INTEGER型),参数4指定寄存器地址属于IO地址空间还是物理地址空间,参数5返回转换后的物理地址。观察HalTranslateBusAddress的源码得知如果是在x86平台,这个函数除了把参数3赋给了参数5其余什么都没有做,而非x86平台将inIoSpace的值置为0,表示一定是物理地址。在调用HalTranslateBusAddress前要确定从注册表中得到的寄存器地址到底是属于哪个地址空间的,例如:

ULONG inIoSpace = 1; ///1表示是IO空间
            
            PHYSICAL_ADDRESS ioPhysicalBase = {iobase, 0}; ///相当于ioPhysicalBase.LowPart = iobase


  在地址转换后就要将转换后的地址映射到驱动程序(一般IST和应用程序一样运行在用户模式)能够访问的虚拟地址空间(0x80000000以下)和ISR能够访问的静态虚拟地址空间中(0x80000000以上)。例如:


////如果地址属于物理地址空间
            
            ioPortBase = (PUCHAR)MmMapIoSpace(ioPhysicalBase, Size, FALSE);
            TransBusAddrToStatic(Isa, 0, ioPhysicalBase, Size, &inIoSpace, ppStaticAddress);


  MmMapIoSpace函数负责将物理地址映射到驱动程序能够访问的虚拟地址空间中,通过源码分析MmMapIoSpace在内部分别调用:


pVirtualAddress =VirtualAlloc(0, SourceSize, MEM_RESERVE, PAGE_NOACCESS);
            
            VirtualCopy(pVirtualAddress, (PVOID)(SourcePhys >> 8), SourceSize, PAGE_PHYSICAL | PAGE_READWRITE |
            (CacheEnable ? 0 : PAGE_NOCACHE));


  VirtualAlloc分配一块和MemLen一样大小的虚拟地址空间,因为参数1为0,所以内核自动分配。一般MemLen小于2MB,所以会在应用程序的地址空间中分配。VirtualCopy负责将硬件设备寄存器的物理地址与VirtualAlloc分配的虚拟地址做一个映射关系,这样驱动程序访问PvirtualAddress实际上就是访问第一个寄存器。因为硬件设备寄存器的物理地址一定是在512MB(CE支持RAM的最大值)以上,所以除了最后的参数要加PAGE_PHYSICAL外,第二个参数物理地址也要右移8位(或者除以256)。

       映射硬件寄存器当然PAGE_NOCACHE是必须加的。TransBusAddrToStatic函数负责将物理地址映射到ISR能够访问的静态虚拟地址空间中,当出现中断共享时,ISR要负责访问硬件设备的某一个寄存器来判断中断源,所以将寄存器的物理地址映射到静态虚拟地址空间中是必要的(ISR只能访问静态的虚拟地址空间)。所谓静态虚拟地址空间是指在OEMAddressTable中定义的虚拟地址空间(当然是0x80000000以上)。在x86平台一般这个表只定义RAM的物理地址与虚拟地址对应关系,而硬件设备的寄存器地址并不在该表中定义,所以如果要创建一块静态的虚拟地址空间供ISR访问,必须在此之前调用CreateStaticMapping函数在0xC4000000到0xE0000000虚拟地址空间中分配。TransBusAddrToStatic函数在内部就是调用了CreateStaticMapping函数。注:硬件设备的寄存器地址也可以在OEMAddressTable中定义。

////如果地址属于IO空间
            
            ioPortBase = (PUCHAR)ioPhysicalBase.LowPart;
            *ppStaticAddress=ioPortBase


  这种情况只属于x86平台,是IO空间就可以直接访问,即使是用户模式。

  SerInit函数接着初始化SER_INFO结构体成员,之后调用SL_Init函数,这个函数在ser16550中定义,负责初始化SER16550_INFO结构体,在这个结构体中保存串口8个寄存器的地址。SerInit函数执行完毕后COM_Init函数创建接收缓冲区,然后调用StartDispatchThread函数初始化中断并且创建IST。StartDispatchThread函数在内部调用InterruptInitialize函数关联SysIntr和Event,然后调用InterruptDone函数告诉内核当前串口可以中断处理,接着调用CreateThread函数创建IST线程。(over吧,再往下说就和串口硬件有关了,看多了没注释的代码我也烦!!)
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2025-1-11 06:11 , 耗时 0.102818 秒, 19 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

快速回复 返回顶部 返回列表