android駆動学習---led実験

14189 ワード

android駆動学習---led実験
ブログの分類:
  • android駆動学習
  • android jni駆動
    ========================
    ドライブ:
    カーネル:android-kernel 2.6.36(プレート上のカーネルに対応する必要があります.そうしないとinsmodエラーが発生します)
    目的:androidアプリケーション層のユーザー空間からカーネル空間ドライバにアクセスします.
    実験:Buttonコントロール、LEDの点灯と消灯.
    注記:androidアプリケーション層アクセスドライバは、一般的にハードウェアドライバにアクセスする2つの方法があります.
    ここで個人的な見方を説明しますから、気にしないでください.
    1:アプリケーション層----->framwork層JNI----->駆動c
    2:アプリケーション層--->framwork層JNI----->ハードウェア抽象層HAL------>駆動c
    2つの方法は、それぞれのメリットがあり、1つ目は、koファイルとlibxxxをコンパイルすれば、駆動デバッグ実験を便利にすることができる.soファイルは、小さなマシンに入れるとすぐにデバッグできます.
    第2のJNI法はHAlを多少変更して追加し,ドライバをパッケージ化し,簡単に言えばハードウェアドライバはLinuxカーネルに分布する一方,ユーザ空間のハードウェア抽象層に分布する.androidはドライバを半分に分けていると誤解しないでください.実はandroidはドライバの呼び出しインタフェースに対応するインタフェース機能を追加してframwork層JNIに呼び出すだけです.例えば、readインタフェースが駆動され、HAl層はreadインタフェースをカプセル化し、hal_を作る.readインタフェース、readインタフェースを呼び出しhal_readインタフェースはJNIに呼び出されます.
    分かりましたか.この方面はとてもよく話している人がいます.これをクリックしてください.
    http://blog.csdn.net/luoshengyang/article/details/6575988
    メリットはメーカーにとってビジネス秘密を隠すことができることです.私たちが駆動実験をすると、操作は極めて複雑になりますが、androidシステム全体を理解するには極めて役に立ちます.androidシステムのハードウェアドライバ層、ハードウェア抽象層、ランタイムライブラリ、アプリケーションフレームワーク層などに関連しているからです.
    ここでは現在、第1の方法しか実現されていません.その前に、JNIのプログラミング方法を理解してください.JNIはJAVAとC、C++の間で互いにアクセスできるプログラミングインターフェースです.この教材をお勧めします(添付ファイルを参照):
    ===============================================================
    ドライブ:
    	#include <linux/module.h>               /* For module specific items */
    	#include <linux/moduleparam.h>          /* For new moduleparam's */
    	#include <linux/types.h>                /* For standard types (like size_t) */
    	#include <linux/errno.h>                /* For the -ENODEV/... values */
    	#include <linux/kernel.h>               /* For printk/panic/... */
    	#include <linux/fs.h>                   /* For file operations */^M
    	#include <linux/ioport.h>               /* For io-port access */
    	#include <linux/platform_device.h>      /* For platform_driver framework */
    	#include <linux/init.h>                 /* For __init/__exit/... */
    	#include <linux/uaccess.h>              /* For copy_to_user/put_user/... */
    	#include <linux/io.h>                   /* For inb/outb/... */
    	#include <linux/gpio.h>
    	#include <linux/device.h>
    	#include <linux/cdev.h>
    	#include <linux/slab.h>               /*kamlloc */
    	//#include <asm-generic/ioctl.h>
    	 
    	 //ioctl         。
    	#define CMD_FLAG  'i'
    	#define LED_ON			_IOR(CMD_FLAG,0x00000000,__u32)  
    	#define LED_OFF		_IOR(CMD_FLAG,0x00000001,__u32)
    	
    	static int  major =0;
    	static struct class *led_class;
    	struct cdev_led {
    		struct cdev cdev;
    	}; //   2.6     ,2.4           。
    	struct cdev_led *led_dev;
    	
    	static int led_ioctl(struct file* filp,unsigned int cmd,unsigned long argv)
    	{
    		printk(KERN_INFO "entry kernel.... 
    "); switch(cmd) { case LED_ON: { gpio_set_value(S3C64XX_GPK(4),0); //LED1 gpkdat[4] printk(KERN_INFO "led on
    "); break; } case LED_OFF: { gpio_set_value(S3C64XX_GPK(4),1); //LED1 gpkdat[4] printk(KERN_INFO "led off
    "); break; } default: return -EINVAL; } return 0; } //open static int led_open(struct inode* i_node,struct file* filp) { printk(KERN_INFO "open init....
    "); int err; err = gpio_request(S3C64XX_GPK(4),"led1"); // gpkcon0[4] 。 if(err<0) { printk(KERN_INFO "gpio request faile
    "); return err; } gpio_direction_output(S3C64XX_GPK(4),1); // gpkcon0[4] return 0; } //close static void led_close(struct inode* i_node,struct file* filp) { printk(KERN_INFO "close init
    "); gpio_free(S3C64XX_GPK(4)); // return ; } /* file operations */ struct file_operations fops={ .owner = THIS_MODULE, .open = led_open, .unlocked_ioctl = led_ioctl, // 2.6.36 ioctl , unlocked_ioctl compat_ioctl. , ioctl 。 .release= led_close, }; static int __init led_init(void) { printk(KERN_INFO "init ....
    "); dev_t dev_no; int result,err; err = alloc_chrdev_region(&dev_no,0,1,"my_led"); // if(err<0) { printk(KERN_INFO "ERROR
    "); return err; } major = MAJOR(dev_no); led_dev = kmalloc(sizeof(struct cdev_led),GFP_KERNEL); if(!led_dev) { result = -ENOMEM; goto fail_malloc; } memset(led_dev,0,sizeof(led_dev)); cdev_init(&led_dev->cdev,&fops); // cdev led_dev->cdev.owner = THIS_MODULE; result = cdev_add(&led_dev->cdev,dev_no,1); // if(result <0) { printk(KERN_INFO "error
    "); goto fail_add; } led_class = class_create(THIS_MODULE,"myled"); // sys/class sysfs device_create(led_class,NULL,MKDEV(major,0),NULL,"myled"); // /dev/myled, return 0; fail_add: kfree(led_dev); fail_malloc: unregister_chrdev_region(dev_no,1); return result; } static void __exit led_exit(void) { dev_t dev_no=MKDEV(major,0); unregister_chrdev_region(dev_no,1); cdev_del(&led_dev->cdev); kfree(led_dev); device_destroy(led_class,dev_no); class_destroy(led_class); printk(KERN_INFO "exit........
    "); } module_init(led_init); module_exit(led_exit); MODULE_AUTHOR("koliy <[email protected]>"); MODULE_DESCRIPTION("ARM test led"); MODULE_LICENSE("GPL");

    個人的なアドバイス:作成ドライバは、定義されたgpioインタフェースをできるだけ使用することが望ましい:
    gpio_direction_output(S3C64XX_GPK(4),1)
    gpio_set_value(S3C64XX_GPK(4),1);
    方面は一目でわかる.プログラムの仕様に役立ちます.
    ------------------------------------------------------------------
    Makefile:
    	KERN_DIR = /android/linux-2.6.36-android
    	all:
    		make -C $(KERN_DIR) M=`pwd` modules
    	clean:
    		make -C $(KERN_DIR) M=`pwd` clean
    	
    	obj-m	+= android_led.o
    

    :make-C:指定したカーネルディレクトリに入り、カーネルの中のMakefileファイルを使用するには、カーネルの保存パスを指定する必要があります.
    M=`pwd`modules:コンパイル現在のディレクトリがモジュールであることを示します.ここでは引用符ではなく、キーボードの数値1キーの左側のキーです.注意してください.
        Obj-m +=android_led.o:コンパイルするモジュール名.このファイルはカーネルのMakefileで生成され、ファイル名を同じにすればいいです.
    コンパイル:(あなたのドライバディレクトリパスの下)#make
    xxx,koモジュールファイルを生成します.
    ------------------------------------------------------------
    アプリケーションレイヤ:androidコントロールandroidコントロール
    この点は、eclipseとandroid-sdkをインストールしてください.わかりませんが、ネットで資料を探してください.
    public class LedControl extends Activity implements OnClickListener {
    	private Button led1_on;
    	private Button led1_off;
    	public int led_on = 1;
    	public int led_off = 2;   
    	public int fd =0;
    	
    	static {
    		try{
    			Log.i("JNI","try to load libled.so");
    			System.loadLibrary("led");  
    	//     ,   JNI   libxxx.so  ,    。
    		}catch (UnsatisfiedLinkError ule){
    			Log.e("JNI","WARNING: Could not load libled.so");
    		}
    	}
    	//JNI   , JAVA  C   。Java         ,      。     ,         。
    	public static native int openled();  
    	public static native void closeled();
    	public static native int ioctl(int led_num,int on_off);
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    	
            fd =this.openled(); //   JNI      /dev/myled    ,         。
            if(fd<0)
            {
            	setTitle("open device faile!");
            	finish();
            }else{
            	setTitle("open device success!");
            }
            findById();
            setOnClickListener();
        }
        
        private void findById(){
        	led1_on = (Button)findViewById(R.id.bt_led1);
        	led1_off=(Button)findViewById(R.id.bt_led2);
        }
        private void setOnClickListener(){
        	led1_on.setOnClickListener(this);
        	led1_off.setOnClickListener(this);
        }
    
    	@Override
    	public void onClick(View v) {
    		// TODO Auto-generated method stub
    		switch(v.getId()){
    			
    			case R.id.bt_led1: {
    				this.ioctl(1,led_on); // led1  on
    				break;
    			}
    			case R.id.bt_led2:{
    				this.ioctl(1,led_off);  // led1 off
    				break;
    			}
    		}
    		
    	}
        
    	protected void onDestroy(){
    		super.onDestroy();
    		this.closeled();
    	}
        
    	}
    
      :
     <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
    <TextView  
    	android:id="@+id/position"
    	android:layout_centerInParent="true"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:textSize="25sp"
        android:text=" led "
        />
    <Button 
    	android:id="@+id/bt_led1"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:textSize="18sp"
    	android:text="LED1 on"
    	android:layout_toLeftOf="@+id/position"
    	android:layout_centerHorizontal="true"
    	android:layout_alignTop="@+id/position"
    	/>
    <Button 
    	android:id="@+id/bt_led2"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:textSize="18sp"
    	android:text="LED1 off"
    	android:layout_toRightOf="@+id/position"
    	android:layout_alignTop="@+id/position"
    	/>
    </RelativeLayout>
    

    ------------------------------------------------------------
    これらは簡単ですが、JNIについて説明します.
    JNI:プロジェクトファイルディレクトリの下にjniディレクトリを新規作成し、中にledを新規作成します.cファイルは、JNIメソッドを記述します.
    	#include<stdio.h>
    	#include<stdlib.h>
    	#include<fcntl.h>
    	#include<errno.h>
    	#include<unistd.h>
    	#include<sys/ioctl.h>
    	#include<jni.h>  //         
    	#include<string.h>
    	#include<sys/types.h>
    	#include<sys/stat.h>
    	#include "android/log.h"
    	//       .
    	#define CMD_FLAG 'i'
    	#define LED_ON		_IOR(CMD_FLAG,0x00000000,__u32)  
    	#define LED_OFF		_IOR(CMD_FLAG,0x00000001,__u32)
    	
    	#define DEVICE_NAME "/dev/myled"
    	int fd ;
    	
    	static const char *TAG="led";
    	#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
    	#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
    	#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
    	
    	/* * Class:     Linuxc 
    	* Method:    openled
    	* Signature: ()I 
    	*/
      JNIEXPORT Jint JNICALL Java_tw_com_mini6410_led_LedControl_openled(JNIEnv* env, jclass mc)
    	{
    		fd = open(DEVICE_NAME,O_RDWR);
    		if(fd<0)
    		{
    			LOGI("don't open dev");
    			return -1;	
    		}
    		else
    			LOGI("open success");
    		return fd;
    	}
    	/* * Class:     Linuxc 
    	* Method:    clsoeled
    	* Signature: ()V
    	*/
    	JNIEXPORT void JNICALL Java_tw_com_mini6410_led_LedControl_closeled(JNIEnv* env, jclass mc)
    	{
    		LOGI("dev close");
    		close(fd);	
    	}
    	
    	
    	JNIEXPORT jint JNICALL Java_tw_com_mini6410_led_LedControl_ioctl
    	(JNIEnv* env,jclass mc, jint a, jint b)
    	{       int tmp = b;
    		if(tmp==1){
    		   
    		 	//int err= write(fd,&tmp,sizeof(tmp));
    			LOGI("led on");
    			ioctl(fd,LED_ON,NULL);
    		}
    		else{
    	//int err= write(fd,&tmp,sizeof(tmp));
    		LOGI("led1 off");
    		ioctl(fd,LED_OFF,NULL);
    		}
    		return 0;	
    	}
    

    Java_tw_com_mini6410_led_LedControl_ioctl :
    tw_com_mini6410_led_LedControl:パッケージ名+クラス名:
    ここで特に説明すると、JNIのフォーマット仕様に注意すべき点は次のとおりです.
    1.関数宣言の形式:JNIは''をに変換クラス名と関数インタフェースに''は表示されません.アプリケーション層がJNIインタフェースを呼び出さないようにすることは初心者にとって極めて重要であるため,eclipseで生成したandroidクラスファイルはクラス名を変更したほうがよい.実験に対する情熱的な打撃が重いことを知らない.2.JNI関数は、ローカルメソッドと静的メソッドに分けられます.ローカルメソッド:public native int jni()//static声明なし.対応するJNI関数のパラメータの定義に変更があります:Java_xx_xx_LedControl_jni(JNIEnv*env,jobject obj)静的方法:public static native int jni()//static声明付き.対応するJNI関数のパラメータの定義に変更があります:Java_xx_xx_LedControl_jni(JNIEnv*env, jclass cls)
    jobjectとjclassの変動に注意してください.
    ぜひJNIを知ってみてください.
    ---------------------------------------------------
    コンパイル:
    このJNIインタフェースを生成するヘッダファイルをコンパイルするにはjavah-jniという別の方法があり、ヘッダファイルに宣言されたインタフェースに基づいて改善することができます.
    しかし、私はどのようにコンパイルしても生成することができなくて、仕方がなくて、手で打つだけで、JNIフォーマットはすべてとても規則的です.
    コマンドなしでLIbxxxを生成するため.soファイル.だからNDKツールを使わなければなりません.インターネットでダウンロードしてください.
    Ndkディレクトリの下にJNIファイルディレクトリを作成します.
    アプリケーションエンジニアリングファイル全体をJNIの下に入れます.
    アクセス(ndkディレクトリパス)/JNI/(アプリケーションエンジニアリングファイル)/jni/
    新しいAndroid.mkファイル
    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    TARGET_PLATFORM := android-3
    LOCAL_MODULE    := led   //     libled.so
    LOCAL_SRC_FILES := led.c   //      。
    LOCAL_LDLIBS    := -llog
    
    include $(BUILD_SHARED_LIBRARY)
    

    -------------------------------------
    -----
    (ndkディレクトリパス)/JNI/(アプリケーションエンジニアリングファイル)/パスに戻る
    入力コマンド:../.../ndk-build
    libsとobjの2つのファイルが生成されます.Libled.soファイルはlibs/armeabi/の下に置く
    ==========================================================
    実験:
    はい、必要な書類はすべて完成しました.今から実験を始めます.その前に、自分の
    開発ボードのandroidにはbusyboxツールが入っています.insmod rmmodなどのコマンドが必要です.
    なければ、インターネットで教材を探してください.
    Adb shell
    #Mkdir  mydev
    #exit
    Adb push  d:\android_led.ko   /mydev
    Adb shell
    #cd mydev
    #chmod 777 android_led.ko
    #insmod android_led.ko
    #lsmod//ロードされているかどうかを確認します.アンインストールコマンドrmmod android_ledは入れないでください.ko
    #cat/proc/devices//デバイス番号とデバイス名も表示できます.
    #ls-l/dev/myled//同様.
    myled権限を変更する必要があります.
    #chmod 777/dev/myled
    ----------
    Libled.so:JNIが生成したsoファイル
    Adb push d:\libled.so/system/lib/hw/アプリケーション層をロードするには、必ずここに置いてください.
    #chmod 766/system/lib/hw/libled.so
    --------------
    では、eclipseでアプリケーションapkを開発ボードにインストールし、開見効果を起動します.あるいはSdで開けてもいいです.
    ここで、JNIインタフェースを呼び出すとnativeインタフェースが見つからないという問題が発生する可能性があります.
    よくチェックすると、方法のフォーマットが複数対あるのは、落ちても使えないので、JNIインタフェースを書き直したり、インタフェース名を変えたりすることができます.このような問題に対しては、本当に崩壊するまでデバッグさせられます.複雑な点は、jniメソッドでclassを指定したほうがいいです.
    この方面はJNI資料を知ったほうがいい.
    最初は多くの問題が発生しますので、ネットワークを多く使用してください.