zoukankan      html  css  js  c++  java
  • 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"	initialized
    ");
        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建立一个新的应用project。取名为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工具编译生成。

    } }

    上述步骤就绪后,编译project,再将该project复制到Ubuntu下

    project文件夹下创建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
    ");
    		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,假设project文件夹下没有libs/armeabi,那么就创建armeabi


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

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

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

    pwm.apk

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

    pm install -f pwm.apk

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

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


  • 相关阅读:
    javaweb 最简单的分页技术
    Jquery选择器小结
    JSON 初探
    C# GridView 的使用
    C# 操作数据库
    Java中String为什么是不可变
    Eclipse使用技巧小结
    Java File类方法使用详解
    JSP基础语法总结
    JSP取得绝对路径
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7105576.html
Copyright © 2011-2022 走看看