阅读:2572回复:7
求助!关于在wince下访问硬件寄存器的问题
我想在wince的应用程序中控制gpio口,下面是部分相关程序
PHYSICAL_ADDRESS IoAddress; IoAddress.LowPart = 0x56000050;\\这是arm9 GPFCON控制寄存器的硬件地址 IoAddress.HighPart = 0; ULONG * gpioPtr; gpioPtr = ( ULONG *)MmMapIoSpace( IoAddress,40,FALSE ); WRITE_REGISTER_ULONG(gpioPtr,numDatWrite);\\写0x56000050寄存器 WRITE_REGISTER_ULONG((gpioPtr+4),numDatWrite);\\写0x56000054寄存器 然后我debug这个应用程序,发现虚拟地址映射是成功的,写0x56000050寄存器也是成功的,但是写0x56000054寄存器时,evc出错,跟硬件短开了 以下是错误代码 C Run-Time Error R6025pure virtual function call No object has been instantiated to handle the pure virtual function call. This error is caused by calling a virtual function in an abstract base class through a pointer which is created by a cast to the type of the derived class, but is actually a pointer to the base class. This can occur when casting from a void* to a pointer to a class when the void* was created during the construction of the base class. 但是我假如我修改上面的代码,不写0x56000050这个寄存器,而是直接写0x56000054时,不会报错,但是数值写不到寄存其中去,真是奇哉怪也啊 哪位能指点下迷津呢? |
|
最新喜欢:jediji... |
论坛版主
|
沙发#
发布于:2004-10-21 13:32
我虽然没有试过mmmapiospace能不能工作,但是我认为即使可以工作也最好不要使用这个函数,我觉得这个函数是用在那些memroy空间和io空间独立编址的处理器中的,这个函数应该用于映射io空间到进程虚拟地址空间。
arm是memroy和io统一编址的,所有外围设备的访问都是对memory空间进行,所以应该使用virtualalloc在进程虚拟地址空间中分配一段,然后把你的gpio寄存器的地址空间用virtualcopy映射到这段空间,用下面这个试试吧: 参数给出你要映射的物理地址空间的首地址和长度 返回可用的虚拟地址 PVOID MyVirtualMap(PVOID PhyMem, UINT32 size) { PVOID pVirtualAddr; pVirtualAddr = VirtualAlloc( 0, size, MEM_RESERVE, PAGE_NOACCESS ); if(pVirtualAddr == NULL) { RETAILMSG(1,(TEXT("MyVirtualMap : pVirtualAddr is not allocated!\n\r"))); RETAILMSG(1,(TEXT("MyVirtualMap : Error code = 0x%x\n\r"),GetLastError())); return NULL; } if( !VirtualCopy(pVirtualAddr, PhyMem, size, PAGE_READWRITE | PAGE_NOCACHE ) ) { RETAILMSG(1, (TEXT("MyVirtualMap : pVirtualAddr is not mapped!\n\r"))); RETAILMSG(1,(TEXT("MyVirtualMap : Error code = 0x%x\n\r"),GetLastError())); VirtualFree((PVOID)pVirtualAddr, 0, MEM_RELEASE); return NULL; } return pVirtualAddr; } 使用的是有注意事项有: 1.参数中所谓的物理地址,其实也是一个变幻过的地址,其实是wince内核虚拟地址, 2.物理地址必须4k对齐,这个msdn的帮助没有说,我试出来的 |
|
板凳#
发布于:2004-10-21 14:42
哎呀,又是你啊,真是个热心人,我现在就回去试试! :D
|
|
论坛版主
|
地板#
发布于:2004-10-21 14:59
要得!最近在弄wince,所以经常和兄弟们探讨一下:)
|
|
地下室#
发布于:2004-10-22 08:55
哎,今天用你的方法试了一下,还是在写寄存器的时候出错被强行断开,我好迷惘啊。。。。
下面这个是我的部分代码,为了方便,把好多输出调试信息的语句都去掉了 DWORD size=128; PVOID pVirtualAddr; BOOL x; pVirtualAddr = VirtualAlloc( 0, size, MEM_RESERVE, PAGE_NOACCESS ); x=VirtualCopy(pVirtualAddr, (void *)(0xb1600000/256), size, PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL) ; WRITE_REGISTER_ULONG((ULONG*)pVirtualAddr,0x00000000); |
|
5楼#
发布于:2004-10-22 10:37
参考XSCALE BSP里关于VirtualAllocCopy的实现吧.注意物理地址4K对齐.
还有你的硬件地址到系统的物理地址的影射关系是什么样的? 0x56000050 -- > 0xb1600000 ?好象不太对哦. 所以你要处理好自己的对齐关系,然后加OFFSET去找到要设置的寄存器. 另外,关于VirtualCopy的用法, 如果你的参数里带了 PAGE_PHYSICAL, 那你传入的lpvSrc参数应该是硬件地址/256 , 如果不带PAGE_PHYSICAL, 那么应该传入系统的物理地址. #define PAGE_SIZE 0x1000 #define ALIGNMENT_MASK (PAGE_SIZE-1) PVOID VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress) { PVOID ptr; unsigned offset; offset = (unsigned)pVirtualAddress & ALIGNMENT_MASK; size +=offset ? PAGE_SIZE : 0; ptr = VirtualAlloc(0,size,MEM_RESERVE,PAGE_NOACCESS); if (ptr == NULL) { ERRORMSG(1,(TEXT("VirtualAlloc failed! %s : size=0x%x, (0x%x)\r\n"),str,size,GetLastError())); return(0); } if (!VirtualCopy((PVOID)ptr,(PVOID)((unsigned)pVirtualAddress - offset),size,PAGE_READWRITE|PAGE_NOCACHE)) { ERRORMSG(1,(TEXT("VirtualCopy failed! %s : addr=0x%x, offset=0x%x(0x%x)\r\n"),str,(unsigned)pVirtualAddress,offset,GetLastError())); return(0); } return((PVOID)((PBYTE)ptr+offset)); } |
|
|
6楼#
发布于:2004-10-22 12:13
刚才终于成功了!
下面是代码,给大家参考下 相关参数的定义在2410.h中,如下 // Registers : I/O port // #define IOP_BASE 0xB1600000 // 0x56000000 typedef struct { unsigned int rGPACON; // 00 unsigned int rGPADAT; unsigned int rPAD1[2]; unsigned int rGPBCON; // 10 unsigned int rGPBDAT; unsigned int rGPBUP; unsigned int rPAD2; unsigned int rGPCCON; // 20 unsigned int rGPCDAT; unsigned int rGPCUP; unsigned int rPAD3; unsigned int rGPDCON; // 30 unsigned int rGPDDAT; unsigned int rGPDUP; unsigned int rPAD4; unsigned int rGPECON; // 40 unsigned int rGPEDAT; unsigned int rGPEUP; unsigned int rPAD5; unsigned int rGPFCON; // 50 unsigned int rGPFDAT; unsigned int rGPFUP; unsigned int rPAD6; unsigned int rGPGCON; // 60 unsigned int rGPGDAT; unsigned int rGPGUP; unsigned int rPAD7; unsigned int rGPHCON; // 70 unsigned int rGPHDAT; unsigned int rGPHUP; unsigned int rPAD8; unsigned int rMISCCR; // 80 unsigned int rDCKCON; unsigned int rEXTINT0; unsigned int rEXTINT1; unsigned int rEXTINT2; // 90 unsigned int rEINTFLT0; unsigned int rEINTFLT1; unsigned int rEINTFLT2; unsigned int rEINTFLT3; // A0 unsigned int rEINTMASK; unsigned int rEINTPEND; unsigned int rGSTATUS0; // AC unsigned int rGSTATUS1; // B0 unsigned int rGSTATUS2; // B4 unsigned int rGSTATUS3; // B8 unsigned int rGSTATUS4; // BC }IOPreg; 其实我要做的就是让把GPF0和GPF2设置成IO输出工作方式,让他们输出一个高低电平不断变换的波形 下面是部分代码 BOOL x; int n,m; v_pIOPRegs = (volatile IOPreg *)VirtualAlloc(0, sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS); x=VirtualCopy((PVOID)v_pIOPRegs, (PVOID)IOP_BASE, sizeof(IOPreg), PAGE_READWRITE|PAGE_NOCACHE); v_pIOPRegs->rGPFCON = (v_pIOPRegs->rGPFCON & 0x00000000) | (0x11);//将GPFn配置成数据输出方式 while(1) { for(n=0;n<100;n++)//延时 { m=n; } v_pIOPRegs->rGPFUP=(v_pIOPRegs->rGPFUP&0x0); v_pIOPRegs->rGPFDAT=(v_pIOPRegs->rGPFDAT|0xf);\\输出高 for(n=0;n<100;n++)\\延时 { m=n; } v_pIOPRegs->rGPFUP=(v_pIOPRegs->rGPFUP|0xf); v_pIOPRegs->rGPFDAT=(v_pIOPRegs->rGPFDAT&0x0);\\输出低 } 这样,我用示波器就可以从GPF0 和GPF2上面检测到一个方波的波形了,我估计原来一直出错的原因可能是因为使用WRITE_REGISTER_ULONG这个函数造成的 [编辑 - 10/22/04 by zq2002] |
|
论坛版主
|
7楼#
发布于:2004-10-22 13:36
那个东西的定义:
#define WRITE_REGISTER_ULONG(reg, val) \ (*(volatile unsigned long * const)(reg)) = (val) 不应该是这个的问题,不过这样用: WRITE_REGISTER_ULONG(&(v_pIOPRegs->rGPFCON), val) |
|