日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WINCE下I/O操作基础

發布時間:2023/12/10 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WINCE下I/O操作基础 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
對外設進行?I/O?操作實際上也就是讀寫外設的寄存器,而我們通常使用的X86或者ARM處理器在硬件上決定了wince系統啟動后,無法直接訪問物理地址,因此需要做一些工作來實現I/O操作.??

首先要理解?windows?CE?下的地址映射機制。?wince有兩種地址:物理地址和虛擬地址.不同架構的?CPU?硬件上的區別導致地址映射也不同。MIPS和SH?x?處理器,不采用MMU,直接在CPU和內核里定義?1G?的物理地址;而X86和ARM帶有?MMU?單元,在?OEMAddressTable?中定義物理地址到虛擬地址間的映射關系或者是OS啟動后調用?CreateStaticMapping?和?NKCreateStaticMapping?來實現從虛擬地址到物理地址的靜態映射.經過靜態映射的地址,可以由操作系統內核用于?ISR?訪問設備。如果我們要在應用程序中訪問外設,必須在物理地址和虛擬地址間建立動態映射關系,我們可以使用?VirtualAlloc?和?VirtualCopy?(或者直接調用?MmmapIoSpace?函數)來實現。??

其次,如果是操作通過總線掛接的?I/O?或者存儲器,必須先把總線地址轉化成?CPU?上的系統地址,再做物理地址到虛擬地址的映射。這里需要查?CPU?的?Datasheet?,找出所要操作的I/O地址.先調用?HALTranslateBusAddress(?)把總線地址轉化成CPU上的系統地址,?再調用?MmmapIoSpace?函數實現虛實映射;也可以使用?TransBusAddrToVirtual?()直接把總線上的地址轉化成系統的虛擬地址。??

第三,在一般的應用程序中訪問?I/O?是訪問它的緩存段虛擬地址,而驅動中必須訪問無緩存段虛擬地址。簡單來說無緩存段虛擬地址?=?緩存段虛擬地址?+0x20000000?。??

????總結起來,如果是?wince?內核(如HAL)訪問外部?I/O?,只需要在?OEMAddressTable?中定義物理地址到虛擬地址間的映射關系就可以了;如果是應用程序或者驅動要訪問?I/O?,要做的工作包括:?1?。在?CPU?物理地址和虛擬地址間做一個動態映射,?2?。對虛擬地址進行操作。?


在X86和ARM架構的CPU中,wince訪問系統內存的方法隨程序所屬模式層次的不同而有所區別.?
??1.在系統內核模式下(kernel?mode),在OAL層訪問,只需要在OEMAddressTable?中做靜態的虛實地址映射就可以了.例如X86架構的映射表格式如下:?
???;?OEMAddressTable?defines?the?mapping?between?Physical?and?Virtual?Address??//?定義4GB的虛擬地址和512MB存儲的映射關系?
???;???o?MUST?be?in?a?READONLY?Section?
???;???o?First?Entry?MUST?be?RAM,?mapping?from?0x80000000?->?0x00000000?
???;???o?each?entry?is?of?the?format?(?VA,?PA,?cbSize?)?
???;???o?cbSize?must?be?multiple?of?4M?
???;???o?last?entry?must?be?(0,?0,?0)?
???;???o?must?have?at?least?one?non-zero?entry?
???;?RAM?0x80000000?->?0x00000000,?size?64M???????//把物理地址為0x00000000映射到虛擬地址為?0x80000000?處?
???dd??80000000h,????0,???04000000h?
???;?FLASH?and?other?memory,?if?any?
???;?dd??FlashVA,??????FlashPA,????FlashSize?
???;?Last?entry,?all?zeros?
???dd??0???0???0?
2.在驅動或應用程序(user?mode)中訪問RAM,既可以通過OEMAddressTable+VirtualCopy方式,也可以直接用MmMapIoSpace函數建立物理地址到當前進程虛擬地址的映射關系.?
經過OEMAddressTable,實現的只是CPU物理地址到OS內核層虛擬地址的一次映射,如果需要在普通的應用程序中訪問內存,還要再用VirtuaAlloc+VirtualCopy做一個內核到當前進程的二次映射(有一種情況例外,就是你的OS被配置成Full?Kernel?Mode,這時任何應用程序都可以訪問OS內核地址).?
?????簡單說明幾個關鍵函數:?
?????VirtualAlloc用于在當前進程的虛擬地址空間中保留或者提交空間,在保留時以64KB為單位,提交時以4KB為單位。其函數原型為??

?LPVOID?VirtualAlloc(??

??LPVOID?lpAddress,??//?分配虛擬地址的起始指針??

??DWORD?dwSize,?????//?大小,以字節為單位??

??DWORD?flAllocationType,?//?類型,設為MEM_RESERVE??

??DWORD?flProtect????//??存取保護,設為PAGE_NOACCESS??

);??

??c:??

??BOOL?VirtualCopy(??

??LPVOID?lpvDest,?????????//?虛擬目的地址指針,接受VirtualAlloc的返回值??

??LPVOID?lpvSrc,?????????//?源物理地址指針??

??DWORD?cbSize,??????????//?大小必須與虛擬地址相同??

??DWORD?fdwProtect??//?存取保護類型??

);??

這里需要注意的是?fdwProtect?參數。如果是驅動程序訪問,需要設置為?PAGE_NOCACHE?,以訪問無緩存段虛擬地址。如果映射的物理地址范圍在?0x1FFFFFFF?之上,必須使用?PAGE_PHYSICAL?,此時必須把?lpvSrc?右移八位,實現地址對齊。(這是由內核中?VirtualCopy?的實現決定的,在那個函數中會判斷如果是?PAGE_PHYSICAL?就將?PHYSADDR?左移?8?位移回來,源代碼位于?private/winceos/coreos/nk/kernel?目錄下的?virtmem.c中的DoVirtualCopy?)??

??????MmMapIoSpace?用來把物理地址直接映射到與進程無關的虛擬地址上。函數原型為??

?PVOID?MmMapIoSpace(??

??PHYSICAL_ADDRESS?PhysicalAddress,??

??ULONG?NumberOfBytes,??

??BOOLEAN?CacheEnable??

);?


??一個使用?VirtualAlloc+Copy?的例子:把物理地址為?0x10000000?的單元映射到虛擬地址空間中。??

#include?<windows.h>??

???

#define?PHYSADDR??((PVOID)0x10000000)??

//?PHYSADDR?is?the?physical?address?of?the?peripheral??

//?registers??

???

#define?SIZE??(4800*4)??

???

LPVOID?lpv;??

BOOL?bRet;??

???

lpv?=?VirtualAlloc(0,?SIZE,?MEM_RESERVE,?PAGE_NOACCESS);??

//?For?a?user?mode?driver,?always?leave?the?first??

//?parameter?0?and?use?only?the?flags?MEM_RESERVE??

//?and?PAGE_NOACCESS?Check?the?return?value:?lpv?==?0??

//?is?an?error??

???

printf(TEXT("VirtualAlloc?reservation?@%8.8lx/r/n"),?lpv);??

bRet?=?VirtualCopy(lpv,?PHYSADDR>>8,?SIZE,?PAGE_READWRITE?|?PAGE_NOCACHE?|?PAGE_PHYSICAL);?

//?The?lpv?parameter?is?the?virtual?address?returned??

//?by?VirtualAlloc().??

//?Always?use?PAGE_NOCACHE?*/??

???

//?Check?the?return?value:?bRet?==0?is?an?error?*/??

printf(TEXT("VirtualCopy?returned:?%d/r/n"),?bRet);??

???

//?At?this?point?lpv?is?a?virtual?address?which?maps??

//?the?I/O?registers??

//?at?PHYSADDR?for?SIZE?bytes?*/?

總結

以上是生活随笔為你收集整理的WINCE下I/O操作基础的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。