分类: 嵌入式
2010-04-02 09:58:37
一、编写LED驱动程序
具体代码请参考 \WINCE500\PLATFORM\SMDK2440A\Src\Drivers\wyleddrvr
1、Wyleddrvr.cpp LED流驱动文件
标准流接口驱动函数
1) DWORD LED_Init(DWORD dwContext)
该函数是驱动挂载后第一个被执行的,主要负责完成对设备的初始化操作和驱动的安全性检查。
DWORD LED_Init(DWORD dwContext)
{
DWORD isSuccess=1;//assume success
DWORD error=0; //接受出错码
/* IO Register Allocation */
RETAILMSG(1,(TEXT("LED_init\r\n")));
//为v_pIOPregs变量分配虚拟空间
v_pIOPregs = (volatile S3C2440A_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2440A_IOPORT_REG), MEM_RESERVE,PAGE_NOACCESS);
if (v_pIOPregs == NULL) //分配虚拟空间不成功
{
ERRORMSG(1,(TEXT("For IOPregs : VirtualAlloc failed!\r\n")));
error=GetLastError(); //获得出错码
printf("For IOPregs : VirtualAlloc failed!%d\r\n",error);
isSuccess = 0;
}
else
{
if(!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(S3C2440A_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE)) /*把v_pIOPregs虚拟空间映射到物理内存*/
{
ERRORMSG(1,(TEXT("For IOPregs: VirtualCopy failed!\r\n")));
isSuccess = 0;
}
}
if (!isSuccess) /*分配虚拟空间或映射到物理内存失败*/
{
if (v_pIOPregs) /* 如果v_pIOPregs变量非无效*/
{
VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE); /*释放虚拟空间*/
}
v_pIOPregs = NULL;
}
return (isSuccess);
}
2) BOOL LED_Deinit( DWORD dwData)
整个驱动中最后执行。用来停止和卸载设备
BOOL LED_Deinit( DWORD dwData)
{
DEBUGMSG(ZONE_PDD, (_T("LED_Deinit: invoked\r\n")));
if (v_pIOPregs) /* 如果v_pIOPregs变量非无效*/
{
VirtualFree((PVOID) v_pIOPregs, 0, MEM_RELEASE); /*释放虚拟空间*/
v_pIOPregs = NULL;
}
return true;
}
3)BOOL LED_Open( DWORD dwData,DWORD dwAccess,DWOR dwShareMode)
打开设备,此驱动不需要这个操作直接返回TRUE
4)BOOL LED_Close( DWORD dwData)
关闭设备,此驱动不需要这个操作直接返回TRUE
5)DWORD LED_Read( DWORD dwData,LPVOID pBuf, DWORD dwLen)
读LED状态
DWORD LED_Read( DWORD dwData,LPVOID pBuf, DWORD dwLen)
{
return (v_pIOPregs->GPBDAT & 0x01 << 4); /*返回led灯的状态,返回0表示灯亮,返回非0值表示灯灭*/
}
6) DWORD LED_Write(DWORD dwData,LPCVOID pInBuf,DWOR dwInLen);
写设备,pInBuf为缓冲区指针,由writefile()函数传递过来
DWORD LED_Write(DWORD dwData,LPCVOID pInBuf,DWORD dwInLen)
{
v_pIOPregs->GPFCON |=0x01<< 8; //配置为输出模式
if((v_pIOPregs->GPBDAT & 0x1<< 4)) //读灯的状态,如果是灭的
{
v_pIOPregs->GPBDAT &=0x0<< 4; //打开灯
return true;
}
else
{
v_pIOPregs->GPBDAT |=0x1 << 4 //否则开闭灯
return true;
}
}
7 )
void LED_PowerUp( DWORD hDeviceContext );
void LED_PowerDown( DWORD hDeviceContext );
DWORD LED_Seek(DWORD dwData,long pos,DWORD type);
BOOL LED_IOControl(DWORD dwData,DWORD dwCode, PBYTE
pBufIn,DWORD dwLenIn,PBYTE pBufOut,
DWORD dwLenOut,PDWORD pdwActualOut);
上面这些流接口函数是有关电源管理和IO操作的,这里用不到,所以插入空
码或直接返回。
8)
BOOL WINAPI DllMain(HANDLE hInstDLL, DWORD dwReason, LPVOID lpvReserved)
流驱动入口函数
注意:在写流驱动时为了把接口函数暴露出来给应用程序调用,在实现流驱动
之前对流驱动接口函数进行声名。或者写个头文件把接口函数的声名放
这个头文件里,再写个cpp文件包含这个头文件,然后再实现这些流驱动。
2、wyledrvr.def 接口文件
.def文件的作用就是把流接口函数暴露出来
3、Sources 编译控制文件
TARGETNAME=wyleddrvr 指定目标名
TARGETTYPE=DYNLINK 指定编译成dll即动态链接库
DLLENTRY=DllMain 指定DllMain为驱动入口函数
DEFFILE=myleddri.def 指定myleddri.def流接口函数暴露文件
TARGETLIBS=$(_SYSGENSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib \
$(_SYSGENOAKROOT)\lib\$(_CPUINDPATH)\ceddk.lib \ 指定要用到的库
SOURCES = \
wyleddrvr.cpp 指定要编译的源文件
4、wyleddrvr.reg 注册表文件
"Prefix"="LED" 指定驱动程序的前缀,要跟XXX_init等函数一致
"Dll"="wyleddrvr.dll" 指定调用的动态库
"Order"=dword:0 指定加载顺序,0表示最先加载
"Index"=dword:1 表示索引号,应用程序通过Prefix指定的前缀和索引号来打开此设备,比如之前应用程序CreateFile打开的LED1
二、建立LED流驱动框架
1、在WINCE根目录的PLATFORM\SMDK2440A\Src\Drivers(比如 F:\WINCE500\PLATFORM\SMDK2440A\Src\Drivers)新建一个文件夹wyleddrvr,用来存放驱动程序,把我们编写好的流驱动程序相关的文件wyleddrvr.cpp、myleddrvr.reg、wyleddrvr.def、Sources文件放在些目录下。
2、打开PB5.0,新建一个工程文件,具体操作请参考手册有关wince部分,注意要生成中文的内核,按照手册添加完必要的驱动后,在PB中的Fileview找到PLATFORM\SMDK2440A\drivers\myleddrvr驱动,点右键选择Built Curret Project编译此驱动程序。编译后,在WINCE500\PLATFORM\SMDK2440A\target\ARMV4I\retail生成一个wyleddrvr.dll动态链接库。
如果想把驱动程序编译进内核让wince启动自己加载,请按照如下步骤进行:
a、在WINCE500\PLATFORM\SMDK2440A\Src\Drivers目录下修改dirs文件,在
# AtapiRomi之前添加wyleddrvr \
b、打开PB5.0,在ParameterView下修改platform.bib和platform.reg文件,在platform.bib添加如下内容
wyleddrvr.dll $(_FLATRELEASEDIR)\wyleddrvr.dll NK SH
在platform.reg添加如下内容
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\WyLedDrvr]
"Prefix"="LED"
"Index"=dword:1
"Dll"="wyleddrvr.dll"
"Order"=dword:0
c、在菜单上选择Build OS/Sysgen(注意把Copy files to Release Directory After Build 和Make Run-time Image After Build选上)重新编译内核。
三、加载USB同步驱动
1、把编译好的NK.bin烧写到开发板上,烧写步骤参考手册。
2、安装ActiveSync4.5,ActiveSync是USB同步功能
3、安装USB同步驱动。将 USB 打印线一头接在WY2440的 USB DEV口,另一头插
在 PC 的 USB 口上,进入 WINCE5.0 系统后,PC会提供发现新的硬件,如下:
a.选择“否,暂时不”点击下一步;
b.选择“从列表或指定位置安装”点击下一步;
c.点击“浏览”,选择USB同步驱动wceusbsh.inf的目录,点击下一步;
d.提示该驱动“没有通过Windows微标测试”时,点解仍然继续;
e.点击完成,驱动安装完毕。
此时同步软件 Activesync 会自动打开,第一次使用时会提供 USB 同步是否选择同步,选择后要将“文件”部分选上,确定后将出现下面窗口进入。全部使用默认的配置,不需要作修改。 选择是,然后下一步。
4、完成以上步骤后,打开我的电脑,可以看到有一个“移动设备”的图标,这时打开“移动设备”就可以对wince的目录进行读写操作,把之前生成的wyleddrvr.dll放到wince的windows目录下,把我们提供驱动调试工具DM.exe和myleddrvr.reg放在wince当前目录。
5、点击触摸屏100打开“我的设备”,双击运行驱动调试工具DM.exe,打开驱动调试->导入注册表,把led驱动信息添加到注册表中,再点击激活驱动led灯驱动就加载进系统进程了,此时本来亮着的led灯就灭了,led驱动加载正常