wince 如何访问物理地址

时间:2021-06-13 17:31:24

WINCE驱动开发-寄存器的使用 一:寄存器的使用: 1、wince内部对物理地址的访问: 可以有3个途径。 1:直接使用g_oalAddressTable(oemaddrtab_cfg.inc)的已经定义好的,物理地址对应的虚拟地址。 如: DCD 0x80000000, 0x30000000, 128 ; 访问虚拟地址0x80000000实际就是访问物理地址0x30000000。 2:在OAL层,使用OALPAtoVA函数。 如: volatile S3C2410X_IOPORT_REG *pIOCTR; pIOCTR = (volatile S3C2410X_IOPORT_REG *)OALPAtoVA(S3C2410X_BASE_REG_PA_IOPORT, FALSE); 那么在访问pIOCTR指向的首地址,实际就是访问被映射后S3C2410X_BASE_REG_PA_IOPORT定义的物理地址。 VOID* OALPAtoVA( UINT32 pa, 参数1:需要映射的物理地址 BOOL cached 参数2:是否使用cache(驱动中要使用uncached)) 3:在kernel里,使用MmMapIoSpace函数。 如: pBaseAddress = (PUCHAR)MmMapIoSpace(ioPhysicalBase, Size, FALSE); 同上,访问pBaseAddress的指向地址,就为访问被映射后ioPhysicalBase定义的物理地址。 PVOID MmMapIoSpace( PHYSICAL_ADDRESS PhysicalAddress, 参数1:需要映射的物理地址 ULONG NumberOfBytes, 参数2:映射的地址长度 BOOLEAN CacheEnable 参数3:是否使用cache(驱动中要使用uncached)); 与OALPAtoVA不同,在使用MmMapIoSpace后,必须使用MmUnmapIoSpace。 VOID MmUnmapIoSpace( PVOID BaseAddress, 参数1:被映射后的虚拟地址 ULONG NumberOfBytes 参数2:映射的地址长度); 在一般的NK驱动编写中,为了规范编程风格,请勿直接使用g_oalAddressTable中的虚拟地址。统一使用MmMapIoSpace、MmUnmapIoSpace函数。 2、wince标准的寄存器访问 定义一个结构体。此结构包含某功能模块的寄存器地址。 如: typedef struct { UINT32 GPACON; // Port A - offset 0 UINT32 GPADAT; // Data UINT32 PAD1[2]; …… …… UINT32 GSTATUS0; // external pin status UINT32 GSTATUS1; // chip ID UINT32 GSTATUS2; // reset status UINT32 GSTATUS3; // inform register UINT32 GSTATUS4; // inform register } S3C2410X_IOPORT_REG, *PS3C2410X_IOPORT_REG; volatile S3C2410X_IOPORT_REG *pIOCTR; pIOCTR = (volatile S3C2410X_IOPORT_REG *)OALPAtoVA(S3C2410X_BASE_REG_PA_IOPORT, FALSE); 这样,访问pIOCTR的各个成员,就为访问被映射后S3C2410X_BASE_REG_PA_IOPORT定义的物理偏移地址。 为了统一、兼容平台的驱动代码,我们加入了寄存器操作宏(oal_io.h): #define REG8(_register_) (*(volatile unsigned char *)(_register_)) #define REG16(_register_) (*(volatile unsigned short *)(_register_)) #define REG32(_register_) (*(volatile unsigned long *)(_register_)) 访问模块中的功能寄存器,使用加上偏移地址的方式。 #define USB_REG_FADDR_OFFSET (0x0000) #define USB_REG_POWER_OFFSET (0x0001) 例子: 要编写某个模块的驱动,首先使用MmMapIoSpace或OALPAtoVA建立物理地址映射关系。 volatile BYTE *pUSBCtrlAddr; pUSBCtrlAddr= (volatile BYTE *)OALPAtoVA(AK3224_BASE_REG_PA_USB, FALSE); 这样,usb模块的首地址就为pUSBCtrlAddr的指向地址。然后,使用REGXX的宏来访问各个功能寄存器。 REG8(pUSBCtrlAddr + USB_REG_POWER_OFFSET) = USB_POWER_ENSUSPEND; ucIntStatusR = REG16(pUSBCtrlAddr + USB_REG_INTRRX1_OFFSET); REG32(pUSBCtrlAddr + USB_DMA_COUNT_1_OFFSET) = 256;