实验二线程同步调试实验.docx

上传人:b****6 文档编号:8063276 上传时间:2023-01-28 格式:DOCX 页数:19 大小:191.33KB
下载 相关 举报
实验二线程同步调试实验.docx_第1页
第1页 / 共19页
实验二线程同步调试实验.docx_第2页
第2页 / 共19页
实验二线程同步调试实验.docx_第3页
第3页 / 共19页
实验二线程同步调试实验.docx_第4页
第4页 / 共19页
实验二线程同步调试实验.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

实验二线程同步调试实验.docx

《实验二线程同步调试实验.docx》由会员分享,可在线阅读,更多相关《实验二线程同步调试实验.docx(19页珍藏版)》请在冰豆网上搜索。

实验二线程同步调试实验.docx

实验二线程同步调试实验

实验十一驱动程序实验

[实验目的]

1、了解驱动程序的原理和功能;

2、掌握流式接口驱动程序的结构;

3、掌握编写流式接口的驱动程序的方法

4、熟悉EVC和VS.Net的开发环境;

[实验仪器]

1、装有PlatformBuilder、EVC和VS.Net开发平台的PC机一台

2、XSBase270实验开发平台一套

[实验原理]

1、硬件接口电路分析

XSBase目标板LED和七段数码显示接口电路如图6-1所示,74HC574为D锁存器,在时钟信号CLK作用下,该锁存器将输入信号进行锁存,即xQ=xD(x=1~8)。

从电路图中可以看出,LED和八段数码显示电路将74HC574的时钟信号输入端作为片选信号,其中LED显示的片选信号为LED_CS4、七段数码显示的片选信号为LED_CS1(另外还有一组七段数码显示未画出,参考原理图)。

在七段数码显示电路中,数据的高位(D7、D15:

即数码管的小数点dp段)用作七段数码的公共选通信号,通过控制PNP三极管来控制数码管的显示。

图6-1LED和七段数码显示接口电路

显示电路中的片选信号LED_CSx(x=1-4),由XSBase270目标板系统的处理器PXA270x的地址信号BA22~BA20通过3-8译码器LC138产生(如图2-2所示)。

图6-2片选信号产生电路

由3-8控制功能可知,当BA22、BA21、BA20=101时产生LED显示电路的片选信号LED_CS4,当BA22、BA21、BA20=010、011、100时分别产生七段数码显示电路的片选信号LED_CS1、LED_CS2、LED_CS3(另外2组八段显示电路参考系统提供的总电路图)。

根据分析,可以得出七段数码管和LED的片选信号为:

LED_CS1=0x10200000、LED_CS2=0x10300000、LED_CS3=0x10400000,LED_CS4=0x10500000。

2、流式接口驱动程序简介

驱动程序是对底层硬件的抽象。

应用程序开发者不需要真正理解底层驱动的工作原理,他们只需要通过WindowsCE提供的API函数,就可以直接与硬件进行交互。

WinCE的流式接口驱动程序以动态链接库的形式存在,由设备管理器(通常是device.exe或者gwes.exe)统一加载、管理和卸载。

与具有单独目的的内部设备驱动程序相比,所有流式接口驱动程序都是用同一接口并调用同一个函数集。

每个流式接口驱动程序必须实现一组标准的函数,用来完成标准的文件I/O函数和电源管理函数,这些函数提供给WinCE操作系统的内核使用。

这些函数通常叫做流式接口驱动程序的DLL接口,如表11-1所示:

(详细介绍参考实验三)

表11-1流式接口驱动程序要实现的DLL接口:

函数名称

描述

XXX_Close

在驱动程序关闭时应用程序通过CloseHandle函数调用这个函数

XXX_Deinit

当设备管理器卸载一个驱动程序时调用这个函数

XXX_Init

当设备管理器初始化一个具体设备时调用这个函数.

XXX_IOControl

上层的软件通过DeviceIoControl函数可以调用这个函数

XXX_Open

在打开一个设备驱动程序时应用程序通过CreateFile函数调用这个函数

XXX_PowerDown

在系统调用前调用这个函数

XXX_PowerUp

在系统从新启动前调用这个函数

XXX_Read

在一个设备驱动程序处于打开状态时由应用程序通过ReadFile函数调用

XXX_Seek

对设备的数据指针进行操作,由应用程序通过SetFilePointer函数调用

XXX_Write

在一个设备驱动程序处于打开状态时由应用程序通过WriteFile函数调用.

3、LED流式接口驱动程序的实现

由于在WinCE中流式接口驱动程序以DLL的形式存在,是运行在用户模式的动态链接库,所以既可以使用微软提供的EVC编写流式接口驱动程序,也可以使用PlatformBuilder(PB)来进行编写。

为了方便调试,通常采用PB来开发流式驱动程序。

下面具体介绍LED驱动程序为例介绍采用PB编写流式接口设备驱动程序的方法和步骤。

3.1流式驱动程序的创建步骤:

(1)打开PlatformBuilder。

在PlatformBuilder中选择“File”->“NewProjectorFile”,创建一个“WindowsCEDynamiclinklibrary”项目,项目的名称填写“LedDriver”(如图11-1所示)

图11-1WinCE驱动创建项目界面

(2)按OK按钮,在DLL的类型界面中(如图11-2所示)选中ASimpleWindowsCEDLLprojects,PlatformBuilder将生成DLL框架代码。

图11-2驱动程序的DLL类型选择

3.2LED流式驱动程序的源代码分析:

(1)变量定义

#defineLED_IOCTL_SET0x00000001//IO控制接口代号码

#defineLight_IOCTL_Set0x00000002

#defineLight_IOCTL_LShift0x00000003

#defineLight_IOCTL_RShift0x00000004

#defineLight_IOCTL_LRShift0x00000005

#defineLight_IOCTL_ShiftStop0x00000006

#defineLight_IOCTL_SetTime0x00000007

#defineLED_BASEADDR10x10200000//七段数码的物理地址

#defineLED_BASEADDR20x10300000

#defineLED_BASEADDR30x10400000

#definepLightIoBaseAddress0x10500000//Led物理地址

#defineBIT7(0x1<<7)

#defineBIT15(0x1<<15)

HANDLEm_hShiftEvent=NULL;//LED流水灯移动事件变量

BOOLm_bStop;//LED流水灯停止变量

UINTm_ShiftDir;//LED流水灯移动方向

UINTShiftTime;//LED流水灯时间间隔

unsignedcharShiftData;//LED流水灯赋值变量

(2)驱动程序初始化函数DEM_Init

驱动程序的初始化函数XXX_Init主要完成当用户使用一个设备的时候,设备管理器调用这个函数来对设备进行初始化。

这个函数并不是由应用程序调用的,而是通过设备管理器提供的ActiveDeviceEx()来调用。

该初始化函数主要完成LED和七段数码的物理地址到虚拟地址的转换。

DWORDDEM_Init(DWORDdwContext)

{

charblack=0xff;

RETAILMSG(1,(TEXT("Led_Init\r\n")));//从串口输出调试信息

if(!

LEDInit())

returnFALSE;

SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL);

m_hShiftEvent=CreateEvent(NULL,FALSE,FALSE,NULL);

if(m_hShiftEvent==NULL)

{

RETAILMSG(1,(TEXT("FailedtoCreatethread\r\n")));

returnFALSE;

}

*pLightReg=black;

ShiftTime=500;

m_bStop=FALSE;

m_ShiftDir=1;

returnTRUE;

}

BOOLLEDInit(void)

{charblack=0xff;

PHYSICAL_ADDRESSioPhysicalBase={LED_BASEADDR1,0};

v_pLEDBaseAddr[0]=(USHORT*)MmMapIoSpace(ioPhysicalBase,0x400,FALSE);

ioPhysicalBase.QuadPart=LED_BASEADDR2;

v_pLEDBaseAddr[1]=(USHORT*)MmMapIoSpace(ioPhysicalBase,0x400,FALSE);

ioPhysicalBase.QuadPart=LED_BASEADDR3;

v_pLEDBaseAddr[2]=(USHORT*)MmMapIoSpace(ioPhysicalBase,0x400,FALSE);

if(!

(pLightReg=(char*)VirtualAlloc(0,0x400,MEM_RESERVE,PAGE_READWRITE)))

{

RETAILMSG(1,(TEXT("VirtualAlloc()failed!

\r\n")));

returnFALSE;

}

if(!

VirtualCopy((PVOID)pLightReg,(PVOID)(pLightIoBaseAddress>>8),0x400,PAGE_READWRITE|PAGE_NOCACHE|PAGE_PHYSICAL))

{

VirtualFree((PVOID)pLightReg,0,MEM_RELEASE);

pLightReg=NULL;

RETAILMSG(1,(TEXT("VirtualCopy()failed!

\r\n")));

returnFALSE;

}

if(!

v_pLEDBaseAddr||!

pLightReg)

{

DEBUGMSG(1,(TEXT("VirtualcopyError,Errorcode=%u\r\n"),GetLastError()));

return(FALSE);

}

WRITE_PORT_USHORT(v_pLEDBaseAddr[0],0xffff);

WRITE_PORT_USHORT(v_pLEDBaseAddr[1],0xffff);

WRITE_PORT_USHORT(v_pLEDBaseAddr[2],0xffff);

*pLightReg=black;

returnTRUE;

}

(3)驱动程序卸载函数DEM_Deinit:

当设备管理器卸载一个驱动程序时调用驱动程序卸载函数XXX_Deinit,该函数完成对系统资源的回收。

BOOLDEM_Deinit(DWORDhDeviceContext)

{

UINTi=0;

RETAILMSG(1,(TEXT("DEM_Deinit\r\n")));

for(i=0;i<3;i++)

{

MmUnmapIoSpace(v_pLEDBaseAddr[i],0);

v_pLEDBaseAddr[i]=NULL;

}

if(pLightReg)

{

MmUnmapIoSpace(pLightReg,0);

pLightReg=NULL;

}

if(m_hShiftEvent)

CloseHandle(m_hShiftEvent);

returnTRUE;

}

(4)驱动程序的读写操作DEM_Read、DEM_Write:

当一个流式接口驱动程序已经打开后,可以使用ReadFile()函数和WriteFile()函数对这个设备进行读写操作。

该驱动程序的读操作完成将LED的亮灭的情况输出,应用程序通过ReadFile()函数,写操作函数对四个七段数码管进行点亮。

具体实现函数如下:

DWORDDEM_Read(DWORDhOpenContext,LPVOIDpBuffer,DWORDCount)

{

UINTtemp;

temp=(UINT)ShiftData;

RETAILMSG(1,(TEXT("LED_Read\r\nhOpenContext=%d;*pBuffer=%d;Count=%d\r\n"),hOpenContext,temp,Count));

*(UINT*)pBuffer=temp;

returnTRUE;

}

DWORDDEM_Write(DWORDhOpenContext,LPCVOIDpSourceBytes,DWORDNumberOfBytes)

{

INTbuf=*(INT*)pSourceBytes;

USHORTData;

RETAILMSG(1,(TEXT("DEM_Write\r\nhOpenContext=%d;*pSourceBytes=%d;NumberOfBytes=%d\r\n"),hOpenContext,buf,NumberOfBytes));

buf=buf%10000;

Data=NumData[buf/1000];

buf=buf%1000;

Data|=NumData[buf/100]<<8;

WRITE_PORT_USHORT(v_pLEDBaseAddr[1],~(Data|BIT7|BIT15));

buf=buf%100;

Data=NumData[buf/10];

buf=buf%10;

Data|=NumData[buf]<<8;

WRITE_PORT_USHORT(v_pLEDBaseAddr[2],~(Data|BIT7|BIT15));

returnTRUE;

}

(5)IO控制函数DEM_IOControl

XXX_IOControl通常用于向设备发送一个命令,应用程序使用DeviceIOControl函数来通知操作系统调用该函数。

LED驱动程序的DEM_IOControl函数主要完成对八个LED发光二极管的流水左移、流水右移、流水循环、流水停止、点亮设置、流水移动时间间隔进行控制,采用线程完成流水操作。

BOOLDEM_IOControl(DWORDhOpenContext,DWORDdwCode,PBYTEpBufIn,DWORDdwLenIN,PBYTEpBufOut,DWORDdwLenOut,PDWORDpdwActualOut)

{

charData;

HANDLEm_hShiftThread=NULL;

RETAILMSG(1,(TEXT("LED_IOControl\r\nhOpenContext=%d;dwCode=%d\r\n"),hOpenContext,dwCode));

m_hShiftThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)LedShiftThread,NULL,0,NULL);

switch(dwCode)

{

caseLight_IOCTL_LShift:

m_ShiftDir=1;

SetEvent(m_hShiftEvent);

break;

caseLight_IOCTL_RShift:

m_ShiftDir=2;

SetEvent(m_hShiftEvent);

break;

caseLight_IOCTL_LRShift:

m_ShiftDir=3;

SetEvent(m_hShiftEvent);

break;

caseLight_IOCTL_Set:

Data=*(char*)pBufIn;

*pLightReg=~Data;

break;

caseLight_IOCTL_ShiftStop:

m_bStop=TRUE;

break;

caseLight_IOCTL_SetTime:

ShiftTime=*(UINT*)pBufIn;

break;

}

CloseHandle(m_hShiftThread);

returnTRUE;

}

INTWINAPILedShiftThread(void)

{

UINTi=0;

WaitForSingleObject(m_hShiftEvent,INFINITE);

while

(1)

{

switch(m_ShiftDir)

{

case1:

ShiftData=0x01;

for(i=0;i<8;i++)

{

*pLightReg=~ShiftData;

Sleep(ShiftTime);

ShiftData=ShiftData<<1;

if(m_bStop)

{

*pLightReg=0xff;

m_bStop=FALSE;

return0;

}

}

break;

case2:

ShiftData=0x80;

for(i=0;i<8;i++)

{

*pLightReg=~ShiftData;

Sleep(ShiftTime);

ShiftData=ShiftData>>1;

if(m_bStop)

{

*pLightReg=0xff;

m_bStop=FALSE;

return0;

}

}

break;

case3:

ShiftData=0x01;

for(i=0;i<8;i++)

{

*pLightReg=~ShiftData;

Sleep(ShiftTime);

ShiftData=ShiftData<<1;

if(m_bStop)

{

*pLightReg=0xff;

m_bStop=FALSE;

return0;

}

}

ShiftData=0x80;

for(i=0;i<8;i++)

{

*pLightReg=~ShiftData;

Sleep(ShiftTime);

ShiftData=ShiftData>>1;

if(m_bStop)

{

*pLightReg=0xff;

m_bStop=FALSE;

return0;

}

}

break;

default:

m_bStop=FALSE;

return0;

break;

}

}

return0;

}

其他实现函数如:

DEM_Open、DEM_PowerDown、DEM_PowerUp、DEM_Seek、DEM_Close参考提供的源代码文档。

(6)添加导出函数的定义。

在PlatformBuilder菜单中,选择File->NewProjectorFile->FileTab->TextFile,文件名叫“LedDriver.def”,内容如下:

LIBRARY"LedDriver"

EXPORTS

DEM_Init

DEM_Deinit

DEM_Open

DEM_Read

DEM_Write

DEM_PowerDown

DEM_PowerUp

DEM_Seek

DEM_IOControl

DEM_Close

(7)编译驱动程序项目。

结束后选择“BuildOS”->“OpenBuildReleaseDirectory”,然后输入命令:

dumpbin/exportsLedDriver.dll,确保输出结果如图11-3,表示驱动程序的DLL函数被正确导出。

图11-3驱动程序的函数导出图

3.2LED流式驱动程序的加载:

(1)选择“BuildOS”->“OpenBuildReleaseDirectory”,利用文本编辑器notepad修改平台的注册文件platform.reg,在文件最后添加如下内容:

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\LedDriver]

"Dll"="LedDriver.Dll"

"Prefix"="DEM"

"Index"=dword:

1

"Order"=dword:

0

"FriendlyName"="LEDDriver"

这段注册表信息告诉系统,在系统启动的时候把LedDriver.dll加载到device.exe,驱动的前缀是DEM,下标索引是1,这样,应用程序中可以使用CreateFile(L"DEM"……)这样的方式来访问驱动程序了。

(2)驱动程序固化

选择“BuildOS”->“OpenBuildReleaseDirectory”,利用文本编辑器notepad修改平台的配置文件platform.bib,将驱动程序LedDriver.dll文件固化到映像文件中在文件,在platform.bib文件中具体添加内容如下:

LedDriver.dll$(_FLATRELEASEDIR)\LedDriver.dllNKSH

③、生成映像文件

选择“BuildOS”->“MakeRun-TimeImage”生成映像文件,然后下载到目标板中。

4、LED流式接口驱动程序的应用测试

利用VS.net编写一个驱动程序的应用测试程序DriverApp。

具体实现如下:

●打开设备

voidCDriverAppDlg:

:

OnBnClickedbtnopendevice()

{

TCHARFileName[10]=TEXT("DEM1:

");

m_hFile=CreateFile((LPCTSTR)&FileName,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ,

NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

if(m_hFile==NULL){

MessageBox(_T("打开LED设备失败!

"),_T("系统信息"),MB_OK|MB_ICONINFORMATION);

}

}

●LED流水灯左移

voidCDriverAppDlg:

:

OnBnClickedbtnlshift()

{

if(m_hFile)

{

if(!

DeviceIoControl(m_hFile,Light_IOCTL_RShift,NULL,0,NULL,0,NULL,NULL))

{

MessageBox(_

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育 > 幼儿读物

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1