微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > MapPtrToProcess 用法 WINCE驱动分析3

MapPtrToProcess 用法 WINCE驱动分析3

时间:02-24 来源:互联网 点击:

下,看看应用程序的代码:

COPY_STRUCT cs[1];

auto char data1[10];

auto char data2[10];

cs结构和data1,data2数组都是自动变量,存放在堆栈里。假设这个应用程序被加载到0x18000000位置的slot里,那么他们的地址都是0x18XXXXXX。不熟悉wince memory architecture的可以看看资料,了解一下slot。当调用了

DeviceIoControl,按照文档的说法,cs指针得到了转换,因为从应用程序的进程转到了device.exe进程,而device进程又是当前的运行的进程,被映射到了slot0,系统负责转换cs指针。而cs包含的pBuffer1和pBuffer2是没有映射不能直接用的。

事实上,我们传过来的指针根本就是不需要映射,因为他们都是0x18xxxxxx,在应用程序的slot里,所以只要device.exe有访问应用程序的权限,就可以了。而这个权限,系统已经帮我们设置好了。

那什么情况下要自己映射呢?

如果应用程序在定义 data1和data2使用static关键字,或者使用LocalAlloc,HeapAlloc的时候,一定要自己映射cs里的指针。

在应用程序里这样写:

cs.pBuffer1 = (char *)malloc(10);

cs.pBuffer2 = (char*)malloc(10);

cs.nLen = 10;

如果不使用MapPtrToProcess完成映射,那就出现data abort exception.

为什么呢?

因为这些变量都是在堆里分配的,而当应用程序运行时,被映射到slot0,堆的地址也就是处于slot的范围内,传递到device.exe后,device.exe被映射到了slot0,这个时候必须要将应用程序的指针映射回应用程序所在的slot。否则访问的是device.exe的空间,会发生不可知道的结果。

验证一下上面说的地址分配问题。

我们这样定义

COPY_STRUCT cs[1];

static char data1[10]; 堆里

auto char data2[10]; 栈里

这样赋值:

cs[0].pBuffer1 = data1[0];

cs[0].pBuffer2 = data2[0];

cs[0].nLen = 10;

调试信息:

cs[0].pBuffer1 = data1[0];

180112D0 ldr r2, [pc, #0xD0]

180112D4 str r2, [sp, #0x10]

读取data1[0]使用的是PC作为基址,而此时的应用程序处于运行阶段映射到slot0,那么pc也就在0~01ffffff范围,我的调试结果是在0x000112D0+8,使用的是arm,流水线机制,当前指令地址+8才是pc值。

143: cs[0].pBuffer2 = data2[0];

180112D8 add r0, sp, #0x20

180112DC str r0, [sp, #0x14]

读取data2[0]采用的是sp作为基址,sp在应用程序加载到slot的时候就确定了的。所以保持了在应用程序slot的值,处于0x18xxxxxx范围。

我们看到因为wince的slot机制,我们有时候需要映射,有时候不需要。所以wince文档说结构里的指针要映射。毕竟你不知道应用程序怎么写。

当然,你可以根本不映射,只要把那个结构屏蔽调,写一个STATIC LIBRARY给用户使用,自己保证使用正确的地址分配就可以了。上面我说的那个家伙就是这么干的。

好了,接着调用:

CloseHandle(hnd);

程序结束了,完成了一次简单的拷贝。

这个框架完成了,driver的基本接口设计,强调了内存指针的使用问题。但是相对于一个真正的driver,还缺少点东西,就是访问硬件的方法。下面继续讨论如何访问硬件

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top