您的位置:首页 > 移动开发 > Android开发

基于老罗的freg案例,使用NDK工具调用驱动流程详细分析

2014-09-16 16:14 369 查看
        鉴于老罗的《Android内核源代码情景分析》第二章介绍的实例freg,全是在源代码中完成(添加HAL层、JNI层以及开启系统服务),这是一个相对复杂的过程。虽然这种调用过程是比较标准的,但对于项目的开发进度会造成很大的拖延(应用程序每变动一次,你不可能就对内核编译一次吧,虽然使用mmm命令每次花费时间几分钟,但一个项目积累下来这个时间量是相当惊人的)。所以本人通过使用NDK工具直接编写JNI层,生成so库文件,然后在Android应用程序中添加类,加载so库文件即可完成对设备驱动的调用。

说实话,没人指导,一人在那摸索真是痛苦,不过痛苦之后方见彩虹,一切都是值得的。允许我唠叨了些,(*^__^*) 好了,废话不多说,直接进入正题,我仍以freg为例进行讲解编写jni库文件用以调用设备的驱动程序,开发板是飞思卡尔的IMX53开发板,cortex-A8内核。

first,编写Android驱动程序,在myAndroid/kernel_imx/drivers文件夹下新建freg文件夹,文件夹下包含freg.c、freg.h、Kconfig、Makefile,内容就不多说了,照着老罗的驱动copy过来即可,当然你要是有耐心自己一点点敲更好了,加深印象嘛。

          接着就到了修改drivers目录下kconfig和Makefile的环节,kconfig中添加 source "drivers/freg/Kconfig",Makefile中添加 obj-$(CONFIG_FREG)
+= freg/。

          剩下的工作就是编译生成系统文件了。

second,到了本文的重点——编写JNI文件。首先新建Java类,

package com.lcl.whut_open;

import android.util.Log;

public class Jni_open {

public static native int open();

// public static native int get_number();

public static native int write(int i);

public static native int close();

static {

try {

Log.i("JNI", "trying to load freg.default.so");

System.loadLibrary("freg.default");

}catch (UnsatisfiedLinkError e) {

Log.e("JNI", "WARNING: Could not load freg.default.so");

}

}

}

生成头文件,找到你的项目文件保存目录(我的项目文件保存在C:\cygwin\usr\local\android\android-ndk-r6b\samples),在cmd中依次输入

             cd C:\cygwin\usr\local\android\android-ndk-r6b\samples\whut_open和javah -classpath bin\classes -d jni com.lcl.whut_open.Jni_open。就可生成相应的头文件。

根据头文件编写freg.c,

#include<string.h>

#include<jni.h>

#include<fcntl.h>

#include<unistd.h>

#include<stdlib.h>

#include<android/log.h>

#define LOG_TAG "System.out"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , LOG_TAG , __VA_ARGS__)

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO , LOG_TAG , __VA_ARGS__)

#define DEV_NAME "/dev/freg"

int fd;

JNIEXPORT jint JNICALL Java_com_lcl_whut_1open_Jni_1open_open

(JNIEnv* env, jclass thiz)

{

fd = open(DEV_NAME, O_RDWR);

if(fd<0)

{

LOGD ("open failed!");

return fd;

}

LOGD ("freg open success!");

return fd;

}

JNIEXPORT jint JNICALL Java_com_lcl_whut_1open_Jni_1open_write

(JNIEnv* env, jclass thiz, jint i)

{

write(fd,&i,sizeof(i));

return 0;

}

JNIEXPORT jint JNICALL Java_com_lcl_whut_1open_Jni_1open_close

(JNIEnv* env, jclass thiz)

{

close(fd);

return 0;

}

编写Android.mk,

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := freg.default

LOCAL_SRC_FILES := freg.c

LOCAL_LDLIBS += -llog

include $(BUILD_SHARED_LIBRARY)

最后使用NDK来编译生成so库文件,1)、运行cygwin,输入命令cd C:/cygwin/usr/local/android/android-ndk-r6b/samples/JNItest,进入到JNItest目录。

2)、输入"$NDK/ndk-build",执行成功后,它会自动生成一个libs目录,把编译生成的.so文件放在里面。($NDK是调用我们之前配置好的环境变量,ndk-build是调用ndk的编译程序)。

finally,在Android应用层代码通过类访问驱动,代码如下:

package com.lcl.whut_open;

import android.os.Bundle;

import android.app.Activity;

import android.util.Log;

import android.view.Menu;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

public class MainActivity extends Activity {

private final static String LOG_TAG = "com.lcl.whut_open.MainActivity";

public int fd=0;

public int val;

private EditText valueText = null;

private EditText EditText01 = null;

private Button openButton = null;

private Button readButton = null;

private Button writeButton = null;

private Button closeButton = null;

private Button.OnClickListener writebutton_listener=new Button.OnClickListener()

{

public void onClick(View v)

{

int i=-1;

val=4;

i=Jni_open.write(val);

Log.d(LOG_TAG, "write success");

String text = String.valueOf(i);

valueText.setText(text);

}

};

private Button.OnClickListener openbutton_listener=new Button.OnClickListener()

{

public void onClick(View v)

{

fd=Jni_open.open();

if(-1==fd){

Log.d(LOG_TAG, "open device error!");

}

String text = String.valueOf(fd);

EditText01.setText(text);

}

};

private Button.OnClickListener closebutton_listener=new Button.OnClickListener()

{

public void onClick(View v)

{

fd=Jni_open.close();

if(-1==fd)

Log.d(LOG_TAG, "close device error!");

String text = String.valueOf(fd);

EditText01.setText(text);

valueText.setText(text);

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

valueText = (EditText)findViewById(R.id.edit_value);

EditText01 = (EditText)findViewById(R.id.EditText01);

openButton= (Button)findViewById(R.id.button_open);

readButton= (Button)findViewById(R.id.button_read);

writeButton= (Button)findViewById(R.id.button_write);

closeButton= (Button)findViewById(R.id.button_close);

String text = String.valueOf(fd);

EditText01.setText(text);

openButton.setOnClickListener(openbutton_listener);

// readButton.setOnClickListener(readbutton_listener);

writeButton.setOnClickListener(writebutton_listener);

closeButton.setOnClickListener(closebutton_listener);

}

至此整个编写过程已经完成,接下来就是将应用软件安装到imx536开发板上(需要注意的是,安装apk之前必须在电脑上运行360手机助手之类的软件,要不然无法直接运行程序,++,诡异的开发板,花了哥大把时间在这上面。),就可发现apk软件来控制freg驱动程序了。(应用程序的界面图就不提供了,和老罗的应用程序界面基本一样,太麻烦,懒人一枚望见谅。)

望此文对新手们有用,当然我也是新手一枚。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐