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 __cplusplus
extern "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 := pwm
LOCAL_SRC_FILES := pwm.c
LOCAL_LDLIBS := -llog
LOCAL_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百分之五十的波形,测试成功。

Android JNI用于驱动测试

时间: 2024-10-20 21:17:08

Android JNI用于驱动测试的相关文章

基于Eclipse的Android JNI层测试应用开发过程记录

前言 本文记录一个Java层与JNI层参数与数据交互的应用程序开发过程,为实现一个功能完整的带Java与JNI的应用程序打下基础.本文假设读者已搭建好Android的Eclipse与NDK开发环境,包括通过ADB连接手机的配置. 1. 构建基本的Android应用程序 1.1 引导界面配置 打开Eclipse,"File"->"New"->"Android Application Project",在弹出界面,配置如下(红色框表示不是

android JNI 调用NDK方法

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css); 准备工作: 1.需要安装JDK,我使用的是JDK 1.7.0: 2.安装NDK,我使用的是android studio 自动下载的版本: 现在开始实现这个调用过程: 1.新建一个工程:MyJNITest activity_main.xml(用于显示测试结果): 2.在

windows android JNI 使用和环境搭建

网上看了很多文章,有的太老了,有的不说的不是很清楚,这个一步一步开始使用android JNI 方法 参考:http://bbs.51cto.com/thread-948244-1.html### http://www.cnblogs.com/kissazi2/p/3298884.html 使用GNUStep作为C/C++编译器,选择这个的原因是,编译器小,很快就下载完成 (一)下载安装编译环境 1.打开网站  http://www.gnustep.org/ 进入后,下载安装,从上到下的顺序安装

Android系统从驱动到上层服务再到应用的两种服务架构方式

Android系统从驱动到上层服务再到应用的两种服务架构方式 1)使用类似sensor service的方式: 此方式用于,service的接口不想暴露给上层activity直接使用的情形例如sensor架构c/s结构,适合多个应用与单个服务通信,binder通信时,做connection的区分即可区分不同的client. 2)使用AIDL直接暴露接口的方式: 这个更适合单个应用与服务通信,多个应用与服务通信时,需要处理接口的重入问题.利用Binder实现的标准JNI,不用你去专门实现自己的JN

【转】android JNI

原文网址:http://jinguo.iteye.com/blog/696185 Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C.C++ 和汇编语言)编写的应用程序和库进行交互操作. 1.从如何载入.so档案谈起 由于Android的应用层的类都是以Java写的,这些Java类编译为Dex型式的Byt

Android单元测试与模拟测试详解

测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabricator differential 发diff时提交需要执行的单元测试,在开发流程上就可以保证远端代码的稳定性). 2. 测什么? 一般单元测试: 列出想要测试覆盖的异常情况,进行验证. 性能测试. 模拟测试: 根据需求,测试用户真正在使用过程中,界面的反馈与显示以及一些依赖系统架构的组件的应用测

Android JNI之JAVA与C++对象建立对称关联(JNI优化设计,确保JNI调用的稳定性)

转载请声明:原文转自:http://www.cnblogs.com/xiezie/p/5930503.html Android JNI之JAVA与C++对象建立对称关联 1.JAVA对象持有C++对象的指针 在JAVA类中创建一个int类型的变量(如int mObj),用于储存C++对象的指针 在创建C++对象(如MyCPlusObj)的本地方法中,将C++对象的指针存入JAVA变量中(mObj) JNIEXPORT void JNICALL Java_nativeMethod (JNIEnv

Android JNI 获取应用签名

使用Android JNI 获取应用签名. 根据获取的签名来生成自己的密码,这样可以防止别人反编译自己的源码后查找密码. jstring Java_com_masonsdk_jni_JNIUtil_getPWD(JNIEnv* env, jobject thizz ,jobject thiz ){ jclass native_clazz = env->GetObjectClass(thiz); // 得到 getPackageManager 方法的 ID jmethodID methodID_f

I.MX6 Android CAN 命令行测试

/********************************************************************* * I.MX6 Android CAN 命令行测试 * 说明: * 这里使用can-utils测试一下CAN驱动. * * 2016-8-9 深圳 南山平山村 曾剑锋 ********************************************************************/ 一.shell 命令流程: 1. netcfg c