2012 내장형 시스템 설계
Full Color LED 디바이스 구성 Full Color LED 디바이스 드라이버 Full Color LED JNI 라이브러리 작성 Full Color LED 안드로이드 App 구현 JNI 라이브러리 빌드 결과 화면 2
3 ◦ FPGA 내부의 컨트롤러에 의해 제어됨
4 ◦ 9bit 로 구성된 12 개의 레지스터 Full Color LED1 Red0x0500_00A08-0 : LED PWM Data 0x000 ~ 0x100 Full Color LED1 Green0x0500_00A28-0 : LED PWM Data Full Color LED1 Blue0x0500_00A48-0 : LED PWM Data Full Color LED2 Red0x0500_00A68-0 : LED PWM Data Full Color LED2 Green0x0500_00A88-0 : LED PWM Data Full Color LED2 Blue0x0500_00AA8-0 : LED PWM Data Full Color LED3 Red0x0500_00B08-0 : LED PWM Data Full Color LED3 Green0x0500_00B28-0 : LED PWM Data Full Color LED3 Blue0x0500_00B48-0 : LED PWM Data Full Color LED4 Red0x0500_00B68-0 : LED PWM Data Full Color LED4 Green0x0500_00B88-0 : LED PWM Data Full Color LED4 Blue0x0500_00BA8-0 : LED PWM Data
5 ◦ 드라이버 코드 위치 “~/linux s4210/drivers/hanback“ 디렉토리에 포 함되어있음 ◦ 드라이버 소스 코드 (fullcolorled.c) #include
6 ◦ 드라이버 소스 코드 (fullcolorled.c) #define DRIVER_AUTHOR"hanback" #define DRIVER_DESC"full color led test program" #define FULLCOLORLED_NAME "fullcolorled" #define FULLCOLORLED_MODULE_VERSION"FULL COLOR LED V0.1" #define FULLCOLORLED_ADDRESS 0x #define FULLCOLORLED_ADDRESS_RANGE 0x1000 #define FULL_LED19 #define FULL_LED28 #define FULL_LED37 #define FULL_LED46 #define ALL_LED5 static int fullled_usage = 0; static int led_num=0; static unsigned long *fullled_ioremap; static unsigned short *full_led_addr[4][3];
7 ◦ 드라이버 소스 코드 (fullcolorled.c) int fullled_open(struct inode *minode, struct file *mfile) { if(fullled_usage != 0) return -EBUSY; fullled_ioremap=ioremap(FULLCOLORLED_ADDRESS,FULLCOLORLED_ADDRESS_RANGE); if(!check_mem_region((unsigned long)fullled_ioremap, FULLCOLORLED_ADDRESS_RANGE)) { request_mem_region((unsigned long)fullled_ioremap, FULLCOLORLED_ADDRESS_RANGE, FULLCOLORLED_NAME); } elseprintk("driver: unable to register this!\n"); full_led_addr[0][0] =(unsigned short *)((unsigned long)fullled_ioremap+0xa0); full_led_addr[0][1] =(unsigned short *)((unsigned long)fullled_ioremap+0xa2); full_led_addr[0][2] =(unsigned short *)((unsigned long)fullled_ioremap+0xa4); full_led_addr[1][0] =(unsigned short *)((unsigned long)fullled_ioremap+0xa6); full_led_addr[1][1] =(unsigned short *)((unsigned long)fullled_ioremap+0xa8); full_led_addr[1][2] =(unsigned short *)((unsigned long)fullled_ioremap+0xaa); full_led_addr[2][0] =(unsigned short *)((unsigned long)fullled_ioremap+0xb0); full_led_addr[2][1] =(unsigned short *)((unsigned long)fullled_ioremap+0xb2); full_led_addr[2][2] =(unsigned short *)((unsigned long)fullled_ioremap+0xb4); full_led_addr[3][0] =(unsigned short *)((unsigned long)fullled_ioremap+0xb6); full_led_addr[3][1] =(unsigned short *)((unsigned long)fullled_ioremap+0xb8); full_led_addr[3][2] =(unsigned short *)((unsigned long)fullled_ioremap+0xba); fullled_usage = 1; return 0; }
8 ◦ 드라이버 소스 코드 (fullcolorled.c) int fullled_release(struct inode *minode, struct file *mfile) { iounmap(fullled_ioremap); release_mem_region((unsigned long)fullled_ioremap, FULLCOLORLED_ADDRESS_RANGE); fullled_usage = 0; return 0; } static int fullled_ioctl(struct file *file, unsigned int cmd,unsigned long arg) { switch(cmd) { case FULL_LED1:led_num = 0;break; case FULL_LED2:led_num = 1;break; case FULL_LED3:led_num = 2;break; case FULL_LED4:led_num = 3;break; case ALL_LED:led_num = 4;break; } return 0; }
9 ◦ 드라이버 소스 코드 (fullcolorled.c) ssize_t fullled_write(struct file *inode, const char *gdata, size_t length, loff_t *off_what) { int ret,i=0,j=0; unsigned char buf[3]; ret = copy_from_user(buf,gdata,length); for(j=0;j<3;j++) { if(buf[j]%0x10 >= 0xA)buf[j]+=0x06; if(buf[j]%0x100 >= 0xA0)buf[j]+=0x60; } if(led_num != 4) { for(j=0;j<3;j++) { *full_led_addr[led_num][j] = buf[j]; } else { for(i=0;i<4;i++) { for(j=0;j<3;j++) { *full_led_addr[i][j] = buf[j]; } return length; }
10 ◦ 드라이버 소스 코드 (fullcolorled.c) struct file_operations fullled_fops = {.owner= THIS_MODULE,.write= fullled_write,.open= fullled_open,.release= fullled_release,.unlocked_ioctl= fullled_ioctl, }; static struct miscdevice fullled_driver = {.fops= &fullled_fops,.name= FULLCOLORLED_NAME,.minor= MISC_DYNAMIC_MINOR, }; int fullled_init(void) { printk("driver: %s DRIVER INIT\n",FULLCOLORLED_NAME); return misc_register(&fullled_driver); } void fullled_exit(void) { misc_deregister(&fullled_driver); printk("driver: %s DRIVER EXIT\n",FULLCOLORLED_NAME); } module_init(fullled_init); module_exit(fullled_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("Dual BSD/GPL");
11 ◦ Full Color LED 드라이버를 안드로이드 앱에서 사용하기 위해서는 JNI 인 터페이스 라이브러리가 필요 ◦ 이 라이브러리는 구글의 NDK 를 이용하여 빌드
12 ◦ JNI 프로그램 소스 fullcolorled.c #include jint Java_package_fullLed_FullLedActivity_FLEDControl(JNIEnv* env, jobject thiz, jint led_num, jint val1, jint val2, jint val3) { int fd,ret; char buf[3]; fd = open("/dev/fullcolorled",O_WRONLY); if (fd < 0) { return -errno; } ret = (int)led_num; switch(ret) { case FULL_LED1: ioctl(fd,FULL_LED1); break; case FULL_LED2: ioctl(fd,FULL_LED2); break; case FULL_LED3: ioctl(fd,FULL_LED3); break; case FULL_LED4: ioctl(fd,FULL_LED4); break; case ALL_LED: ioctl(fd,ALL_LED); break; } buf[0] = val1; buf[1] = val2; buf[2] = val3; write(fd,buf,3); close(fd); return ret; } jint : 함수의 리턴 타입 package_fullLed : 안드로이드 앱의 package 이름 FullLedActivity : 안드로이드 앱의 Activity 이름 FLEDControl : 안드로이드 앱에서 사용할 함수 이름 #define FULL_LED19 #define FULL_LED28 #define FULL_LED37 #define FULL_LED46 #define ALL_LED5
13 ◦ 안드로이드용 Makefile 인 Android.mk 작성하기 Android.mk (1) 컴파일의 결과물로서 생성되는 라이브러리 이름이며, NDK 에서는 이 이름 앞에 lib 가 추가되고, 뒤에.so 가 붙어 libfullcolorled.so 라는 파일이 만들어짐 (2) 컴파일 할 소스 파일의 이름 (3) Shared Library 용으로 빌드한다는 표시로서 확장자.so 가 붙음 (1) (2) (3) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= fullcolorled LOCAL_SRC_FILES:= fullcolorled.c include $(BUILD_SHARED_LIBRARY)
Application name ◦ FullLed Project Name ◦ FullLed Package name ◦ {name}. fullLed Activity name ◦ FullLedActivity Layout name ◦ main 14
<manifest xmlns:android=" package="moriya.fullLed" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <application > <activity android:name=".FullLedActivity" android:screenOrientation="landscape" > AndroidManifest.xml 15
<LinearLayout xmlns:android=" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dip" > <RadioGroup android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <RadioButton android:layout_margin="3px" android:checked="true" android:gravity="right|center_vertical" android:text="LED1" /> <RadioButton android:layout_margin="3px" android:checked="false" android:gravity="right|center_vertical" android:text="LED2" /> main.xml (1) 16 <RadioButton android:layout_margin="3px" android:checked="false" android:gravity="right|center_vertical" android:text="LED3" /> <RadioButton android:layout_margin="3px" android:checked="false" android:gravity="right|center_vertical" android:text="LED4" /> <RadioButton android:layout_margin="3px" android:checked="false" android:gravity="right|center_vertical" android:text="All" />
<RadioGroup android:layout_width="wrap_content" android:layout_height="wrap_content" android:baselineAligned="true" android:orientation="horizontal" > <RadioButton android:layout_margin="5px" android:checked="false" android:gravity="center|center_vertical" android:text="Red" /> <RadioButton android:layout_margin="5px" android:checked="false" android:gravity="right|center_vertical" android:text="Blue" /> main.xml (2) 17 <RadioButton android:layout_margin="5px" android:checked="false" android:gravity="right|center_vertical" android:text="Green" /> <RadioButton android:layout_margin="5px" android:checked="false" android:gravity="right|center_vertical" android:text="Random" /> <RadioButton android:layout_margin="5px" android:checked="true" android:gravity="right|center_vertical" android:text="Off" />
<SeekBar android:layout_width="400dip" android:layout_height="wrap_content" android:layout_marginTop="10px" android:max="100" /> <SeekBar android:layout_width="400dip" android:layout_height="wrap_content" android:layout_marginTop="10px" android:max="100" /> <SeekBar android:layout_width="400dip" android:layout_height="wrap_content" android:layout_marginTop="10px" android:max="100" /> main.xml (3) 18
#ff0000 #0000ff # #ffff00 # #ff #e # #f00 #0000ff #f0f0 #ffffff00 # #ffffffff color.xml : ‘res/values’ 에 추가 19
package moriya.fullLed; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.View; import android.widget.RadioButton; import android.widget.SeekBar; public class FullLedActivity extends Activity { static { System.loadLibrary("fullcolorled"); } public native int FLEDControl(int led_num, int val1, int val2, int val3); static SeekBar[] sb; static int temp; int[] public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); led_val = new int[4]; led_val[0] = 9; for (int i = 1; i < 4; i++) { led_val[i] = 0; } FullLedActivity.java (1) 20
findViewById(R.id.fcl_ledbut1).setOnClickListener(mLedButtonListener); findViewById(R.id.fcl_ledbut2).setOnClickListener(mLedButtonListener); findViewById(R.id.fcl_ledbut3).setOnClickListener(mLedButtonListener); findViewById(R.id.fcl_ledbut4).setOnClickListener(mLedButtonListener); findViewById(R.id.fcl_ledbut5).setOnClickListener(mLedButtonListener); findViewById(R.id.fcl_red).setOnClickListener(mColorButtonListener); findViewById(R.id.fcl_green).setOnClickListener(mColorButtonListener); findViewById(R.id.fcl_blue).setOnClickListener(mColorButtonListener); findViewById(R.id.fcl_random).setOnClickListener(mColorButtonListener); findViewById(R.id.fcl_off).setOnClickListener(mColorButtonListener); // sb = new SeekBar[3]; sb[0] = (SeekBar) findViewById(R.id.fcl_seekBar_red); sb[1] = (SeekBar) findViewById(R.id.fcl_seekBar_green); sb[2] = (SeekBar) findViewById(R.id.fcl_seekBar_blue); sb[0].setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { public void onStopTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub temp = arg0.getProgress(); led_val[1] = temp; FLEDControl(led_val[0], led_val[1], led_val[2], led_val[3]); } public void onStartTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub temp = arg0.getProgress(); } FullLedActivity.java (2) 21
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { // TODO Auto-generated method stub temp = arg0.getProgress(); led_val[1] = temp; FLEDControl(led_val[0], led_val[1], led_val[2], led_val[3]); } }); sb[1].setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { public void onStopTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub temp = arg0.getProgress(); led_val[2] = temp; FLEDControl(led_val[0], led_val[1], led_val[2], led_val[3]); } public void onStartTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub temp = arg0.getProgress(); } public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { // TODO Auto-generated method stub temp = arg0.getProgress(); led_val[2] = temp; FLEDControl(led_val[0], led_val[1], led_val[2], led_val[3]); } }); FullLedActivity.java (3) 22
sb[2].setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { public void onStopTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub temp = arg0.getProgress(); led_val[3] = temp; FLEDControl(led_val[0], led_val[1], led_val[2], led_val[3]); } public void onStartTrackingTouch(SeekBar arg0) { // TODO Auto-generated method stub temp = arg0.getProgress(); } public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { // TODO Auto-generated method stub temp = arg0.getProgress(); led_val[3] = temp; FLEDControl(led_val[0], led_val[1], led_val[2], led_val[3]); } }); } RadioButton.OnClickListener mLedButtonListener = new RadioButton.OnClickListener() { public void onClick(View v) { switch (v.getId()) { case R.id.fcl_ledbut1: led_val[0] = 9; break; case R.id.fcl_ledbut2: led_val[0] = 8; break; case R.id.fcl_ledbut3: led_val[0] = 7; break; case R.id.fcl_ledbut4: led_val[0] = 6; break; case R.id.fcl_ledbut5: led_val[0] = 5; break; } FullLedActivity.java (4) 23
led_val[1] = sb[0].getProgress(); led_val[2] = sb[1].getProgress(); led_val[3] = sb[2].getProgress(); FLEDControl(led_val[0], led_val[1], led_val[2], led_val[3]); } }; RadioButton.OnClickListener mColorButtonListener = new RadioButton.OnClickListener() { public void onClick(View v) { switch (v.getId()) { case R.id.fcl_red: led_val[1] = 100; led_val[2] = 0; led_val[3] = 0; break; case R.id.fcl_green: led_val[1] = 0; led_val[2] = 0; led_val[3] = 100; break; case R.id.fcl_blue: led_val[1] = 0; led_val[2] = 100; led_val[3] = 0; break; case R.id.fcl_random: led_val[1] = (int) (Math.random() * 101); led_val[2] = (int) (Math.random() * 101); led_val[3] = (int) (Math.random() * 101); break; case R.id.fcl_off: led_val[1] = 0; led_val[2] = 0; led_val[3] = 0; break; } FullLedActivity.java (5) 24
FLEDControl(led_val[0], led_val[1], led_val[2], led_val[3]); sb[0].setProgress(led_val[1]); sb[1].setProgress(led_val[2]); sb[2].setProgress(led_val[3]); } }; } FullLedActivity.java (6) 25
빌드 순서 ◦ JNI 소스인 fullcolorled.c 와 Android.mk 파일을 프로젝트의 jni 폴더에 추가 ◦ “ 윈도키 +r” 을 입력하여 실행창을 오픈한 다음, “cmd” 를 입력하여 커맨드 창을 오픈함 ◦ 안드로이드 App 프로젝트가 있는 폴더로 이동 ◦ 빌드 명령을 실행 빌드를 위해 프로젝트 폴더에 아래와 같은 명령어를 입력 > /EmbeddedSystem/Android/ndk/ndk-build ◦ 빌드가 성공하면, libfullcolorled.so 파일이 생성된 것을 확인 26
27
28