440 likes | 784 Views
NDK / Java Native Interface. 자바 네이티브 인터페이스. NDK / Java Native Interface. ACHRO4210 의 디바이스 안드로이드에서 사용되는 대표적인 디바이스 LCD, Touch, Keypad, Wifi , Bluetooth, audio,… - 커널에서는 각 드라이버를 해당 플랫폼 드라이버로 등록 그외의 일반적이지 않은 디바이스 보통의 안드로이드 기기에서 사용하지 않는 장치
E N D
NDK / Java Native Interface 자바 네이티브 인터페이스
NDK / Java Native Interface • ACHRO4210의 디바이스 • 안드로이드에서 사용되는 대표적인 디바이스 LCD, Touch, Keypad, Wifi, Bluetooth, audio,… - 커널에서는 각 드라이버를 해당 플랫폼 드라이버로 등록 • 그외의 일반적이지 않은 디바이스 보통의 안드로이드 기기에서 사용하지 않는 장치 - 커널에 별도의 드라이버 모듈을 적재하고, App은 JNI를 이용 장치와 통신 … WiFi Keypad Bluetooth Touch LCD … Blood Checker MPU RFID GPS EPD
NDK / Java Native Interface • Java Native Interface • JNI 개요- Java는 순수 소프트웨어 툴- 하드웨어 의존적인 코드와 속도향상을 위해 Device를 제어할 필요가 있는경우 이용- C와 C++로 작성- 구글에서 제공하는 NDK(Native DK)툴을 이용 • 안드로이드플래폼 구조
NDK / Java Native Interface • JNI • JVM에서 돌아가는 Java 코드와 C/C++로 구현된 코드가 상호참조하기 위해 사용하는 programming framework • Platform-dependent한 라이브러리를 사용하고자 할 때, 혹은 기존의 프로그램을 Java에서 접근가능하도록 변경하고자 할 때 쓰임
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)+
NDK / Java Native Interface • 언제 Android NDK를 쓸 것인가? • 단지 C, C++을 더 쓰고 싶어서라면 쓰지말것.. • NDK 사용의 단점을 뛰어넘는 장점이 있을때만 사용할 것 • 응용 개발의 복잡성이 증가하며, • 디버깅이 어려움 • 그리고, C, C++을 사용한다고 해서 항상 성능이 빨라지는 것도 아님
NDK / Java Native Interface • NDK 설치- jni파일을 컴파일하여so파일로 컴파일 하는 툴과 예제를 포함한 개발 킷 • NDK 다운로드 • android-ndk-r9b-linux-x86.tar.bz2다운로드 fromhttp://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 jxvfandroid-ndk-r9b-linux-x86.tar.bz2 -C /work/mydroid • NDK 패스설정 # cd /root # vim .bashrc … … # NDK Path export PATH=/work/mydroid/android-ndk-r8b:$PATH
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.propertiesjnilibsobj res src tests # ls ./jni Android.mk hello-jni.c # ndk-build
NDK / Java Native Interface • JNI 테스트 • IDE툴을 이용하여 HelloJNI를 연다. • Project를 열때 기존에 존재하는 소스 디렉터리를 선택Create project form existing source Browse hello-jni디렉터리 • libhello-jni.so 파일 확인- IDE 패키지 트리에서컴파일한hello-jni.c가 정상적으로 컴파일 되었는지를 확인- 정상적으로 컴파일 되었다면 libs/armeabi/libhello-jni.so 파일이 생성되어있어야 함 • 실행- IDE에서 Run을 실행하여 프로그램을 실행한다. - 장치가 있으면 장치에서 실행하고, 없는 경우생성되어있는 가상 디바이스(AVD)에 실행된다. ndk에 있는 hello-jni프로젝트를 열어서 실제로 실행 시켜 본다. FILE NEW Other… Android Project 선택
NDK / Java Native Interface • Hello Jni소스 분석 • Hello-jni.java • hello-jni.c native 키워드를 붙여선언부만 작성함. 네이티브 라이브러리에 구현 부가 있음 public native String stringFromJNI(); public class HelloJni extends Activity { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); TextViewtv = 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’는생략한다. jstringJava_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobjectthiz ) { return (*env)->NewStringUTF(env, "Hello from JNI !"); } 패키지 클래스 함수 공통 파라메타 접두사 리턴 타입
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_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog include $(BUILD_SHARED_LIBRARY) 빌드시스템에서 제공하는 LOCAL_PATH를 제외하고 LOCAL_XXX를 Clear함(undefine) 모듈의 이름의 정의. 유일하고중간에 공백이 있어서는 안된다. Shardlibrary를 생성 LOCAL_XXX 변수에서 제공하는 정보를 수집하고 목록의 소스로 부터shared library를 빌드하는 방법을 결정 모듈로 빌드될C와 C++ 소스파일의 목록 추가적인 linker flag의 목록 • include $(BUILD_SHARED_LIBRARY) • lib$(LOCAL_MODULES).so • include $(BUILD_STATIC_LIBRARY) • lib$(LOCAL_MODULE).a
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파일로 생성
NDK / Java Native Interface • Linux 구조- 안드로이드의JNI는 드라이버를 처리 하거나 복잡한 메모리 연산부분에 대해서커널을 이용하는 방법이용한다.
NDK / Java Native Interface • Linux Device Driver- 커널을 통해 디바이스를 제어하기 위해 사용되는 소프트웨어- 커널은주번호와부번호를 통해 등록된 디바이스와 연결- 리눅스의 모든 하드웨어 장치들은 파일로 관리 (/dev) • 디바이스드라이버와 커널
NDK / Java Native Interface • 디바이스드라이버와 어플리케이션간의 통신
NDK / Java Native Interface • 커널 모듈 • 모듈은 리눅스 시스템이 부팅된 후 동적으로 load, unload 할 수 있는 커널의 구성 요소 • 시스템을 재부팅 하지 않고, 일부를 교체할 수 있다 • 리눅스를 구성하는 많은 모듈들은 의존성이 있을 수 있다. • 커널을 등록시킬 때에는 insmod명령을 이용하고 내릴 때는 rmmod명령을 이용한다.
NDK / Java Native Interface • LED 드라이버 • 회로 Exynos4210 CPU
NDK / Java Native Interface • LED 드라이버 • 회로 설명- CPU의 GPIO핀과 LED가 연결되어있음- LED에는 VDD를 통해 전원이 공급되고 있음- CPU의 핀이 LOW(0)가 되면 LED가 점등. • LED Driver Souce
NDK / Java Native Interface • LED Driver Souce
Internal Device Driver • Led Driver • File Operation struct • led_open() • led_release()
Internal Device Driver • led_write() • led_release()
Internal Device Driver • led_init()
Internal Device Driver • Test Application
NDK / Java Native Interface • LED Driver 컴파일 스크립트 (Makefile)
NDK / Java Native Interface • LED Driver 컴파일- 컴파일이 완료되면 led_driver.ko파일이 생성된다. • Led_driver.ko파일을 보드로 전송 • 안드로이드에서led를 제어할 수 있도록 장치 노드를 생성- adb를 이용하여 shell을 사용한다.
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 소스 코드
NDK / Java Native Interface • LedJNI Example • Project 생성
NDK / Java Native Interface • UI 작성 (main.xml) • <RadioButtonandroid:text="4" android:id="@+id/RB04" • android:layout_width="wrap_content" • android:layout_height="wrap_content"> • </RadioButton> • <RadioButtonandroid:text="5" android:id="@+id/RB05" • android:layout_width="wrap_content" • android:layout_height="wrap_content"> • </RadioButton> • <RadioButtonandroid:text="6" android:id="@+id/RB06" • android:layout_width="wrap_content • android:layout_height="wrap_content"> • </RadioButton> • <RadioButtonandroid:text="7" android:id="@+id/RB07" • android:layout_width="wrap_content" • android:layout_height="wrap_content"> • </RadioButton> • <RadioButtonandroid:text="8" • android:id="@+id/RB08" • android:layout_width="wrap_content" • android:layout_height="wrap_content"> • </RadioButton> • </RadioGroup> <?xml version="1.0" encoding="utf-8"?> <LinearLayoutxmlns:android= "http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello"/> <RadioGroupandroid:id="@+id/RadioGroup01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <RadioButtonandroid:text="1" android:id="@+id/RB01" android:layout_width="wrap_content" android:layout_height="wrap_content"></RadioButton> <RadioButtonandroid:text="2" android:id="@+id/RB02" android:layout_width="wrap_content" android:layout_height="wrap_content"> </RadioButton> <RadioButtonandroid:text="3" android:id="@+id/RB03" android:layout_width="wrap_content" android:layout_height="wrap_content"> </RadioButton>
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 { RadioGroupmRadioGroup; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mRadioGroup = (RadioGroup)findViewById(R.id.RadioGroup01); mRadioGroup.setOnCheckedChangeListener(this); } @Override public void onCheckedChanged(RadioGroup group, intcheckedId) { switch(checkedId) { case R.id.RB01 : ReceiveLedValue(0); // LED 1 break ; case R.id.RB02 : ReceiveLedValue(1); // LED 2 break ; case R.id.RB03 : • 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 ; • } • } • public native String RecieveLedValue(int x); • static { • System.loadLibrary("led-jni"); • } • }
NDK / Java Native Interface • JNI 컴파일 스크립트 및 JNI 코드 작성 (LedJniExampleActivity.java.xml) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := led-JNI LOCAL_SRC_FILES := led-JNI.c LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog include $(BUILD_SHARED_LIBRARY) #include <string.h> #include <jni.h> #include <android/log.h> #include <fcntl.h> void led_main (int x) { intfd = -1; 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, "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_achro4_huins_ex1_LedJniExampleActivity_ReceiveLedValue( JNIEnv* env,jobjectthiz, jintval ) { __android_log_print(ANDROID_LOG_INFO, "LedJniExample", "led value = %d", val); led_main(val); }
NDK / Java Native Interface • 작성된 JNI 소스 컴파일- 작성된 jni소스가 있는 디렉터리로 이동하여 컴파일 • 생성된 라이브러리 확인 • 경과확인
NDK / Java Native Interface • 프로그램 실행- 메뉴 > RUN > RUN 을 선택하여 Achro-4210에 전송하고 실행
Internal Device Control Application • 안드로이드와리눅스에서 디바이스를 제어하기 위한 전체 경로
NDK / Java Native Interface • 7-Segment Driver • LED 회로분석 LED 회로 구성 핀 연결 CPU I/O
NDK / Java Native Interface • 회로정리 • 7Segment(이하 FND)를 제어하기 위해서는 CPU의 GPIO를 이용하여 제어 • FND에 공급되는 전원은 ANODE • FND_A ~ FND_DP의 핀이 0(Low)이 되어야 FND의 각 요소가 점등 • FND Digit 선택 • 각 FND의구성 핀
NDK / Java Native Interface • FND 점등 위치 • 숫자테이블
Internal Device Driver • FND Driver • fnd_driver.c • 장치관련 선언부 및 사용할 레지스터 주소 설정 • File Operation Structure
NDK / Java Native Interface • fnd_open() • fnd_release()
NDK / Java Native Interface • fnd_write()
NDK / Java Native Interface • fnd_init(void)
NDK / Java Native Interface • 모듈 관련 등록 수행 함수 및 라이선스 지정
커널 타이머 • 타이머 인터럽트: 주기적으로 인터럽트를 발생시켜 반복해서 처리해야 할 작업에 사용 • 타이머 인터럽트는 HZ(아키텍처에 의존적인 값)로 설정 • 타이머 인터럽트가 발생하면 스케줄러에 의해 새로운 작업을 스케줄하고 jiffies(운영체제가 부팅된 시점부터 발생한 클록 회수) 값을 증가 • 커널 타이머를 사용해 특정 작업을 정해진 시간에 실행 • “jiffies ≧ timer->expires” 조건을 만족할 때 타이머에 등록한 함수를 실행 • expires는 jiffies와 타이머 간격을 합한 값