Transcript 9.0

NDK / Java Native Interface
자바 네이티브 인터페이스
-1-
NDK / Java Native Interface
 ACHRO4210의 디바이스

안드로이드에서 사용되는 대표적인 디바이스
LCD, Touch, Keypad, Wifi, Bluetooth, audio,…
- 커널에서는 각 드라이버를 해당 플랫폼 드라이버로 등록
LCD
Bluetooth
Keypad
Touch
WiFi
…

그외의 일반적이지 않은 디바이스
보통의 안드로이드 기기에서 사용하지 않는 장치
- 커널에 별도의 드라이버 모듈을 적재하고, App은 JNI를 이용 장치와 통신
GPS
EPD
MPU
RFID
-2-
Huins. R&D Center
Blood Checker
…
2
NDK / Java Native Interface
 Java Native Interface

JNI 개요
- Java는 순수 소프트웨어 툴
- 하드웨어 의존적인 코드와 속도향상을 위해 Device를 제어할 필요가 있는경우 이용
- C와 C++로 작성
- 구글에서 제공하는 NDK(Native DK)툴을 이용

안드로이드 플래폼 구조
-3-
Huins. R&D Center
3
NDK / Java Native Interface
 JNI
 JVM에서 돌아가는 Java 코드와 C/C++로 구현된 코드가 상호참조하

기 위해 사용하는 programming framework
Platform-dependent한 라이브러리를 사용하고자 할 때, 혹은 기존의
프로그램을 Java에서 접근가능하도록 변경하고자 할 때 쓰임
-4-
Huins. R&D Center
4
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-
Huins. R&D Center
5
NDK / Java Native Interface
 언제 Android NDK를 쓸 것인가?
 단지 C, C++을 더 쓰고 싶어서라면 쓰지말것..
 NDK 사용의 단점을 뛰어넘는 장점이 있을때만 사용할 것



응용 개발의 복잡성이 증가하며,
디버깅이 어려움
그리고, C, C++을 사용한다고 해서 항상 성능이 빨라지는 것도 아님
-6-
Huins. R&D Center
6
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-r8-linux-x86.tar.tar
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-
Huins. R&D Center
7
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.xml default.properties jni libs obj res src tests
# ls ./jni
Android.mk hello-jni.c
# ndk-build
-8-
Huins. R&D Center
8
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-
Huins. R&D Center
9
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 -
클래스
Huins. R&D Center
함수
공통 파라메타
10
NDK / Java Native Interface
 Android.mk
- GNU Makefile의 일부
- Static library와 Shared library를 생성
- Static library는 Shared library를 생성하기 위해 사용
LOCAL_PATH 는 현재 파일의 경로를 주기 위해 사용
‘my-dir’은 현재 디렉터리 경로를 반환
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
빌드 시스템에서 제공하는 LOCAL_PATH를 제외하고
LOCAL_XXX를 Clear함(undefine)
LOCAL_MODULE
:= hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_LDLIBS
:= -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
Shard library를 생성
LOCAL_XXX 변수에서 제공하는 정보를 수집하고
목록의 소스로 부터 shared library를 빌드하는
방법을 결정
모듈의 이름의 정의. 유일하고 중간에 공백이
있어서는 안된다.
모듈로 빌드될 C와 C++ 소스파일의 목록
추가적인 linker flag의 목록
include $(BUILD_SHARED_LIBRARY)
lib$(LOCAL_MODULES).so
include $(BUILD_STATIC_LIBRARY)
lib$(LOCAL_MODULE).a
- 11 -
Huins. R&D Center
11
NDK / Java Native Interface
 Shared library의 명명 규칙
1. ‘lib’prefix<name>’.so’suffix의 형식
2. <name>이 ‘hello-jni’라면, 최종 파일은 ‘libhello-jni.so’
 생성된 라이브러리 위치
Shared library는 프로젝트의 적절한 경로에 복사되고, 최종 ‘.apk’파일에 포함
최종 파일은 project\libs\armeabi 의 경로에 libhello-jni.so파일로 생성
- 12 -
Huins. R&D Center
12
NDK / Java Native Interface

Linux 구조
- 안드로이드의 JNI는 드라이버를 처리 하거나 복잡한 메모리 연산부분에 대해서
커널을 이용하는 방법이용한다.
- 13 -
Huins. R&D Center
13
NDK / Java Native Interface

Linux Device Driver
- 커널을 통해 디바이스를 제어하기 위해 사용되는 소프트웨어
- 커널은 주번호와 부번호를 통해 등록된 디바이스와 연결
- 리눅스의 모든 하드웨어 장치들은 파일로 관리 (/dev)
 디바이스 드라이버와 커널
- 14 -
Huins. R&D Center
14
NDK / Java Native Interface
 디바이스 드라이버와 어플리케이션간의 통신
- 15 -
Huins. R&D Center
15
NDK / Java Native Interface
 커널 모듈




모듈은 리눅스 시스템이 부팅된 후 동적으로 load, unload 할 수 있는 커널의 구성 요소
시스템을 재부팅 하지 않고, 일부를 교체할 수 있다
리눅스를 구성하는 많은 모듈들은 의존성이 있을 수 있다.
커널을 등록시킬 때에는 insmod 명령을 이용하고 내릴 때는 rmmod 명령을 이용한다.
/* This program is modue example
AUTH : Huins, Inc
MENT : Test Only */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
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 -
Huins. R&D Center
16
NDK / Java Native Interface
 LED 드라이버

회로
Exynos4210 CPU
- 17 -
Huins. R&D Center
17
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 -
Huins. R&D Center
18
NDK / Java Native Interface

LED Driver Souce
if(result <0) {
printk(KERN_WARNING"Can't get any major!\n");
return result;
}
led_data = ioremap(LED_GPBDAT, 0x01);
if(led_data==NULL) {
printk("ioremap failed!\n");
return -1;
}
led_ctrl = ioremap(LED_GPBCON, 0x04);
if(led_ctrl==NULL) {
printk("ioremap failed!\n");
return -1;
} else {
get_ctrl_io=inl((unsigned int)led_ctrl);
get_ctrl_io|=(0x11110000);
outl(get_ctrl_io,(unsigned int)led_ctrl);
}
outb(0xF0, (unsigned int)led_data);
return 0;
}
static int led_usage = 0;
static unsigned char *led_data;
static unsigned int *led_ctrl;
static struct file_operations led_fops = {
.open = led_open,
.write = led_write,
.release = led_release,
};
int led_open(struct inode *minode, struct file *mfile) {
if(led_usage != 0)
return -EBUSY;
led_usage = 1;
return 0;
}
int led_release(struct inode *minode, struct file *mfile) {
led_usage = 0;
return 0;
}
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;
outb (led_buff, (unsigned int)led_data);
return length;
}
void __exit led_exit(void) {
outb(0xF0, (unsigned int)led_data);
iounmap(led_data);
iounmap(led_ctrl);
unregister_chrdev(LED_MAJOR, LED_NAME);
}
int __init led_init(void) {
int result;
unsigned int get_ctrl_io=0;
result = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("Huins HSH");
- 19 -
Huins. R&D Center
19
Internal Device Driver

Led Driver
 File Operation struct
static struct file_operations led_fops =
.open
.write
.release
{
= led_open,
= led_write,
= 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 -
Huins. R&D Center
20
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 -
Huins. R&D Center
21
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 -
Huins. R&D Center
22
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 -
Huins. R&D Center
23
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 -
Huins. R&D Center
24
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 -
Huins. R&D Center
25
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 -
Huins. R&D Center
26
NDK / Java Native Interface

LedJNI Example
 Project 생성
- 27 -
Huins. R&D Center
27
NDK / Java Native Interface
 UI 작성 (main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<RadioButton android:text="4" android:id="@+id/RB04"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</RadioButton>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"/>
<RadioButton android:text="5" android:id="@+id/RB05"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</RadioButton>
<RadioGroup android:id="@+id/RadioGroup01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton android:text="6" android:id="@+id/RB06"
android:layout_width="wrap_content
android:layout_height="wrap_content">
</RadioButton>
<RadioButton android:text="1" android:id="@+id/RB01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></RadioButton>
<RadioButton android:text="7" android:id="@+id/RB07"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</RadioButton>
<RadioButton android:text="2" android:id="@+id/RB02"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</RadioButton>
<RadioButton android:text="3" android:id="@+id/RB03"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</RadioButton>
<RadioButton android:text="8"
android:id="@+id/RB08"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</RadioButton>
</RadioGroup>
- 28 -
Huins. R&D Center
28
NDK / Java Native Interface
 제어 소스 (LedJniExampleActivity.java.xml)
package achro4.huins.ex1;
import android.app.Activity;
import android.os.Bundle;
import android.widget.RadioGroup;
public class LedJniExampleActivity extends Activity
implements RadioGroup.OnCheckedChangeListener {
RadioGroup mRadioGroup;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ReceiveLedValue(2); // LED 3
break ;
case R.id.RB04 :
ReceiveLedValue(3); // LED 4
break ;
case R.id.RB05 :
ReceiveLedValue(4); // ALL ON
break ;
case R.id.RB06 :
ReceiveLedValue(5); // ALL OFF
break ;
}
}
mRadioGroup =
(RadioGroup)findViewById(R.id.RadioGroup01);
mRadioGroup.setOnCheckedChangeListener(this);
public native String RecieveLedValue(int x);
}
@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 :
static {
System.loadLibrary("led-jni");
}
}
- 29 -
Huins. R&D Center
29
NDK / Java Native Interface
 JNI 컴파일 스크립트 및 JNI 코드 작성 (LedJniExampleActivity.java.xml)
LOCAL_PATH := $(call my-dir)
#include <string.h>
#include <jni.h>
#include <android/log.h>
#include <fcntl.h>
include $(CLEAR_VARS)
LOCAL_MODULE := led-JNI
LOCAL_SRC_FILES := led-JNI.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
void led_main (int x) {
int fd = -1;
unsigned char val[ ] = {0x70, 0xB0, 0xD0, 0xE0, 0x00, 0xF0};
include $(BUILD_SHARED_LIBRARY)
fd = open("/dev/led_driver", O_RDWR);
if (fd < 0) {
__android_log_print(ANDROID_LOG_INFO,
"Device Open Error", "Driver = %d", x);
} else {
__android_log_print(ANDROID_LOG_INFO,
"Device Open Success", "Driver = %d", x);
write (fd, &val[x], sizeof(unsigned char));
}
close(fd);
jstring Java_com_huins_ledJNI_LedJNI_RecieveLedValue( JNIEnv* env,jobject thiz, jint val)
<1>
<2>
<3>
<4>
<5>
<6>
<7>
<1> jstring : 리턴 타입으로서 자바 언어의 String에 해당한다.
ex) jbyte -> byte, jshort -> short, jint -> int, void -> void, jobject -> 자바객체 등
<2> Java : 접두사
<3> com_huins_ledJNI : 패키지명
<4> LedJNI : 클래스명
<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 -
Huins. R&D Center
30
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 -
Huins. R&D Center
31
NDK / Java Native Interface
 프로그램 실행
- 메뉴 > RUN > RUN 을 선택하여 Achro-4210에 전송하고 실행
# ndk-build
- 32 -
Huins. R&D Center
32
Internal Device Control Application

안드로이드와 리눅스에서 디바이스를 제어하기 위한 전체 경로
- 33 -
Huins. R&D Center
NDK / Java Native Interface
 7-Segment Driver

LED 회로 분석
LED 회로 구성
핀 연결
CPU I/O
- 34 -
Huins. R&D Center
34
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
연번
순서
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
 각 FND의 구성 핀
- 35 -
Huins. R&D Center
35
NDK / Java Native Interface

FND 점등 위치

숫자테이블
FND 숫자
레지스터 값
점등 위치
계산값
A
B
C
D
E
F
G
P
0
ABCDEF
0
0
0
0
0
0
1
1
0x02
1
BC
1
0
0
1
1
1
1
1
0x9F
2
ABDGE
0
0
1
0
0
1
0
1
0x25
3
ABCDG
0
0
0
0
1
1
0
1
0x0D
4
BCFG
1
0
0
1
1
0
0
1
0x99
5
ACDFG
0
1
0
0
1
0
0
1
0x49
6
CDEFG
1
1
0
0
0
0
0
1
0xC1
7
ABC
0
0
0
1
1
1
1
1
0x1F
8
ABCDEFG
0
0
0
0
0
0
0
1
0x01
9
ABCDFG
0
0
0
0
1
0
0
1
0x09
P
1
1
1
1
1
1
1
0
0xFE
1
1
1
1
1
1
1
1
0xFF
DP
BLANK
- 36 -
Huins. R&D Center
36
Internal Device Driver

FND Driver
 fnd_driver.c

장치관련 선언부 및 사용할 레지스터 주소 설정
// … 생략) …
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/version.h>
#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
.open
.write
.release
};
file_operations fnd_fops = {
= fnd_open,
= fnd_write,
= fnd_release,
- 37 -
Huins. R&D Center
37
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 -
Huins. R&D Center
38
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 -
Huins. R&D Center
39
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 -
Huins. R&D Center
40
NDK / Java Native Interface

모듈 관련 등록 수행 함수 및 라이선스 지정
module_init(fnd_init);
module_exit(fnd_exit);
MODULE_LICENSE ("GPL");
MODULE_AUTHOR ("Huins HSH");
- 41 -
Huins. R&D Center
41
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 -
Huins. R&D Center
42
커널 타이머
 타이머 인터럽트: 주기적으로 인터럽트를 발생시켜 반복해서 처리해야




할 작업에 사용
타이머 인터럽트는 HZ(아키텍처에 의존적인 값)로 설정
타이머 인터럽트가 발생하면 스케줄러에 의해 새로운 작업을 스케줄하
고 jiffies(운영체제가 부팅된 시점부터 발생한 클록 회수) 값을 증가
커널 타이머를 사용해 특정 작업을 정해진 시간에 실행
“jiffies ≧ timer->expires” 조건을 만족할 때 타이머에 등록한 함수를 실
행
 expires는 jiffies와 타이머 간격을 합한 값
- 43 -
 커널 타이머의 사용법
- 44 -