Windows CE .NET Device Driver

Preview:

DESCRIPTION

Windows CE .NET Device Driver. 경희대학교 컴퓨터 공학과 조 진 성. 목차. Overview of device driver GPIO_LED device driver 제작 KEYPAD device driver 제작 KEYPAD, GPIO_LED 를 이용한 application 제작. Overview of Device Driver. Device driver. OS 와 application 에게 적절한 인터페이스를 제공한다 . - PowerPoint PPT Presentation

Citation preview

Embedded System Lab. II

Windows CE .NETWindows CE .NETDevice DriverDevice Driver

경희대학교 컴퓨터 공학과조 진 성

Embedded System Lab. II 2

목차

Overview of device driver

GPIO_LED device driver 제작

KEYPAD device driver 제작

KEYPAD, GPIO_LED 를 이용한 application 제작

Embedded System Lab. II

Overview of Device DriverOverview of Device Driver

Embedded System Lab. II 4

Device driver

OS 와 application 에게 적절한 인터페이스를 제공한다 .

Application programmer 는 device driver 를 사용하여 하드웨어에 관한 지식 없이 하드웨어를 사용할 수 있다 .

Embedded System Lab. II 5

WINCE device driver

Application 에서 직접 H/W 제어 불가 제어를 하기 위해서는 device driver 나 커널을 통해서 제어

Device driver 개발 MS “Platform Builder”

네 가지 프로세서를 지원하는 컴파일러 각종 라이브러리 , 소스코드 등을 포함 커널 포팅 및 device driver, Application 같은 모듈 개발

MS “eMbedded Visual C++” : WinCE 용 Native Application 개발 Visual Studio.net 2003 : Managed Application 개발

다른 OS device driver 와 달리 User Mode 에서 동작한다 . dynamic 또는 static 하게 OS 에 링크된다 . 인터럽트를 받는 부분은 커널 소스를 수정하여야 한다 . 커널은 device driver 에게 인터럽트 발생 메시지를 전송한다 .

Embedded System Lab. II 6

WINCE device driver

일반적인 디바이스 드라이버는 디바이스 매니저가 로드 / 관리의 작업수행 용도에 따라 FileSys, GWES 에서 관리 디바이스 매니저가 관리

HKEY_LOCAL_MACHINE\Drivers 레지스트리에 저장 GWES 가 관리

HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP 위치

Embedded System Lab. II 7

WINCE device driver 의 종류

Built-in driver Native device driver 전용 디바이스 드라이버 다른 드라이버의 구조에 맞춰서 구현하기가 힘들고 , 정해진 방식대로 ,

정해진 함수들을 구현해야 함 파이프 라인 (Pipeline)

Application 이 WINCE 에서 지원하는 API 를 통해서 device driver 에 접근 정적으로 GWES 에 링크되거나 DLL 로 동작한다 . 이 드라이버는 하드웨어에 완전히 종속적이어서 정해진 인터페이스를

제공하지 않는 경우가 많다 .

Embedded System Lab. II 8

WINCE device driver 의 종류

DrawTextBitBlt

CoreDLL.dll

GWES

DDI.DLLDisplay Driver

DISPLAY(LCD, CRT, …)

Application

DeviceDriver

H/W

OEM,3rd Party

Microsoft

OEM

Built-in driver 구조

Embedded System Lab. II 9

WINCE device driver 의 종류

Installable driver Stream device driver Application 과 device driver 가 데이터를 주고 받는 경우 H/W 를 제어하는 방식이 특정 API 를 통하는 방식

Stream 관련 API : CreateFile, ReadFile, WriteFile 등 User Mode DLL 파일 . 디바이스 매니저 (device.exe) 에 의해 로딩되어 동작한다 . 기본적으로 일관된 인터페이스를 가진다 .

Embedded System Lab. II 10

WINCE device driver 의 종류

Embedded System Lab. II 11

WINCE device driver 의 종류

Layered Driver 일반적인 윈도우 CE 디바이스 드라이버 상위 계층 (upper Layer : MDD)

Module Dependent Driver 각 드라이버들의 공통된 부분의 라이브러리나 소스 공통 모듈

하위 계층 (Lower Layer : PDD) 특정 하드웨어에 맞춰진 코드

Monolithic driver MDD 모듈이 제공되지 않거나 비교적 간단한 드라이버에 적용

Embedded System Lab. II 12

WINCE device driver 의 종류

Embedded System Lab. II 13

Stream device driver

Device 에 상관없이 일관된 인터페이스를 제공한다 .

논리적으로 데이터를 주고받는 device 에 적합하다 .

File system API 와 매치되어 진다 . CreateFile, ReadFile, WriteFile …

디바이스 드라이버 이름은 ‘ COM1’ 같은 형태로 만들어진다 . COM : prefix. 영어 3 문자 . device 종류 구분 1 : index. 한자리 숫자 . device 의 index 레지스트리에 저장되어 있는 값이어야 한다 . 사용시 , ‘COM1:’ 형태로 사용한다 . ‘:’ 를 항상 붙여야 한다 .

Embedded System Lab. II 14

Stream device driver

Embedded System Lab. II 15

드라이버 로드 순서

Device manager(device.exe) 가 시스템에 로드 된다 .

장치열거자 (regenum.dll) 을 이용하여 레지스트리 내 드라이버들을 조사한다 . [HKEY_LOCAL_MACHINE\Drivers\Builtin] 을 검사한다 .

드라이버들의 목록과 초기화할 순서를 만든다 .

레지스트리를 읽어 각각의 드라이버 (DLL 파일 ) 을 로드한다 .

각 드라이버의 Active 키를 생성하고 레지스트리에 저장한다 . [HKEY_LOCAL_MACHINE\Drivers\Active] 에 저장한다 .

xxx_Init 을 통해 드라이버를 초기화 시킨다 .

이후 CreateFile 을 통해 드라이버를 사용한다 .

Embedded System Lab. II

Device Driver Device Driver 제작방법제작방법

Embedded System Lab. II 17

Device driver 제작

기본적으로 필요한 파일 *.c – source file *.def – definition file makefile sources – target name, source files 등을 설정한다 .

Embedded System Lab. II

GPIO_LED device driverGPIO_LED device driver

Embedded System Lab. II 19

작업개요

GPIO 를 이용한 LED device driver 의 제작

PXA255PRO3 board 에 2 개의 led 가 있다 .

2 개의 led 는 GPIO82 와 83 에 연결되어 있다 .

LED 가 10 회 깜박거리는 application 을 만들어 2 개의 led 를 test 한다 .

Embedded System Lab. II 20

[\wince40\platform\PXA255PRO3\drivers\gpio_led]

필요한 모든 파일은 위 디렉토리에 저장한다 .

Embedded System Lab. II 21

gpio_led.c(1)// gpio_led.c#include <windows.h>#include <nkintr.h>#include <drv_glob.h>#include <oalintr.h>

#include "xsc1.h"#include "gpio.h"

#define GPIO_82 0x00040000#define GPIO_83 0x00080000

#define GPIO_LED1 0x01#define GPIO_LED2 0x02

#define LED_ON 1#define LED_OFF 0

Embedded System Lab. II 22

gpio_led.c(2)volatile GPIO_REGS *v_pGPIOReg;

BOOL WINAPIDllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved){

switch ( dwReason ){

case DLL_PROCESS_ATTACH:DEBUGMSG(1, (TEXT("GPIO_LED : DLL_PROCESS_ATTACH\r\n")));DisableThreadLibraryCalls((HMODULE) hInstDll);break;

}

return (TRUE);}

Embedded System Lab. II 23

gpio_led.c(3)//------------------------------------------------------------------------------// Returns context data for this Init instance//// Arguments:// dwContext - registry path for this device's active key////------------------------------------------------------------------------------DWORDLED_Init(DWORD dwContext){

DEBUGMSG(1, (TEXT("GPIO_LED : LED_Init\r\n")));

v_pGPIOReg = (GPIO_REGS *)VirtualAlloc(0, 0x80, MEM_RESERVE, PAGE_NOACCESS);if ( v_pGPIOReg == NULL )

{ ERRORMSG(1, (TEXT("LED_Init: GPIO VirtualAlloc failed!\r\n"))); goto error_return; }

Embedded System Lab. II 24

gpio_led.c(4)if ( !VirtualCopy((PVOID)v_pGPIOReg, (PVOID)GPIO_BASE_U_VIRTUAL, 0x80,

PAGE_READWRITE|PAGE_NOCACHE) ) { ERRORMSG(1, (TEXT("LED_Init: GPIO VirtualCopy failed!\r\n"))); goto error_return; }

DEBUGMSG (1, (TEXT("LED_Init - Success\r\n") ));

v_pGPIOReg->GPDR_z |= GPIO_82 | GPIO_83;v_pGPIOReg->GPSR_z |= GPIO_82 | GPIO_83;

return (TRUE);

error_return:

DEBUGMSG (1, (TEXT("LED_Init - Fail!!\r\n") ));

Embedded System Lab. II 25

gpio_led.c(5)if (v_pGPIOReg)

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

v_pGPIOReg = NULL;

return (FALSE);

} // LED_Init

//------------------------------------------------------------------------------//------------------------------------------------------------------------------BOOLLED_Close( DWORD Handle ){

return FALSE;} // LED_Close

Embedded System Lab. II 26

gpio_led.c(6)//------------------------------------------------------------------------------//// Device deinit - devices are expected to close down.// The device manager does not check the return code.////------------------------------------------------------------------------------BOOLLED_Deinit( DWORD dwContext // future: pointer to the per disk structure ){

return FALSE;} // LED_Deinit

Embedded System Lab. II 27

gpio_led.c(7)//------------------------------------------------------------------------------//// Returns handle value for the open instance.////------------------------------------------------------------------------------DWORDLED_Open( DWORD dwData, DWORD dwAccess, DWORD dwShareMode ){

DEBUGMSG(1, (TEXT("GPIO_LED : LED_Open\r\n")));

return (TRUE);} // LED_Open

Embedded System Lab. II 28

gpio_led.c(8)DWORD LED_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes){

WORD i;BYTE *pTmp;

pTmp = (BYTE *) pBuffer;

DEBUGMSG(1, (TEXT("GPIO_LED : LED_Write\r\n")));

for(i=0; i<dwNumBytes; i++)DEBUGMSG(1, (TEXT("Write Data[%d] = 0x%x \r\n"), i, pTmp[i] ));

if ( (pTmp[0] & GPIO_LED1) == LED_ON )v_pGPIOReg->GPCR_z |= GPIO_82;

elsev_pGPIOReg->GPSR_z |= GPIO_82;

Embedded System Lab. II 29

gpio_led.c(9)if ( ((pTmp[0] & GPIO_LED2)>>1) == LED_ON )

v_pGPIOReg->GPCR_z |= GPIO_83;else

v_pGPIOReg->GPSR_z |= GPIO_83;

return dwNumBytes;}

Embedded System Lab. II 30

gpio_led.c(10)//------------------------------------------------------------------------------//// I/O Control function - responds to info, read and write control codes.// The read and write take a scatter/gather list in pInBuf////------------------------------------------------------------------------------BOOLLED_IOControl( DWORD Handle, DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned ){

return FALSE;} // LED_IOControl

Embedded System Lab. II 31

gpio_led.c(11)//------------------------------------------------------------------------------//------------------------------------------------------------------------------DWORD LED_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes){return 0;}DWORD LED_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod){return 0;}void LED_PowerUp(void){}void LED_PowerDown(void){}

Embedded System Lab. II 32

gpio_led.defLIBRARY GPIO_LED

EXPORTS LED_InitLED_DeinitLED_OpenLED_CloseLED_ReadLED_WriteLED_SeekLED_IOControlLED_PowerDownLED_PowerUp

Embedded System Lab. II 33

makefile!if 0Copyright (c) Microsoft Corporation. All rights reserved.!endif!if 0Use of this source code is subject to the terms of the Microsoft end-userlicense agreement (EULA) under which you licensed this SOFTWARE PRODUCT.If you did not accept the terms of the EULA, you are not authorized to usethis source code. For a copy of the EULA, please see the LICENSE.RTF on yourinstall media.!endif## DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source# file to this component. This file merely indirects to the real make file# that is shared by all the components of Windows CE.#!INCLUDE $(_MAKEENVROOT)\makefile.def

Embedded System Lab. II 34

sources(1)!if 0Copyright (c) Microsoft Corporation. All rights reserved.!endif!if 0Use of this source code is subject to the terms of the Microsoft end-userlicense agreement (EULA) under which you licensed this SOFTWARE PRODUCT.If you did not accept the terms of the EULA, you are not authorized to usethis source code. For a copy of the EULA, please see the LICENSE.RTF on yourinstall media.!endif

TARGETNAME=gpio_ledRELEASETYPE=PLATFORMTARGETTYPE=DYNLINK

TARGETLIBS=$(_COMMONSDKROOT)\lib\$(_CPUINDPATH)\coredll.libSOURCELIBS=$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\drvlib.lib

Embedded System Lab. II 35

sources(2)DEFFILE=gpio_led.def

PREPROCESSDEFFILE=1

DLLENTRY=DllEntry

INCLUDES=..\..\inc

SOURCES=gpio_led.c

Embedded System Lab. II 36

Compile device driver

Platform builder 에서 [Build]->[Open build release directory] 를 선택한다 .

Embedded System Lab. II 37

현재 device driver 를 구현한 directory 로 이동한다 . [SET WINCEREL=1] 을 입력한다 .

위 환경변수를 설정하면 , 자동으로 release directory 에 복사된다 .

[build –cfs] 를 입력한다 .

Embedded System Lab. II 38

Build 가 에러없이 완료되었다 .

Embedded System Lab. II

GPIO LED Test Application GPIO LED Test Application 제작제작

Embedded System Lab. II 40

gpio_led test application

Platform builder 에서 [File]->[New Project or File…] 을 선택한다 .

Embedded System Lab. II 41

[WCE Application] 을 선택한다 . Project Name 에는 적절한 이름을 적은 후 , [OK] 를 선택한다 .

Embedded System Lab. II 42

[A simple Windows CE application] 을 선택한다 . [Finish] 를 선택한다 .

Embedded System Lab. II 43

위와 같이 새로운 project 가 생성된 것을 볼 수 있다 . [Source Files]->[gpio_led_test.cpp] 의 내용을 수정해야 한다 .

Embedded System Lab. II 44

gpio_led_test.cpp(1)// gpio_led_test.cpp : Defines the entry point for the application.//

#include "stdafx.h"

HANDLE g_hLed = INVALID_HANDLE_VALUE;

BOOL BlinkLED(){

BYTE i;BYTE bTmp;DWORD dwWrittenNum;BOOL bIsWritten;

if( g_hLed == INVALID_HANDLE_VALUE )return FALSE;

Embedded System Lab. II 45

gpio_led_test.cpp(2)for( i = 0; i < 4; ++i ){

bTmp = i;

// Write to GPIO_LEDbIsWritten = WriteFile( g_hLed, (LPCVOID)&bTmp, 1, &dwWrittenNum, NULL );

Sleep(100);}

return bIsWritten;}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){

Embedded System Lab. II 46

gpio_led_test.cpp(3)RETAILMSG( 1, (TEXT("gpio_led_test ------\r\n")) );

BYTE bTmp[10];int i;

// open GPIO_LED deviceg_hLed = CreateFile( L"LED1:",

(DWORD)GENERIC_READ | GENERIC_WRITE, 0,(LPSECURITY_ATTRIBUTES) NULL,(DWORD)OPEN_EXISTING, // OPEN_ALWAYS(DWORD)0, // FILE_FLAG_OVERLAPPE

D(HANDLE)NULL );

if( g_hLed == INVALID_HANDLE_VALUE ){

RETAILMSG( 1, (TEXT("CreateFile Error : 0x%x\r\n"), GetLastError() ) );return 0;

}

Embedded System Lab. II 47

gpio_led_test.cpp(4)else

RETAILMSG( 1, (TEXT("CreateFile Sucesss : HANDLE(0x%x)\r\n"), g_hLed ) );

bTmp[0] = 0x00;

// repeat 10 times.for( i = 0; i < 10; ++i ){

// Blink GPIO_LEDif( BlinkLED() == FALSE )

return -1;

Sleep(100);}

return 0;}

Embedded System Lab. II 48

Build gpio_led_test app

Platform builder 에서 [Build]->[Build gpio_led_test.exe] 를 선택한다 .

Embedded System Lab. II 49

에러없이 컴파일이 완료되었다 .

Embedded System Lab. II

Making OS ImageMaking OS Image

Embedded System Lab. II 51

Making OS image

GPIO_LED 를 build 한 다음 , 이 device driver 를 OS image 에 포함 시켜야 한다 .

OS image 에 포함시키기 위해 platform.bib, platform.reg 파일을 변경하여야 한다 .

Embedded System Lab. II 52

platform.reg, platform.bib

[wince40\platform\PXA255Pro3\files\] 밑에 있다 .

Platform.bib (gpio_sw_drvr.dll 아래에 삽입 )

Platform.reg(IF BSP_FPGABOARD 전에 삽입 )

gpio_sw_drvr.dll $(_FLATRELEASEDIR)\gpio_sw_drvr.dll NK SH

gpio_led.dll $(_FLATRELEASEDIR)\gpio_led.dll NK SH

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO_LED]

“Dll”=“gpio_led.dll”

“Prefix”=“LED”

“Index”=dword:1

“Order”=dword:0

IF BSP_FPGABOARD

Embedded System Lab. II 53

dirs

[WINCE420\PLATFORM\PXA255PRO3\DRIVERS] 에 있다 .

이 파일을 수정함으로써 자동으로 gpio_led.dll 을 생성할 수 있다 .

gpio_sw_drvr \gpio_led \ 추가

Embedded System Lab. II 54

이전 설정을 적용하기 위해 커널 이미지를 다시 빌드해야 한다 .

[Build]->[Rebuild platform] 을 선택한다 .

Embedded System Lab. II 55

OS Image 생성이 완료되었다 .

Embedded System Lab. II

BoardBoard 에 에 DownloadDownload 하기하기

Embedded System Lab. II 57

Board 에 download 하기

먼저 , OS Image 를 board 에 download 한다 .

과정은 이전과 동일하다 .

Embedded System Lab. II 58

Platform builder 가 debugging 모드로 바뀌었다 . [Target]->[Run Programs…] 을 선택한다 .

Embedded System Lab. II 59

Run programs 대화상자가 뜬다 . [gpio_led_test.exe] 파일을 선택하고 , [Run] 을 선택한다 .

Board 와 debugging 메시지를 보며 device driver 가 잘 동작하는지 확인한다 .

Embedded System Lab. II

KEYPAD Device Driver KEYPAD Device Driver 제작제작

Embedded System Lab. II 61

작업개요

GPIO 와 interrupt 를 이용한 key device driver 의 제작

PXA255-PRO board 에 12 개의 key button 이 있다 .

Key 를 눌렀을 때 , interrupt 를 걸어 그에 해당하는 service routine 이 실행되게 한다 .

debugging 창에 key 값을 출력한다 .

작업시 유의사항 Keypad 는 interrupt 를 이용해야 한다 . Interrupt 를 사용하기 위해서는 kernel 을 수정해야 한다 . Application 을 실행할 때 , blocking 방식을 사용하여야 한다 .

Embedded System Lab. II 62

Driver start Application Start

KPD_Init()

KPD_Open()

KPD_Read()

WaitForSingleObject()

Waiting key interrupt

Copy datapBufer = (key value)

InterruptDone()

CreateFile()

ReadFile()

Waiting...

Call KPD_Open()

Call KPD_Read()

ReadFile() blocking

ReadFile() waking

Embedded System Lab. II 63

WINCE 커널에서의 인터럽트 설정

Interrupt ID 등록 WINCE 커널에서는 interrupt 확인을 위해 interrupt ID 를 사용한다 . 최대 32 개 까지 interrupt ID 를 사용할 수 있다 .( 주요한 ID 는 미리 정의됨 ) 다음을 추가한다 .

<\WINCE420\PLATFORM\PXA255PRO3\INC\oalintr.h>

<\WINCE420\PLATFORM\PXA255PRO3\INC\oalintr.inc>

Embedded System Lab. II 64

Interrupt 초기화 및 Enable, Done, Disable 을 구현한다 . WINCE 에서 interrupt handling 은 ISR(interrupt service routine) 에서

이루어지지 않고 , IST(interrupt service thread) 에서 이루어진다 . 따라서 , 디바이스 드라이버에서 인터럽트 초기화가 요구된다 . [\wince420\platform\pxa255pro3\kernel\hal\cfwxsc1.c] 에 다음을 추가한다 .

OEMInterruptEnable() 함수

Embedded System Lab. II 65

OEMInterruptDisable() 함수

OEMInterruptDone() 함수

Embedded System Lab. II 66

Interrupt Service Routine 구현 WinCE 에서 ISR 은 Physical Interrupt number 을 Logical Interrupt(Interru

pt ID) 로 맵을 해준다 . ARM 의경우 Interrupt 를 여러 장치 들이 공유한다 . 따라서 interrupt 요구한 디바이스를 확인해야 한다 . WinCE 의 커널은 device 의 interrupt 요구 시 OEMInterruptHandler()

호출

kernelOEMInterruptHandler()

•Interrupt Pending Reigster 체크•Interrupt 발생지 확인•해당 interrupt ID 리턴

device driverISTdevice driver

ISTdevice driverISTdevice driver

IST

커널은 리턴된 interrupt ID에 따라 event 를 발생

eventInterrupt request

Embedded System Lab. II 67

[\wince420\platform\pxa255pro3\kernel\hal\arm\intxsc1.c] 에 다음을 추가한다 . OEMInterruptHandler() 함수

Embedded System Lab. II 68

[wince40\platform\PXA255PRO3\drivers\keypad\]

필요한 모든 파일은 위 디렉토리에 저장한다 .

드라이버 구동 절차 IST 생성 – CreateThread() 각 레지스터 address 설정 – Keypad_InitializeAddresses() Interrupt 활성화 – Keypad_EnableInterrupt() Interrupt 를 받을 event 생성 – CreateEvent() Interrupt 와 event 를 연결 – InterruptInitialize() ReadFile() 시 event 가 trigger 되면 값 전달 - KPD_Read()

Embedded System Lab. II 69

keypad_drvr.c(1)// keypad.c#include <windows.h>#include <nkintr.h>#include "XSC1.h"#include "XSC1bd.h"#include <drv_glob.h>#include <oalintr.h>#include "bcr.h"

extern PVOID VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress);

#define PRIVATE static#define PUBLIC

PRIVATE HANDLE gPwrButtonIntrEvent;PRIVATE HANDLE gPwrButtonIntrThread;

PRIVATE volatile GPIO_REGS *v_pGPIOReg = NULL;PRIVATE volatile INTC_REGS *v_pICReg = NULL;

Embedded System Lab. II 70

keypad_drvr.c(2)PRIVATE volatile unsigned char *v_pKeypad = NULL;

PRIVATE VOIDKeypad_EnableInterrupt(VOID){

v_pGPIOReg->GPDR_x &= ~GPIO_0;v_pGPIOReg->GEDR_x = GPIO_0;v_pGPIOReg->GRER_x |= GPIO_0;

INTC_GPIO0_INT_EN (v_pICReg->icmr);

RETAILMSG(1,(TEXT("::: Enable Interrupt of GPIO 0 --- ")));}

PRIVATE BOOLKeypad_IsPushed(VOID){

return ((v_pGPIOReg->GPLR_x & GPIO_0) ? TRUE : FALSE);}

Embedded System Lab. II 71

keypad_drvr.c(3)PRIVATE voidKeypadDeallocateVm(VOID){

if (v_pICReg) {

VirtualFree((void *)v_pICReg,0x400,MEM_RELEASE);v_pICReg = NULL;

}

if (v_pGPIOReg) {

VirtualFree((void *)v_pGPIOReg,0x400,MEM_RELEASE);v_pGPIOReg = NULL;

}

if (v_pKeypad) {

VirtualFree((void *)v_pKeypad,1,MEM_RELEASE);

Embedded System Lab. II 72

keypad_drvr.c(4)v_pKeypad = NULL;

}}

PRIVATE BOOLKeypad_InitializeAddresses(VOID){

BOOL RetValue = TRUE;

if (v_pICReg == NULL) {

v_pICReg = (volatile INTC_REGS *)VirtualAllocCopy(0x400,(char *)TEXT("KeypadEnable: INTC_BASE_U_VIR

TUAL"),(PVOID)INTC_BASE_U_VIRTUAL);

if (v_pICReg) {

if (v_pGPIOReg == NULL) {

Embedded System Lab. II 73

keypad_drvr.c(5)v_pGPIOReg = (volatile GPIO_REGS *)

VirtualAllocCopy(0x400,(char *)TEXT("KeypadEnable: GPIO_BASE_U_VIRTUAL"),

(PVOID)GPIO_BASE_U_VIRTUAL);}

}}

if (v_pKeypad == NULL) {

v_pKeypad = (volatile unsigned char *)VirtualAllocCopy(1,(char *)TEXT("KeypadEnable: IO_BASE_U_VIRTUAL"),(PVOID)IO_BASE_U_VIRTUAL);

}

if ( !v_pGPIOReg|| !v_pICReg || !v_pKeypad ){

KeypadDeallocateVm();DEBUGMSG(1,(TEXT("KeypadEnable(): Error %u\r\n"),GetLastError()));

Embedded System Lab. II 74

keypad_drvr.c(6)return (FALSE);

}

return(TRUE);

}

DWORDKeypad_IntrThread(PVOID pArg){

if (!Keypad_InitializeAddresses()){

RETAILMSG(1, (TEXT("::: Keypad_InitializeAddresses Fail\r\n")));return 0;

}

Keypad_EnableInterrupt();

Embedded System Lab. II 75

keypad_drvr.c(7)gPwrButtonIntrEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

if (!(InterruptInitialize(SYSINTR_KEYPAD, gPwrButtonIntrEvent, 0, 0))) {

RETAILMSG(1, (TEXT("::: SYSINTR_KEYPAD Init Fail\r\n")));}

RETAILMSG(1, (TEXT("::: Interrupt Initialize succeedd on SYSINTR_KEYPAD \r\n")));

while (1) {

// just loop not to exit the program.Sleep(100);

}

return 0; }

Embedded System Lab. II 76

keypad_drvr.c(8)PUBLIC DWORDKPD_Init(DWORD dwContext){

DWORD IDThread;gPwrButtonIntrThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) Keypad_IntrThread,

0, 0, &IDThread);

if ( gPwrButtonIntrThread == NULL ){

RETAILMSG(1, (TEXT("Fatal Error! Failed to create Keypad one Intterupt thread.\r\n")));

return (FALSE);} else {

RETAILMSG(1, (TEXT(" Keypad one Intterupt Init\r\n")));return TRUE;

}return 0;

}

Embedded System Lab. II 77

keypad_drvr.c(9)PUBLIC BOOL WINAPIDllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved){

switch ( dwReason ){case DLL_PROCESS_ATTACH:

DisableThreadLibraryCalls((HMODULE) hInstDll);break;

}

return (TRUE);}

BOOLKPD_Close( DWORD Handle ){

return TRUE;} // KPD_Close

Embedded System Lab. II 78

keypad_drvr.c(10)//// Device deinit - devices are expected to close down.// The device manager does not check the return code.//BOOLKPD_Deinit( DWORD dwContext ) // future: pointer to the per disk structure{

return TRUE;} // KPD_Deinit//// Returns handle value for the open instance.//DWORDKPD_Open( DWORD dwData, DWORD dwAccess, DWORD dwShareMode){

return TRUE;} // KPD_Open

Embedded System Lab. II 79

keypad_drvr.c(11)//// I/O Control function - responds to info, read and write control codes.// The read and write take a scatter/gather list in pInBuf//BOOLKPD_IOControl(DWORD Handle, DWORD dwIoControlCode, PBYTE pInBuf,

DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned )

{return FALSE;

} // KPD_IOControl

//-----------------------------------------------------------------------------// Read function.DWORD KPD_Read(DWORD Handle, LPVOID pBuffer, DWORD dwNumBytes){

if( dwNumBytes < 1 )return FALSE;

Embedded System Lab. II 80

keypad_drvr.c(12)WaitForSingleObject(gPwrButtonIntrEvent, INFINITE);

if (Keypad_IsPushed()) // To Filter Noise{

Sleep(100);

if (Keypad_IsPushed()){

((BYTE*)pBuffer)[0] = (*v_pKeypad)&0x0f;

RETAILMSG(1,(TEXT(" SYSINTR_KEYPAD !!! ")));}

}InterruptDone(SYSINTR_KEYPAD);

return TRUE;}

Embedded System Lab. II 81

keypad_drvr.c(13)DWORD KPD_Write(DWORD Handle, LPCVOID pBuffer, DWORD dwNumBytes){

return 0;}DWORD KPD_Seek(DWORD Handle, long lDistance, DWORD dwMoveMethod){

return 0;}

void KPD_PowerUp(void){

return;}

void KPD_PowerDown(void){

return;}

Embedded System Lab. II 82

Keypad_drvr.defLIBRARY KEYPAD_DRVR

EXPORTS KPD_InitKPD_DeinitKPD_OpenKPD_CloseKPD_ReadKPD_WriteKPD_SeekKPD_IOControlKPD_PowerDownKPD_PowerUp

Embedded System Lab. II 83

makefile!if 0Copyright (c) Microsoft Corporation. All rights reserved.!endif!if 0Use of this source code is subject to the terms of the Microsoft end-userlicense agreement (EULA) under which you licensed this SOFTWARE PRODUCT.If you did not accept the terms of the EULA, you are not authorized to usethis source code. For a copy of the EULA, please see the LICENSE.RTF on yourinstall media.!endif## DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source# file to this component. This file merely indirects to the real make file# that is shared by all the components of Windows CE.#!INCLUDE $(_MAKEENVROOT)\makefile.def

Embedded System Lab. II 84

sources(1)!if 0Copyright (c) Microsoft Corporation. All rights reserved.!endif!if 0Use of this source code is subject to the terms of the Microsoft end-userlicense agreement (EULA) under which you licensed this SOFTWARE PRODUCT.If you did not accept the terms of the EULA, you are not authorized to usethis source code. For a copy of the EULA, please see the LICENSE.RTF on yourinstall media.!endif

TARGETNAME=keypad_drvrRELEASETYPE=PLATFORMTARGETTYPE=DYNLINK

TARGETLIBS=$(_COMMONSDKROOT)\lib\$(_CPUINDPATH)\coredll.libSOURCELIBS=$(_TARGETPLATROOT)\lib\$(_CPUINDPATH)\drvlib.lib

Embedded System Lab. II 85

sources(2)DEFFILE=keypad_drvr.def

PREPROCESSDEFFILE=1

DLLENTRY=DllEntry

INCLUDES=..\..\inc

SOURCES=keypad_drvr.c

Embedded System Lab. II 86

Compile device driver

Platform builder 에서 [Build]->[Open build release directory] 를 선택한다 .

Embedded System Lab. II 87

현재 device driver 를 구현한 directory 로 이동한다 . [SET WINCEREL=1] 을 입력한다 .

위 환경변수를 설정하면 , 자동으로 release directory 에 복사된다 .

[build –cfs] 를 입력한다 .

Embedded System Lab. II 88

Build 가 에러없이 완료되었다 .

Embedded System Lab. II

KEYPAD Test ApplicationKEYPAD Test Application

Embedded System Lab. II 90

KEYPAD test application

Platform builder 에서 [File]->[New Project or File…] 을 선택한다 .

Embedded System Lab. II 91

[WCE Application] 을 선택한다 . Project Name 에는 적절한 이름을 적은 후 , [OK] 를 선택한다 .

Embedded System Lab. II 92

[A simple Windows CE application] 을 선택한다 . [Finish] 를 선택한다 .

Embedded System Lab. II 93

위와 같이 새로운 project 가 생성된 것을 볼 수 있다 . [Source Files]->[keypad_test.cpp] 의 내용을 수정해야 한다 .

Embedded System Lab. II 94

keypad_test.cpp(1)// keypad_test.cpp : Defines the entry point for the application.//

#include "stdafx.h"

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){ // TODO: Place code here.

HANDLE hKey = INVALID_HANDLE_VALUE;BOOL bIsRead;BYTE bBuf = 0x0;DWORD dwReadBytes;

Embedded System Lab. II 95

keypad_test.cpp(2)// open keypad devicehKey = CreateFile( L"KPD1:",

(DWORD)GENERIC_READ | GENERIC_WRITE, 0,(LPSECURITY_ATTRIBUTES) NULL,(DWORD)OPEN_EXISTING, // OP

EN_ALWAYS(DWORD)0,

// FILE_FLAG_OVERLAPPED(HANDLE)NULL );

if( hKey == INVALID_HANDLE_VALUE ){

RETAILMSG( 1, (TEXT("CreateFile Error : 0x%x\r\n"), GetLastError() ) );return 0;

}else

RETAILMSG( 1, (TEXT("CreateFile Sucesss : HANDLE(0x%x)\r\n"), hKey ) );

Embedded System Lab. II 96

keypad_test.cpp(3)while( bBuf != 0x4 ){

bIsRead = ReadFile( hKey, &bBuf, 1, &dwReadBytes, NULL );

RETAILMSG( 1, (TEXT("Key(0x%x) pressed!!\r\n"),bBuf) );}

return 0;}

Embedded System Lab. II 97

Build keypad_test app

Platform builder 에서 [Build]->[Build keypad_test.exe] 를 선택한다 .

Embedded System Lab. II 98

에러없이 컴파일이 완료되었다 .

Embedded System Lab. II

Making OS ImageMaking OS Image

Embedded System Lab. II 100

Making OS image

Keypad_drvr 를 build 한 다음 , 이 device driver 를 OS image 에 포함 시켜야 한다 .

OS image 에 포함시키기 위해 platform.bib, platform.reg 파일을 변경하여야 한다 .

Embedded System Lab. II 101

platform.reg, platform.bib

[Wince40\platform\PXA255PRO3\files\] 밑에 있다 . 아래의 내용들은 이전 GPIO_LED 에서 설정한 부분에 삽입한다 . Platform.bib

Platform.reg

keypad_drvr.dll $(_FLATRELEASEDIR)\keypad_drvr.dll NK SH

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\KEYPAD]

“Dll”=“keypad_drvr.dll”

“Prefix”=“KPD”

“Index”=dword:1

“Order”=dword:0

Embedded System Lab. II 102

dirs

[WINCE420\PLATFORM\PXA255PRO3\DRIVERS] 에 있다 .

이 파일을 수정함으로써 자동으로 gpio_led.dll 을 생성할 수 있다 .

gpio_sw_drvr \gpio_led \keypad \ 추가

Embedded System Lab. II 103

이전 설정을 적용하기 위해 커널 이미지를 다시 빌드해야 한다 .

[Build]->[Rebuild platform] 을 선택한다 .

Embedded System Lab. II 104

OS Image 생성이 완료되었다 .

Embedded System Lab. II

BoardBoard 에 에 DownloadDownload 하기하기

Embedded System Lab. II 106

Board 에 download 하기

먼저 , OS Image 를 board 에 download 한다 .

과정은 이전과 동일하다 .

Embedded System Lab. II 107

Platform builder 가 debugging 모드로 바뀌었다 . [Target]->[Run Programs…] 을 선택한다 .

Embedded System Lab. II 108

Run programs 대화상자가 뜬다 . [keypad_test.exe] 파일을 선택하고 , [Run] 을 선택한다 .

Board 와 debugging 메시지를 보며 device driver 가 잘 동작하는지 확인한다 .

Embedded System Lab. II

KEYPAD, GPIO_LEDKEYPAD, GPIO_LED 를 이용한 를 이용한 applicationapplication제작제작

Embedded System Lab. II 110

GPIO_LED, KEYPAD test app

Platform builder 에서 [File]->[New Project or File…] 을 선택한다 .

Embedded System Lab. II 111

[WCE Application] 을 선택한다 . Project Name 에는 적절한 이름을 적은 후 , [OK] 를 선택한다 .

Embedded System Lab. II 112

[A simple Windows CE application] 을 선택한다 . [Finish] 를 선택한다 .

Embedded System Lab. II 113

위와 같이 새로운 project 가 생성된 것을 볼 수 있다 . [Source Files]->[gpio_led_key.cpp] 의 내용을 수정해야 한다 .

Embedded System Lab. II 114

gpio_led_key.cpp(1)// gpio_led_key.cpp : Defines the entry point for the application.//

#include "stdafx.h"

HANDLE g_hLed = INVALID_HANDLE_VALUE;

BOOL BlinkLED(){

BYTE i;BYTE bTmp;DWORD dwWrittenNum;BOOL bIsWritten;

if( g_hLed == INVALID_HANDLE_VALUE )return FALSE;

Embedded System Lab. II 115

gpio_led_key.cpp(2)for( i = 0; i < 4; ++i ){

bTmp = i;

// write to GPIO_LEDbIsWritten = WriteFile( g_hLed, (LPCVOID)&bTmp, 1, &dwWrittenNum, NULL );

Sleep(100);}

return bIsWritten;}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){

Embedded System Lab. II 116

gpio_led_key.cpp(3) // TODO: Place code here.

HANDLE hKey = INVALID_HANDLE_VALUE;BOOL bIsRead;BYTE bBuf = 0x0;DWORD dwReadBytes;int i;

// open GPIO_LED deviceg_hLed = CreateFile( L"LED1:",

(DWORD)GENERIC_READ | GENERIC_WRITE, 0,(LPSECURITY_ATTRIBUTES) NULL,(DWORD)OPEN_EXISTING, // OPEN_ALWAYS(DWORD)0, // FILE_FLAG_OVERLAPPED(HANDLE)NULL );

if( g_hLed == INVALID_HANDLE_VALUE ){

RETAILMSG( 1, (TEXT("CreateFile(gpio_led) Error : 0x%x\r\n"), GetLastError() ) );return 0;

Embedded System Lab. II 117

gpio_led_key.cpp(4)}else RETAILMSG( 1, (TEXT("CreateFile(gpio_led) Sucesss : HANDLE(0x%x)\r\n"), g_hLed ) );

// open keypad devicehKey = CreateFile( L"KPD1:",

(DWORD)GENERIC_READ | GENERIC_WRITE, 0,(LPSECURITY_ATTRIBUTES) NULL,(DWORD)OPEN_EXISTING, // OPEN_ALWAYS(DWORD)0, // FILE_FLAG_OVERLAPPED(HANDLE)NULL );

if( hKey == INVALID_HANDLE_VALUE ){

RETAILMSG( 1, (TEXT("CreateFile(keypad) Error : 0x%x\r\n"), GetLastError() ) );return 0;

}else

RETAILMSG( 1, (TEXT("CreateFile(keypad) Sucesss : HANDLE(0x%x)\r\n"), hKey ) );

Embedded System Lab. II 118

gpio_led_key.cpp(5)// read keypad and repeat writing to GPIO_LEDwhile( bBuf != 0xB ){

bIsRead = ReadFile( hKey, &bBuf, 1, &dwReadBytes, NULL );

//RETAILMSG( 1, (TEXT("Key(0x%x) pressed!!\r\n"),bBuf) );for( i = bBuf; i >= 0; --i ){

RETAILMSG( 1, (TEXT("remaining count : %d\r\n"), i) );

if( BlinkLED() == FALSE )return -1;

}}return 0;

}

Embedded System Lab. II 119

Build gpio_led_key app

Platform builder 에서 [Build]->[Build gpio_led_key.exe] 를 선택한다 .

Embedded System Lab. II 120

에러없이 컴파일이 완료되었다 .

Embedded System Lab. II

BoardBoard 에 에 DownloadDownload 하기하기

Embedded System Lab. II 122

Board 에 download 하기

먼저 , OS Image 를 board 에 download 한다 .

과정은 이전과 동일하다 .

Embedded System Lab. II 123

Platform builder 가 debugging 모드로 바뀌었다 . [Target]->[Run Programs…] 을 선택한다 .

Embedded System Lab. II 124

Run programs 대화상자가 뜬다 . [gpio_led_key.exe] 파일을 선택하고 , [Run] 을 선택한다 .

Board 와 debugging 메시지를 보며 application 이 잘 동작하는지 확인한다 .

Embedded System Lab. II 125

Debug message 로 application 이 잘 동작하는 것을 확인할 수 있다 .

Recommended