• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > Windows CE下驅動程序開發基礎(二)

    Windows CE下驅動程序開發基礎(二)

    作者: 時間:2006-12-09 來源:網絡 收藏
    函數SerInit接著調用函數Ser_InternalMapRegisterAddresses轉換地址并且映射地址,Ser_InternalMapRegisterAddresses在內部調用系統提供的HalTranslateBusAddress(Isa, 0, ioPhysicalBase, inIoSpace, ioPhysicalBase)函數將與總線相關的地址轉換為系統地址,參數1為總線類型,參數2為總線號,參數3為要轉換的地址(PHYSICAL_ADDRESS類型,實際是LARGE_INTEGER型),參數4指定地址屬于地址空間還是物理地址空間,參數5返回轉換后的物理地址。觀察HalTranslateBusAddress的源碼得知如果是在x86平臺,這個函數除了把參數3賦給了參數5其余什么都沒有做,而非x86平臺將inIoSpace的值置為0,表示一定是物理地址。在調用HalTranslateBusAddress前要確定從注冊表中得到的地址到底是屬于哪個地址空間的,例如:

    ULONG inIoSpace = 1; ///1表示是空間

    PHYSICAL_ADDRESS ioPhysicalBase = {iobase, 0}; ///相當于ioPhysicalBase.LowPart = iobase

    本文引用地址:http://www.czjhyjcfj.com/article/258281.htm


      在地址轉換后就要將轉換后的地址映射到驅動程序(一般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吧,再往下說就和串口硬件有關了,看多了沒注釋的代碼我也煩!!)



    關鍵詞: IO 寄存器

    評論


    相關推薦

    技術專區

    關閉
    主站蜘蛛池模板: 泰和县| 汤阴县| 锦屏县| 晋江市| 万州区| 延津县| 榆社县| 西乡县| 新兴县| 绥芬河市| 芜湖县| 淳化县| 太仆寺旗| 大理市| 兴和县| 淮南市| 手游| 乐至县| 岫岩| 公主岭市| 周口市| 沁水县| 南乐县| 鄄城县| 五原县| 应城市| 大同市| 应城市| 怀安县| 松阳县| 江西省| 庐江县| 左云县| 柯坪县| 宣城市| 通渭县| 荔浦县| 长汀县| 和平县| 邮箱| 社会|