WINCE驱动开发之寄存器的使用

来源:互联网 发布:博奥颐和是传销吗 知乎 编辑:程序博客网 时间:2024/06/05 16:11
 

寄存器的使用:

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; 

在驱动编写中,请统一使用REGXX的宏操作。

原创粉丝点击