【问题标题】:Windows CE: Mapping Physical memory in user modeWindows CE:在用户模式下映射物理内存
【发布时间】:2014-06-20 14:20:22
【问题描述】:

我需要在运行 Windows Embedded Compact 2013 的平台上以用户模式访问物理内存。我找到了一篇文章。内存映射在内核模式驱动程序中完成,并将地址返回给用户模式程序。

在内核驱动中

BOOL BTN_IOControl(DWORD context, DWORD code, UCHAR *pInBuffer, DWORD inSize, UCHAR *pOutBuffer,DWORD outSize, DWORD *pOutSize)
{

      PDWORD tValue = (PDWORD)pOutBuffer;
          switch(code)
          {

           case IOCTL_MAP_MEMORY:
               *tValue = GetVirtualAddress();
               *pOutSize = 4;
                break;
           .....
}

GetVirtualMemory函数如下

LPOID GetVirtualAddress()
{
    volatile DWORD sDevPhysAddr = 0xe000a000;
    volatile DWORD dwSize = PAGE_SIZE;

    LPVOID lpUserAddr;
    volatile ULONG SourceSize;
    volatile ULONG SourcePhys;
    void* pvProcess = (void*)GetCallerVMProcessId();
    SourcePhys = sDevPhysAddr & ~(PAGE_SIZE - 1);
    SourceSize = PAGE_SIZE;
    RETAILMSG(1, (L"Address: %08x Size: %08x.\r\n", SourcePhys, SourceSize));

    lpUserAddr = (LPDWORD)VirtualAllocEx(pvProcess, 0, SourceSize, MEM_RESERVE, PAGE_NOACCESS);
    if (lpUserAddr == NULL) {
        RETAILMSG(1, (L"VirtualAllocEx failed. GetLastError %d.\r\n", GetLastError()));
        return NULL;
    }

    if (!VirtualCopyEx(pvProcess, lpUserAddr, GetCurrentProcess(), (PVOID)
    /*(*/SourcePhys/* >> 8)*/, SourceSize,
    /*PAGE_PHYSICAL | */PAGE_READWRITE | PAGE_NOCACHE)) {
     RETAILMSG(1, (L"VirtualCopyEx failed. Error %d.\r\n", GetLastError()));
    return NULL;
     }
     RETAILMSG(1, (L"Before round up lpUserAddr=0x%x\r\n", lpUserAddr));
     lpUserAddr = (LPVOID)((ULONG)lpUserAddr + (sDevPhysAddr & (PAGE_SIZE - 1)));
     shared_mem = lpUserAddr;
     RETAILMSG(1, (L"After round up gUserAddr=0x%x\r\n", shared_mem));
     return lpUserAddr;
 }

代码是映射物理内存0xe000a000(zynq芯片中的GPIO基地址)。代码在 VirtualCopyEx 中失败,并出现错误 87(无效参数)。但是该代码使用 0x81F00000 处的基本物理地址(该地址由原始程序员使用)。我的问题是如何启用 GPIO 地址的映射。我也愿意尝试任何其他可能的方法。

【问题讨论】:

    标签: memory-management arm windows-ce xilinx


    【解决方案1】:

    经过长时间的奋斗,我找到了答案。

     DWORD GetVirtualAddress()
     {
          HANDLE hCurrentProcess;
          HANDLE hCallerProcess;
          DWORD pAddr;
          PHYSICAL_ADDRESS pa;
          hCurrentProcess = (HANDLE)GetCurrentProcess();
          hCallerProcess = (HANDLE)GetDirectCallerProcessId();
          pa.QuadPart = 0xe000a000;
          pGpioRegs = MmMapIoSpace(pa, sizeof(XILINX_GPIO_REGS), FALSE);
          if (!pGpioRegs)
               RETAILMSG(1, (L"Cannot map the gpio register.\r\n"));
          pAddr = (DWORD)VirtualAllocCopyEx(hCurrentProcess, hCallerProcess, pGpioRegs,
                   PAGE_SIZE, PAGE_READWRITE | PAGE_NOCACHE);
          if (!pAddr)
             RETAILMSG(1, (L"VirtualAllocCopy: Error: %d.\r\n", GetLastError()));
           return pAddr;
    }
    

    这将返回给DeviceIoControl调用的调用者一个映射到设备基地址物理地址的虚拟地址。

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 2014-05-24
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-18
      • 1970-01-01
      • 2014-03-04
      相关资源
      最近更新 更多