NDK / Java Native Interface 자바 네이티브 인터페이스

- 1 - NDK / Java Native Interface

. ACHRO4210의 디바이스 . 안드로이드에서 사용되는 대표적인 디바이스 LCD, Touch, Keypad, Wifi, Bluetooth, audio,… - 커널에서는 각 드라이버를 해당 플랫폼 드라이버로 등록

LCD Bluetooth Touch Keypad WiFi

. 그외의 일반적이지 않은 디바이스 보통의 안드로이드 기기에서 사용하지 않는 장치 - 커널에 별도의 드라이버 모듈을 적재하고, App은 JNI를 이용 장치와 통신

GPS EPD MPU RFID Blood Checker …

- 2 - 2 Huins. R&D Center NDK / Java Native Interface

. Java Native Interface . JNI 개요 - Java는 순수 소프트웨어 툴 - 하드웨어 의존적인 코드와 속도향상을 위해 Device를 제어할 필요가 있는경우 이용 - C와 ++로 작성 - 구글에서 제공하는 NDK(Native DK)툴을 이용

. 안드로이드 플래폼 구조

- 3 - 3 Huins. R&D Center NDK / Java Native Interface

. JNI . JVM에서 돌아가는 Java 코드와 C/C++로 구현된 코드가 상호참조하 기 위해 사용하는 programming framework . Platform-dependent한 라이브러리를 사용하고자 할 때, 혹은 기존의 프로그램을 Java에서 접근가능하도록 변경하고자 할 때 쓰임

- 4 - 4 Huins. R&D Center NDK / Java Native Interface

. Android NDK . A toolset that lets you embed in your apps native source code . C, C++(recently supported December 2010) and assembly(?) . It is supported on android cupcake(1.5)+

- 5 - 5 Huins. R&D Center NDK / Java Native Interface

. 언제 Android NDK를 쓸 것인가? . 단지 C, C++을 더 쓰고 싶어서라면 쓰지말것.. . NDK 사용의 단점을 뛰어넘는 장점이 있을때만 사용할 것 . 응용 개발의 복잡성이 증가하며, . 디버깅이 어려움 . 그리고, C, C++을 사용한다고 해서 항상 성능이 빨라지는 것도 아님

- 6 - 6 Huins. R&D Center NDK / Java Native Interface

. NDK 설치 - jni 파일을 컴파일하여 so파일로 컴파일 하는 툴과 예제를 포함한 개발 킷

. NDK 다운로드 . android-ndk-r9b-linux-x86.tar.bz2 다운로드 from http://developer.android.com/tools/sdk/ndk/index.html or http://web.donga.ac.kr/jwjo or [CD]/android_tools/linux/ndk_linux_x86_x64/android-ndk-r7-linux-x86.tar.bz . NDK 복사 및 설치 # tar jxvf android-ndk-r9b-linux-x86.tar.bz2 -C /work/mydroid

. NDK 패스 설정 # cd /root # vim .bashrc … … # NDK Path export PATH=/work/mydroid/android-ndk-r8b:$PATH

- 7 - 7 Huins. R&D Center NDK / Java Native Interface

. JNI 테스트 - JNI 가 정상 설치되었는지 테스트

. Hello JNI 디렉터리로 이동

# cd /work/mydroid/android-ndk-r9b/samples/hello-jni

. 패키지에 포함된 경로

# cd /work/mydroid/android-ndk-r9b/samples/hello-jni # ls AndroidManifest. default.properties jni libs obj res src tests # ls ./jni Android.mk hello-jni.c # ndk-build

- 8 - 8 Huins. R&D Center NDK / Java Native Interface

. JNI 테스트 . IDE툴을 이용하여 HelloJNI를 연다. ndk에 있는 hello-jni프로젝트를 열어서 실제로 실행 시켜 본다. FILE  NEW  Other… Android Project 선택

. Project를 열때 기존에 존재하는 소스 디렉터리를 선택 Create project form existing source  Browse  hello-jni 디렉터리

. libhello-jni.so 파일 확인 - IDE 패키지 트리에서 컴파일한 hello-jni.c 가 정상적으로 컴파일 되었는지를 확인 - 정상적으로 컴파일 되었다면 libs/armeabi/libhello-jni.so 파일이 생성되어있어야 함

. 실행 - IDE에서 Run을 실행하여 프로그램을 실행한다. - 장치가 있으면 장치에서 실행하고, 없는 경우 생성되어있는 가상 디바이스(AVD)에 실행된다.

- 9 - 9 Huins. R&D Center NDK / Java Native Interface

. Hello Jni 소스 분석 . Hello-jni.java native 키워드를 붙여 선언부만 작성함. public native String stringFromJNI(); 네이티브 라이브러리에 구현 부가 있음 public class HelloJni extends Activity { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); TextView tv = new TextView(this); tv.setText( stringFromJNI() ); setContentView(tv); 네이티브 라이브러리 함수도 보통의 자바 메소드와 같은 방식으로 사용한다. } public native String stringFromJNI(); public native String unimplementedStringFromJNI(); static { System.loadLibrary("hello-jni"); 클래스가 로딩될 때 호출됨. } hello-jni라는 이름의 네이티브 라이브러리를 로딩. ‘lib’와 ‘.so’는 생략한다. }

. hello-jni.c jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) {

return (*env)->NewStringUTF(env, "Hello from JNI !"); }

접두사 패키지 클래스 함수 공통 파라메타 리턴 타입 - 10 - 10 Huins. R&D Center

NDK / Java Native Interface

. Android.mk - GNU Makefile의 일부 - Static library와 Shared library를 생성 - Static library는 Shared library를 생성하기 위해 사용 LOCAL_PATH := $(call my-dir) LOCAL_PATH 는 현재 파일의 경로를 주기 위해 사용 ‘my-dir’은 현재 디렉터리 경로를 반환 include $(CLEAR_VARS) 빌드 시스템에서 제공하는 LOCAL_PATH를 제외하고 LOCAL_MODULE := hello-jni LOCAL_XXX를 Clear함(undefine) LOCAL_SRC_FILES := hello-jni.c LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog

include $(BUILD_SHARED_LIBRARY) 모듈의 이름의 정의. 유일하고 중간에 공백이 있어서는 안된다.

Shard library를 생성 LOCAL_XXX 변수에서 제공하는 정보를 수집하고 모듈로 빌드될 C와 C++ 소스파일의 목록 목록의 소스로 부터 shared library를 빌드하는 방법을 결정 추가적인 linker flag의 목록

include $(BUILD_SHARED_LIBRARY) lib$(LOCAL_MODULES).so include $(BUILD_STATIC_LIBRARY) lib$(LOCAL_MODULE).a

- 11 - 11 Huins. R&D Center NDK / Java Native Interface

. Shared library의 명명 규칙 1. ‘lib’prefix’.so’suffix의 형식 2. 이 ‘hello-jni’라면, 최종 파일은 ‘libhello-jni.so’

. 생성된 라이브러리 위치 Shared library는 프로젝트의 적절한 경로에 복사되고, 최종 ‘.apk’파일에 포함 최종 파일은 project\libs\armeabi 의 경로에 libhello-jni.so파일로 생성

- 12 - 12 Huins. R&D Center

NDK / Java Native Interface

. Linux 구조 - 안드로이드의 JNI는 드라이버를 처리 하거나 복잡한 메모리 연산부분에 대해서 커널을 이용하는 방법이용한다.

- 13 - 13 Huins. R&D Center NDK / Java Native Interface

. Linux Device Driver - 커널을 통해 디바이스를 제어하기 위해 사용되는 소프트웨어 - 커널은 주번호와 부번호를 통해 등록된 디바이스와 연결 - 리눅스의 모든 하드웨어 장치들은 파일로 관리 (/dev) . 디바이스 드라이버와 커널

- 14 - 14 Huins. R&D Center NDK / Java Native Interface

. 디바이스 드라이버와 어플리케이션간의 통신

- 15 - 15 Huins. R&D Center NDK / Java Native Interface

. 커널 모듈 . 모듈은 리눅스 시스템이 부팅된 후 동적으로 load, unload 할 수 있는 커널의 구성 요소 . 시스템을 재부팅 하지 않고, 일부를 교체할 수 있다 . 리눅스를 구성하는 많은 모듈들은 의존성이 있을 수 있다. . 커널을 등록시킬 때에는 insmod 명령을 이용하고 내릴 때는 rmmod 명령을 이용한다.

/* This program is modue example AUTH : Huins, Inc MENT : Test Only */

#include #include #include

MODULE_LICENSE("GPL"); MODULE_AUTHOR("Huins");

static int module_begin(void) { printk(KERN_ALERT "Hello module, Achro 4210!!\n"); return 0; }

static void module_end(void) { printk(KERN_ALERT "Goodbye module, Achro 4210!!\n"); }

module_init(module_begin); module_exit(module_end);

- 16 - 16 Huins. R&D Center NDK / Java Native Interface

. LED 드라이버 . 회로

Exynos4210 CPU

- 17 - 17 Huins. R&D Center NDK / Java Native Interface

. LED 드라이버 . 회로 설명 - CPU의 GPIO핀과 LED가 연결되어있음 - LED에는 VDD를 통해 전원이 공급되고 있음 - CPU의 핀이 LOW(0)가 되면 LED가 점등. 연번 순서 PIN NAME CPU/IO 1 LED 0 SPI_1.MOSI GPB7 2 LED 1 SPI_1.MISO GPB6

3 LED 2 SPI_1.NSS GPB5

4 LED 3 SPI_1.CLK GPB4

. LED Driver Souce /* LED Ioremap Control FILE : led_driver.c */

// 헤더 선언부 #define LED_MAJOR 240 // 디바이스 드라이버의 주번호 #define LED_MINOR 0 // 디바이스 드라이버의 부번호 #define LED_NAME "led_driver" // 디바이스 드라이버의 이름 #define LED_GPBCON 0x11400040 // GPBCON 레지스터의 물리주소 #define LED_GPBDAT 0x11400044 // GPBDAT 레지스터의 물리주소

int led_open(struct inode *, struct file *); int led_release(struct inode *, struct file *); ssize_t led_write(struct file *, const char *, size_t, loff_t *);

- 18 - 18 Huins. R&D Center NDK / Java Native Interface

. LED Driver Souce

static int led_usage = 0; if(result <0) { static unsigned char *led_data; printk(KERN_WARNING"Can't get any major!\n"); static unsigned int *led_ctrl; return result; static struct file_operations led_fops = { } .open = led_open, led_data = ioremap(LED_GPBDAT, 0x01); .write = led_write, if(led_data==NULL) { .release = led_release, printk("ioremap failed!\n"); }; return -1; } int led_open(struct inode *minode, struct file *mfile) { led_ctrl = ioremap(LED_GPBCON, 0x04); if(led_usage != 0) if(led_ctrl==NULL) { return -EBUSY; printk("ioremap failed!\n"); led_usage = 1; return -1; return 0; } else { } get_ctrl_io=inl((unsigned int)led_ctrl); get_ctrl_io|=(0x11110000); int led_release(struct inode *minode, struct file *mfile) { outl(get_ctrl_io,(unsigned int)led_ctrl); led_usage = 0; } return 0; outb(0xF0, (unsigned int)led_data); } return 0; } ssize_t led_write(struct file *inode, const char *, size_t length, loff_t *off_what) { void __exit led_exit(void) { const char *tmp = gdata; outb(0xF0, (unsigned int)led_data); unsigned short led_buff=0; iounmap(led_data); outb (led_buff, (unsigned int)led_data); iounmap(led_ctrl); return length; unregister_chrdev(LED_MAJOR, LED_NAME); } }

int __init led_init(void) { module_init(led_init); int result; module_exit(led_exit); unsigned int get_ctrl_io=0; MODULE_LICENSE ("GPL"); result = register_chrdev(LED_MAJOR, LED_NAME, &led_fops); MODULE_AUTHOR ("Huins HSH");

- 19 - 19 Huins. R&D Center Internal Device Driver

. Led Driver . File Operation struct

static struct file_operations led_fops = { .open = led_open, .write = led_write, .release = led_release, } ;

. led_open()

int led_open(struct inode *minode, struct file *mfile) { if(led_usage != 0) return -EBUSY; led_usage = 1; return 0; }

. led_release()

int led_release(struct inode *minode, struct file *mfile) { led_usage = 0; return 0; }

- 20 - 20 Huins. R&D Center Internal Device Driver

. led_write()

ssize_t led_write(struct file *inode, const char *gdata, size_t length, loff_t *off_what) { const char *tmp = gdata;

unsigned short led_buff=0;

if (copy_from_user(&led_buff, tmp, length)) return -EFAULT;

outb (led_buff, (unsigned int)led_data);

return length; }

. led_release()

void __exit led_exit(void) { outb(0xF0, (unsigned int)led_data); iounmap(led_data); iounmap(led_ctrl); unregister_chrdev(LED_MAJOR, LED_NAME); printk("Removed LED module\n"); }

- 21 - 21 Huins. R&D Center Internal Device Driver

. led_init()

int __init led_init(void) { int result; unsigned int get_ctrl_io=0;

result = register_chrdev(LED_MAJOR, LED_NAME, &led_fops); if(result <0) { printk(KERN_WARNING"Can't get any major!\n"); return result; }

led_data = ioremap(LED_GPBDAT, 0x01); if(led_data==NULL) [ // 오류 처리 }

led_ctrl = ioremap(LED_GPBCON, 0x04); if(led_ctrl==NULL) { // 오류 처리 } else { get_ctrl_io=inl((unsigned int)led_ctrl); get_ctrl_io|=(0x11110000); outl(get_ctrl_io,(unsigned int)led_ctrl); }

printk("init module, /dev/led_driver major : %d\n", LED_MAJOR); outb(0xF0, (unsigned int)led_data);

return 0; }

- 22 - 22 Huins. R&D Center Internal Device Driver

. Test Application

/* … (생략) …

int main(int argc, char **argv) {

unsigned char val[] = {0x70, 0xB0, 0xD0, 0xE0, 0x00, 0xF0}; if(argc != 2) { // 실행 어규먼트를 받았는지 체크 및 오류처리 }

led_fd = open("/dev/led_device", O_RDWR); // 디바이스를 오픈. if (led_fd<0) { // 만약 디바이스가 정상적으로 오픈되지 않으면 오류 처리후 종료 }

get_number=atoi(argv[1]); // 받은 인자를 숫자로 바꾼다. if(get_number>0||get_number<9) // 숫자가 0~9 까지에 포함되는지 확인. write(led_fd,&val[get_number],sizeof(unsigned char)); else printf("Invalid Value : 0 thru 9"); // 포함되지 않으면, 메시지를 출력. close(led_fd); // 장치를 닫아줌. return 0; // 프로그램을 종료. }

- 23 - 23 Huins. R&D Center NDK / Java Native Interface

. LED Driver 컴파일 스크립트 (Makefile)

# vim Makefile

# This is simple Makefile obj-m := led_driver.o # led_driver.c를 컴파일하여 led_driver.ko파일을 만든다. CC := arm-linux-gcc # 어플리케이션 컴파일 시 사용할 컴파일러

KDIR := /work/achro4210/kernel # 커널 소스가 풀려있는 디렉터리

PWD := $(shell pwd) # 현재 디렉터리 환경 변수를 가져옴 FILE := test_led # 응용 프로그램 파일이름

all: driver # make만 입력했을 때 실행되는 전체 부분

driver : # make driver를 입력했을 때 실행되는 부분 $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

install : # make install을 입력했을 때 실행되는 부분 cp -a led_driver.ko /nfsroot

clean: # make clean을 입력했을 때 실행되는 부분 rm -rf *.ko rm -rf *.mod.* rm -rf *.o rm -rf $(FILE) rm -rf modules.order rm -rf Module.symvers

- 24 - 24 Huins. R&D Center NDK / Java Native Interface

. LED Driver 컴파일 - 컴파일이 완료되면 led_driver.ko 파일이 생성된다. # make

. Led_driver.ko 파일을 보드로 전송

# adb push led_driver.ko /

. 안드로이드에서 led를 제어할 수 있도록 장치 노드를 생성 - adb를 이용하여 shell을 사용한다.

명령창 명령창을 연다 # adb shell <-- PC (Target Board ) # mknod /dev/gpio c 246 0 <-- Target Board 명령창

# insmod /led_driver.ko <--- Target Board 명령창

# exit <--- Target Board 명령창(Target Board의 명령창을 빠져나간다.)

- 25 - 25 Huins. R&D Center NDK / Java Native Interface

. LED JNI . 개발 순서 . android application 소스코드 작성 (Java) . android.mk 작성 (JNI) . jni 소스코드 작성 : led_jni.c (JNI) . jni 파일을 패키지에 포함 (패키지에서 새파일을 만들어 위의 파일을 작성해도 됨) . 터미널에서 해당 jni 파일이 있는 위치로 이동하여 ndk-build 실행 -> libled-jni.so 생성 . 안드로이드 소스에서 소스를 갱신 (F5키를 눌러도 됨) -> 안드로이드 프로젝트에서 라이브러리 경로와 파일이 표시됨 . RUN을 실행하여 컴파일 하여 보드에서 실행

. 소스 디렉터리 구조 . bin – 컴파일 된 애플리케이션 코드 . libs – 애플리케이션에서 사용하는 외부 라이브러리 파일이 위치 . src – 애플리케이션을 구성하는 자바 소스 코드 . res – 아이콘이나 GUI 레이아웃 등 컴파일 된 자바 코드와 함께 애플리케이션 패키지에 포함될 각종 파일 . assets – 장비에 애플리케이션을 설치할 때 함께 설치할 그 밖의 데이터 파일 . jni – 네이티브 라이브러리를 구성하는 C 소스 코드

- 26 - 26 Huins. R&D Center NDK / Java Native Interface

. LedJNI Example . Project 생성

- 27 - 27 Huins. R&D Center NDK / Java Native Interface

. UI 작성 (main.xml)

android:layout_width="fill_parent" android:layout_height="fill_parent" > android:text="@string/hello"/>

android:orientation="horizontal">

android:layout_height="wrap_content"> android:id="@+id/RB08" android:layout_width="wrap_content" android:layout_height="wrap_content"> android:layout_width="wrap_content" android:layout_height="wrap_content">

- 28 - 28 Huins. R&D Center NDK / Java Native Interface

. 제어 소스 (LedJniExampleActivity.java.xml)

package achro4.huins.ex1; ReceiveLedValue(2); // LED 3 import android.app.Activity; break ; import android.os.Bundle; case R.id.RB04 : import android.widget.RadioGroup; ReceiveLedValue(3); // LED 4 break ; public class LedJniExampleActivity extends Activity case R.id.RB05 : implements RadioGroup.OnCheckedChangeListener { ReceiveLedValue(4); // ALL ON RadioGroup mRadioGroup; break ; @Override case R.id.RB06 : public void onCreate(Bundle savedInstanceState) { ReceiveLedValue(5); // ALL OFF super.onCreate(savedInstanceState); break ; setContentView(R.layout.main); } } mRadioGroup = (RadioGroup)findViewById(R.id.RadioGroup01); public native String RecieveLedValue(int x); mRadioGroup.setOnCheckedChangeListener(this); } static { System.loadLibrary("led-jni"); @Override } public void onCheckedChanged(RadioGroup group, int checkedId) { } switch(checkedId) { case R.id.RB01 : ReceiveLedValue(0); // LED 1 break ; case R.id.RB02 : ReceiveLedValue(1); // LED 2 break ; case R.id.RB03 :

- 29 - 29 Huins. R&D Center NDK / Java Native Interface

. JNI 컴파일 스크립트 및 JNI 코드 작성 (LedJniExampleActivity.java.xml)

LOCAL_PATH := $(call my-dir) #include include $(CLEAR_VARS) #include #include LOCAL_MODULE := led-JNI #include LOCAL_SRC_FILES := led-JNI.c LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog void led_main (int x) { int fd = -1; include $(BUILD_SHARED_LIBRARY) unsigned char val[ ] = {0x70, 0xB0, 0xD0, 0xE0, 0x00, 0xF0};

fd = open("/dev/led_driver", O_RDWR); if (fd < 0) { __android_log_print(ANDROID_LOG_INFO, jstring Java_com_huins_ledJNI_LedJNI_RecieveLedValue( JNIEnv* env,jobject thiz, jint val) "Device Open Error", "Driver = %d", x); <1> <2> <3> <4> <5> <6> <7> } else { <1> jstring : 리턴 타입으로서 자바 언어의 String에 해당한다. __android_log_print(ANDROID_LOG_INFO, ex) jbyte -> byte, jshort -> short, jint -> int, void -> void, jobject -> 자바객체 등 "Device Open Success", "Driver = %d", x); <2> Java : 접두사 write (fd, &val[x], sizeof(unsigned char)); <3> com_huins_ledJNI : 패키지명 } <4> LedJNI : 클래스명 close(fd); <5> RecieveLedValue : 함수명 } <6> JNIEnv *, Jobject thiz : 공통 파라메타 <7> jint val : 함수에 전달할 파라메타 jstring Java_achro4_huins_ex1_LedJniExampleActivity_Receive LedValue( JNIEnv* env,jobject thiz, jint val ) { __android_log_print(ANDROID_LOG_INFO, "LedJniExample", "led value = %d", val); led_main(val); }

- 30 - 30 Huins. R&D Center NDK / Java Native Interface

. 작성된 JNI 소스 컴파일 - 작성된 jni 소스가 있는 디렉터리로 이동하여 컴파일 # ndk-build

. 생성된 라이브러리 확인 # ls ../libs/armeabi

. 경과 확인 # adb shell # insmod led_driver.ko # mknod /dev/led_driver c 240 0

- 31 - 31 Huins. R&D Center NDK / Java Native Interface

. 프로그램 실행 - 메뉴 > RUN > RUN 을 선택하여 Achro-4210에 전송하고 실행 # ndk-build

- 32 - 32 Huins. R&D Center Internal Device Control Application

. 안드로이드와 리눅스에서 디바이스를 제어하기 위한 전체 경로

- 33 - Huins. R&D Center NDK / Java Native Interface

. 7-Segment Driver . LED 회로 분석

LED 회로 구성 핀 연결

CPU I/O

- 34 - 34 Huins. R&D Center NDK / Java Native Interface

. 회로 정리 . 7Segment(이하 FND)를 제어하기 위해서는 CPU의 GPIO를 이용하여 제어 . FND에 공급되는 전원은 ANODE . FND_A ~ FND_DP의 핀이 0(Low)이 되어야 FND의 각 요소가 점등 . FND Digit 선택

연번 순서 PIN NAME CPU/IO 계산값

1 FND1 LCD_B_VD15 GPE3_1 0x02 2 FND2 LCD_B_VD16 GPE3_2 0x04

3 FND3 LCD_B_VD18 GPE3_4 0x10

4 FND4 LCD_B_VD21 GPE3_7 0x80

. 각 FND의 구성 핀

연번 순서 PIN NAME CPU/IO

1 FND A GPS_GPIO_7 GPL2_7

2 FND B GPS_GPIO_6 GPL2_6 3 FND C GPS_GPIO_5 GPL2_5

4 FND D GPS_GPIO_4 GPL2_4

5 FND E GPS_GPIO_3 GPL2_3

6 FND F GPS_GPIO_2 GPL2_2

7 FND G GPS_GPIO_1 GPL2_1

8 FND DP GPS_GPIO_0 GPL2_0

- 35 - 35 Huins. R&D Center NDK / Java Native Interface

. FND 점등 위치

. 숫자테이블

레지스터 값 FND 숫자 점등 위치 계산값 A B C D E F G P 0 A B C D E F 0 0 0 0 0 0 1 1 0x02 1 B C 1 0 0 1 1 1 1 1 0x9F

2 A B D G E 0 0 1 0 0 1 0 1 0x25

3 A B C D G 0 0 0 0 1 1 0 1 0x0D

4 B C F G 1 0 0 1 1 0 0 1 0x99

5 A C D F G 0 1 0 0 1 0 0 1 0x49

6 C D E F G 1 1 0 0 0 0 0 1 0xC1

7 A B C 0 0 0 1 1 1 1 1 0x1F

8 A B C D E F G 0 0 0 0 0 0 0 1 0x01

9 A B C D F G 0 0 0 0 1 0 0 1 0x09

DP P 1 1 1 1 1 1 1 0 0xFE

BLANK 1 1 1 1 1 1 1 1 0xFF

- 36 - 36 Huins. R&D Center Internal Device Driver

. FND Driver . fnd_driver.c . 장치관련 선언부 및 사용할 레지스터 주소 설정

// … 생략) … #include #include #include #include

#define FND_MAJOR 241 // fnd device minor number #define FND_MINOR 0 // fnd device minor number #define FND_NAME "fnd_device" // fnd device name

#define FND_GPL2CON 0x11000100 // Pin Configuration #define FND_GPL2DAT 0x11000104 // Pin Data

. File Operation Structure

static struct file_operations fnd_fops = { .open = fnd_open, .write = fnd_write, .release = fnd_release, };

- 37 - 37 Huins. R&D Center NDK / Java Native Interface

. fnd_open()

int fnd_open(struct inode *minode, struct file *mfile) { if(fnd_usage != 0) return -EBUSY; fnd_usage = 1; return 0; }

. fnd_release()

int fnd_release(struct inode *minode, struct file *mfile) { fnd_usage = 0; return 0; }

- 38 - 38 Huins. R&D Center NDK / Java Native Interface

. fnd_write()

ssize_t fnd_write(struct file *inode, const short *gdata, size_t length, loff_t *off_what) { // ... 생략 if (copy_from_user(&fnd_buff, tmp, length)) return -EFAULT;

printk("DATA : %d\n",fnd_buff); outw (fnd_buff, (unsigned int)fnd_data); return length; }

- 39 - 39 Huins. R&D Center NDK / Java Native Interface

. fnd_init(void)

int __init fnd_init(void) { int result;

result = register_chrdev(FND_MAJOR, FND_NAME, &fnd_fops); if(result <0) { // ...(오류처리)... }

fnd_data = ioremap(FND_GPL2DAT, 0x01); if(fnd_data==NULL) { // ...(오류처리)... }

fnd_ctrl = ioremap(FND_GPL2CON, 0x04); fnd_ctrl2 = ioremap(FND_GPE3CON, 0x04); if(fnd_ctrl==NULL) { // ...(오류처리)... } else { outl(0x11111111,(unsigned int)fnd_ctrl); outl(0x10010110,(unsigned int)fnd_ctrl2); }

printk("init module, /dev/fnd_driver major : %d\n", FND_MAJOR); outb(0xFF, (unsigned int)fnd_data);

return 0; }

- 40 - 40 Huins. R&D Center NDK / Java Native Interface

. 모듈 관련 등록 수행 함수 및 라이선스 지정

module_init (fnd_init); module_exit (fnd_exit);

MODULE_LICENSE ("GPL"); MODULE_AUTHOR ("Huins HSH");

- 41 - 41 Huins. R&D Center NDK / Java Native Interface

// … 생략 … #define FND0 0x00 #define FND1 0x01 // … 생략 … #define FND8 0x08 #define FND9 0x09 #define FNDP 0x0A // DP #define FNDA 0x0B // ALL #define FNDX 0x0C // ALL OFF

int main(int argc, char **argv) { int fnd_fd; // …생략… if(argc != 3) { // 장치를 열수 없을 때 오류처리 }

fnd_fd = open("/dev/fnd_device", O_WRONLY); if (fnd_fd<0) { // 장치를 열수 없는 경우 } get_fndnumber=(char)atoi(argv[1]); switch(get_fndnumber) { case 0 : set_fndvalue = 0x96; break; // … 생략 … case 4 : set_fndvalue = 0x80; break; }

- 42 - 42 Huins. R&D Center 커널 타이머

. 타이머 인터럽트: 주기적으로 인터럽트를 발생시켜 반복해서 처리해야 할 작업에 사용 . 타이머 인터럽트는 HZ(아키텍처에 의존적인 값)로 설정 . 타이머 인터럽트가 발생하면 스케줄러에 의해 새로운 작업을 스케줄하 고 jiffies(운영체제가 부팅된 시점부터 발생한 클록 회수) 값을 증가 . 커널 타이머를 사용해 특정 작업을 정해진 시간에 실행 . “jiffies ≧ timer->expires” 조건을 만족할 때 타이머에 등록한 함수를 실행 . expires는 jiffies와 타이머 간격을 합한 값

- 43 - . 커널 타이머의 사용법

- 44 -