当前位置: 代码迷 >> Android >> Android JNI用来驱动测试
  详细解决方案

Android JNI用来驱动测试

热度:47   发布时间:2016-04-28 04:52:58.0
Android JNI用于驱动测试

硬件平台:S3C6410

操作系统:Ubuntu、windows

板子系统:Android

开发工具:jdk,ndk,eclipse

本次测试从linux内核模块编译开始,以S3C6410的pwm驱动为例。

pwm_6410.c:

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/clk.h>#include <linux/cdev.h>#include <linux/device.h>#include <linux/miscdevice.h>#include <linux/interrupt.h>#include <plat/regs-timer.h>#include <plat/gpio-cfg.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/mach/time.h>#include <asm/uaccess.h>#include <mach/map.h>#include <mach/regs-clock.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <mach/gpio-bank-e.h>#include <mach/gpio-bank-f.h>#include <mach/gpio-bank-k.h>#include <mach/regs-irq.h>#define DEVICE_NAME  "pwm"static struct semaphore lock;static void PWM_Set_Freq( unsigned long freq ){	unsigned long tcon;	unsigned long tcnt;	unsigned long tcfg1;	unsigned long tcfg0;	unsigned long pclk;	unsigned tmp;	struct clk *clk_p;    printk ("Freq is %d",freq);	tmp = readl(S3C64XX_GPFCON);//PWM GPF15    tmp &= ~(0x3U << 30);// Timer1    tmp |=  (0x2U << 30);	writel(tmp, S3C64XX_GPFCON);	tcon  = __raw_readl(S3C_TCON);	tcfg1 = __raw_readl(S3C_TCFG1);	tcfg0 = __raw_readl(S3C_TCFG0);	tcfg0 &= ~S3C_TCFG_PRESCALER0_MASK;	tcfg0 |= (50 - 1);     tcfg1 &= ~S3C_TCFG1_MUX1_MASK;    tcfg1 |= S3C_TCFG1_MUX1_DIV16;	__raw_writel(tcfg1, S3C_TCFG1);	__raw_writel(tcfg0, S3C_TCFG0);	clk_p = clk_get(NULL, "pclk");	pclk  = clk_get_rate(clk_p);	tcnt  = (pclk/50/16)/freq;	__raw_writel(tcnt, S3C_TCNTB(1));	__raw_writel(tcnt/2, S3C_TCMPB(1));	tcon &= ~(0xf << 8);	tcon |= (0xb << 8);			__raw_writel(tcon, S3C_TCON);	tcon &= ~(2 << 8);	__raw_writel(tcon, S3C_TCON);}void PWM_Stop( void ){	unsigned tmp;	tmp = readl(S3C64XX_GPFCON);	tmp &= ~(0x3U << 30);// set GPF15	writel(tmp, S3C64XX_GPFCON);}static int s3c64xx_pwm_open(struct inode *inode, struct file *file){	if (!down_trylock(&lock))		return 0;	else		return -EBUSY;}static int s3c64xx_pwm_close(struct inode *inode, struct file *file){	up(&lock);	return 0;}static long s3c64xx_pwm_ioctl(struct file *filep, unsigned int cmd, unsigned long arg){	switch (cmd) 	{		case 1:			if (arg == 0)			return -EINVAL;			PWM_Set_Freq(arg);			break;		case 0:			PWM_Stop();			break;	}	return 0;}static struct file_operations dev_fops = {    .owner		= THIS_MODULE,    .open		= s3c64xx_pwm_open,    .release	= s3c64xx_pwm_close,     .unlocked_ioctl	= s3c64xx_pwm_ioctl,};static struct miscdevice misc = {    .minor = MISC_DYNAMIC_MINOR,    .name  = DEVICE_NAME,    .fops  = &dev_fops,};static int __init dev_init(void){	int ret;	init_MUTEX(&lock);	ret = misc_register(&misc);	printk (DEVICE_NAME"\tinitialized\n");    return ret;}static void __exit dev_exit(void){	misc_deregister(&misc);}MODULE_LICENSE("GPL");module_init(dev_init);module_exit(dev_exit);
Makefile添加:

obj-$(CONFIG_PWM_S3C6410)        += pwm_6410.o
Kconfig添加:

config PWM_S3C6410	tristate "pwm"	depends on CPU_S3C6410

make menuconfig配置内核后编译内核

make zImage后启动Android系统

ls /dev会看到名称为pwm的设备驱动

驱动已经加载好,这时候就要编写Android下的测试程序。JNI是Java Native Interface的缩写,即Java本地调用,它允许java代码和其他语言写的代码进行交互。写测试程序时使用JNI方式实现。

eclipse建立一个新的应用工程,取名为pwm,包名为com.example.pwm

默认生成的java代码:PwmActivity.java

package com.example.pwm;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;public class PwmActivity extends Activity {	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_pwm);	}	@Override	public boolean onCreateOptionsMenu(Menu menu) {		// Inflate the menu; this adds items to the action bar if it is present.		getMenuInflater().inflate(R.menu.activity_pwm, menu);		return true;	}}
添加本地方法:

package com.example.pwm;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;public class PwmActivity extends Activity {	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_pwm);	}	@Override	public boolean onCreateOptionsMenu(Menu menu) {		// Inflate the menu; this adds items to the action bar if it is present.		getMenuInflater().inflate(R.menu.activity_pwm, menu);		return true;	}       public static native int pwm_set_freq(int i, int j);		static {  	System.loadLibrary("pwm");  // 添加 C/C++动态库导入方法  	}}

编辑res/layout下activity_pwm.xml

添加button控件

    <Button        android:id="@+id/pwm_on"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_above="@+id/textView1"        android:layout_alignLeft="@+id/textView1"        android:layout_marginBottom="39dp"        android:onClick="onPwmOnClicked"        android:text="@string/pwm" />
编辑res/values下strings.xml

添加

<string name="pwm">pwm</string>
PwmActivity.java中添加:

    public void onPwmOnClicked(View v){    	pwm_set_freq(1,200);    }
PwmActivity.java:

package com.example.pwm;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;public class PwmActivity extends Activity {	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_pwm);	}	@Override	public boolean onCreateOptionsMenu(Menu menu) {		// Inflate the menu; this adds items to the action bar if it is present.		getMenuInflater().inflate(R.menu.activity_pwm, menu);		return true;	}        public void onPwmOnClicked(View v){    	        pwm_set_freq(1,200); //按下按键就输出波形        }	public static native int pwm_set_freq(int i, int j);		static {  	System.loadLibrary("pwm");  // 添加 C/C++动态库导入方法  ,这个库需要使用NDK工具编译生成。	}  }
上述步骤就绪后,编译工程,再将该工程拷贝到Ubuntu下

工程目录下创建jni文件夹:


使用javah命令生成jni头文件

注意冒号后没有空格

生成的头文件:


com_example_pwm_PwmActivity.h:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_pwm_PwmActivity */#ifndef _Included_com_example_pwm_PwmActivity#define _Included_com_example_pwm_PwmActivity#ifdef __cplusplusextern "C" {#endif#undef com_example_pwm_PwmActivity_MODE_PRIVATE#define com_example_pwm_PwmActivity_MODE_PRIVATE 0L#undef com_example_pwm_PwmActivity_MODE_WORLD_READABLE#define com_example_pwm_PwmActivity_MODE_WORLD_READABLE 1L#undef com_example_pwm_PwmActivity_MODE_WORLD_WRITEABLE#define com_example_pwm_PwmActivity_MODE_WORLD_WRITEABLE 2L#undef com_example_pwm_PwmActivity_MODE_APPEND#define com_example_pwm_PwmActivity_MODE_APPEND 32768L#undef com_example_pwm_PwmActivity_MODE_MULTI_PROCESS#define com_example_pwm_PwmActivity_MODE_MULTI_PROCESS 4L#undef com_example_pwm_PwmActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING#define com_example_pwm_PwmActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L#undef com_example_pwm_PwmActivity_BIND_AUTO_CREATE#define com_example_pwm_PwmActivity_BIND_AUTO_CREATE 1L#undef com_example_pwm_PwmActivity_BIND_DEBUG_UNBIND#define com_example_pwm_PwmActivity_BIND_DEBUG_UNBIND 2L#undef com_example_pwm_PwmActivity_BIND_NOT_FOREGROUND#define com_example_pwm_PwmActivity_BIND_NOT_FOREGROUND 4L#undef com_example_pwm_PwmActivity_BIND_ABOVE_CLIENT#define com_example_pwm_PwmActivity_BIND_ABOVE_CLIENT 8L#undef com_example_pwm_PwmActivity_BIND_ALLOW_OOM_MANAGEMENT#define com_example_pwm_PwmActivity_BIND_ALLOW_OOM_MANAGEMENT 16L#undef com_example_pwm_PwmActivity_BIND_WAIVE_PRIORITY#define com_example_pwm_PwmActivity_BIND_WAIVE_PRIORITY 32L#undef com_example_pwm_PwmActivity_BIND_IMPORTANT#define com_example_pwm_PwmActivity_BIND_IMPORTANT 64L#undef com_example_pwm_PwmActivity_BIND_ADJUST_WITH_ACTIVITY#define com_example_pwm_PwmActivity_BIND_ADJUST_WITH_ACTIVITY 128L#undef com_example_pwm_PwmActivity_CONTEXT_INCLUDE_CODE#define com_example_pwm_PwmActivity_CONTEXT_INCLUDE_CODE 1L#undef com_example_pwm_PwmActivity_CONTEXT_IGNORE_SECURITY#define com_example_pwm_PwmActivity_CONTEXT_IGNORE_SECURITY 2L#undef com_example_pwm_PwmActivity_CONTEXT_RESTRICTED#define com_example_pwm_PwmActivity_CONTEXT_RESTRICTED 4L#undef com_example_pwm_PwmActivity_RESULT_CANCELED#define com_example_pwm_PwmActivity_RESULT_CANCELED 0L#undef com_example_pwm_PwmActivity_RESULT_OK#define com_example_pwm_PwmActivity_RESULT_OK -1L#undef com_example_pwm_PwmActivity_RESULT_FIRST_USER#define com_example_pwm_PwmActivity_RESULT_FIRST_USER 1L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_DISABLE#define com_example_pwm_PwmActivity_DEFAULT_KEYS_DISABLE 0L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_DIALER#define com_example_pwm_PwmActivity_DEFAULT_KEYS_DIALER 1L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_SHORTCUT#define com_example_pwm_PwmActivity_DEFAULT_KEYS_SHORTCUT 2L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_SEARCH_LOCAL#define com_example_pwm_PwmActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L#undef com_example_pwm_PwmActivity_DEFAULT_KEYS_SEARCH_GLOBAL#define com_example_pwm_PwmActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L/* * Class:     com_example_pwm_PwmActivity * Method:    pwm_set_freq * Signature: (II)I */JNIEXPORT jint JNICALL Java_com_example_pwm_PwmActivity_pwm_1set_1freq  (JNIEnv *, jclass, jint, jint);#ifdef __cplusplus}#endif#endif

将头文件拷贝到jni目录下,jni目录下创建pwm.c:

#include <jni.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <android/log.h> #define LOG_TAG "PWM" //android logcat #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__ ) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS_ _) jint JNICALL Java_com_example_pwm_PwmActivity_pwm_1set_1freq(JNIEnv *env, jclass thiz, jint cmd, jint freq)  { //函数名与头文件中的保持一致	int fd;	fd = open("/dev/pwm",O_RDWR);	if (fd < 0)	{		printf ("Open /dev/pwm file error\n");		return -1;	}		ioctl(fd,1,200);	close (fd);	return 0;}

jni目录下创建Android.mk

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := pwmLOCAL_SRC_FILES := pwm.cLOCAL_LDLIBS := -llogLOCAL_C_INCLUDES := $(MY_ANDROID_SOURCE)/frameworks/base/core/jni/android/graphics \$(MY_ANDROID_SOURCE)/external/skia/include/core \$(MY_ANDROID_SOURCE)/external/skia/include/images \$(MY_ANDROID_SOURCE)/frameworks/base/include \$(MY_ANDROID_SOURCE)/system/core/include include $(BUILD_SHARED_LIBRARY)
命令ndk-build,如果工程目录下没有libs/armeabi,那么就创建armeabi


生成了libpwm.so就是我们在Android应用工程中需要的库文件

 static {        System.loadLibrary("pwm");  // 添加 C/C++动态库导入方法        }  

将含有libpwm.so的工程文件从Ubuntu中考到windows,eclipse打开工程,编译生成apk

pwm.apk

在板子上安装,控制终端下输入命令:

pm install -f pwm.apk

安装成功提示success之后,点开软件,点击pwm按钮。

示波器输出200Hz百分之五十的波形,测试成功。


  相关解决方案