第一步:首先在linux下添加驱动
第二步:建立Android测试代码---实现.so文件
第三步:写应用程序
问题一:android NDK jni下的c文件 Unresolved inclusion
问题二:在android 里使用JNI,总是报错:in something not a structure or union
问题三:直接在应用程序中获取驱动的可执行权限#chmod 777
问题四:S5VP210端口设置小结
第一步:首先在linux下添加驱动
1.查看原理图,找出未使用的引脚,这里是:GPJ0_0 GPJ0_1
2.添加char字符设备驱动,找到LINUX源代码下的char设备驱动路径: FriendlyArm /Linux3.0.8/ Drivers/char/目录,在目录下新建里一个文件lzm_fjicc.c 用来写驱动用。
需要注册设备、设备的打开、关闭、取消设备等操作。
源代码如下:
//lzm_fjicc.c
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <mach/map.h>
#include <mach/gpio.h>
#include <mach/regs-clock.h>
#include <mach/regs-gpio.h>
#define DEVICE_NAME "LZM_FJICC"
static int lzm_gpios[] = {
S5PV210_GPJ0(0),
S5PV210_GPJ0(1),
S5PV210_GPJ0(2),//设置为输入,读取次引脚的状态
};
#define GPIO_NUM ARRAY_SIZE(lzm_gpios)
static int lzm_open(struct inode *inode, struct file *file)
{
int ret;
int i;
for (i = 0; i < GPIO_NUM; i++) {
ret = gpio_request(lzm_gpios[i], "GPIO");
if (ret) {
printk("%s: request GPIO %d failed, ret = %d\n", DEVICE_NAME,
lzm_gpios[i], ret);
return ret;
}
s3c_gpio_cfgpin(lzm_gpios[i], S3C_GPIO_OUTPUT); //设置为输出状态
gpio_set_value(lzm_gpios[i], 1);//默认高电平
}
//set to be input and pullup
s3c_gpio_cfgpin(lzm_gpios[2], S3C_GPIO_INPUT); //设置为输入状态
s3c_gpio_setpull(lzm_gpios[2],S3C_GPIO_PULL_UP);//上拉
// ret = misc_register(&lzm_dev);//register devices to core
printk(DEVICE_NAME"\t open success!\n");
return 0;
}
static int lzm_close(struct inode *inode, struct file *file)
{
int i;
for (i = 0; i < GPIO_NUM; i++) {
gpio_free(lzm_gpios[i]);
}
// misc_deregister(&lzm_dev);
printk(DEVICE_NAME"\t close success! \n");
return 0;
}
static long lzm_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
int temp;
switch(cmd) {
case 0://write 0
if (arg > GPIO_NUM) {
return -EINVAL;
}
gpio_set_value(lzm_gpios[arg],0);
//printk(DEVICE_NAME": %d %d\n", arg, cmd);
break;
case 1://write 1
if (arg > GPIO_NUM) {
return -EINVAL;
}
gpio_set_value(lzm_gpios[arg],1);
//printk(DEVICE_NAME": %d %d\n", arg, cmd);
break;
case 3://read GPJ0_2 state //读取端口状态
temp = gpio_get_value(S5PV210_GPJ0(2));
udelay(50);//delay for
printk("read the GPJ0_2 value :%d\n",temp);
return temp;
break;
default:
return -EINVAL;
}
return 0;
}
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = lzm_open,
.unlocked_ioctl = lzm_ioctl,
.release = lzm_close,
};
static struct miscdevice lzm_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &dev_fops,
};
//register device
static int __init dev_init(void)
{
int ret;
ret = misc_register(&lzm_dev);
printk(DEVICE_NAME"\t registered!\n");
return ret;
}
//disregister device
static void __exit dev_exit(void)
{
misc_deregister(&lzm_dev);
printk("\texit!\n");
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");//驱动类型
MODULE_AUTHOR("LZM");//作者信息
MODULE_DESCRIPTION("TEST TEST");//驱动描述
第二步:建立Android测试代码,第一步要实现.so文件:
1.打开eclipseàFileàNewàAndroid Application Project com.example.lzm0922
2.新建jni文件夹,在文件夹内新建两个文件:jni0922.c和Android.mk
Android.mk内容如下:
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
include$(CLEAR_VARS)
LOCAL_MODULE := jni0922
LOCAL_SRC_FILES := jni0922.c
include$(BUILD_SHARED_LIBRARY)
jni0922.c内容如下:
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include<termios.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/ioctl.h>
#include<fcntl.h>
#include<string.h>
#include<jni.h>
#include<errno.h>
//#include <utils/Log.h>
#include<ALog.h>
//#include <system.h>
#define OFF 0x11
#define ON 0x22
#define READ 0x33
#define DEV_NAME "/dev/LZM_FJICC"
int fd;
/* This is a trivial JNI example where we use a native method
* to return a new VM String. See the corresponding Java source
* file located at:
*
* /project/app/TEST/src/com.example.lzm0922/MainActivity.java
* /project/app/TEST/src/com.example.lzm0922/TESTCLASS.java
*/
jstring
Java_com_example_lzm0922_TESTCLASS_stringFromJNI( JNIEnv* env, jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
jint
Java_com_example_lzm0922_TESTCLASS_IOCTL( JNIEnv* env, jobject thiz,jint fd ,jint controlcode,jint ledid )
{
/* LED */
int CTLCODE = controlcode;
int value =-1;
switch(CTLCODE)
{ case ON:
{
ioctl(fd,1,ledid);//setLedState( 0, 1 );//调用驱动程序中的ioctrl接口,把命令传下去,实现硬件操作
break;
}
case OFF:
{
ioctl(fd,0,ledid);//// setLedState( 0, 0 );//调用驱动程序中的ioctrl接口,把命令传下去,实现硬件操作
break;
}
case READ:
{
value=ioctl(fd,3,ledid);// 2 表示读取状态的cmd;0、1表示led控制的命令;
return value;
break;
}
default:break;
}
return 0;
}
jint
Java_com_example_lzm0922_TESTCLASS_OPEN(JNIEnv* env)
{
fd=open(DEV_NAME,O_RDWR);
return fd;
}
int
Java_com_example_lzm0922_TESTCLASS_CLOSE(JNIEnv* env)
{ int ret;
ret = close(fd);
return ret;
}
注意其中的一个头文件Alog.h需要自己写,然后放在jni文件夹下的
#pragma once
#include<android/log.h>
#define LOG_TAG "debug log"
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt, ##args)
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##args)
3.建立完毕,打开Cygwin工具,并进入到工程目录下的jni目录下:
$ cd d:/Program/Android/workspace/lzm0922/jni
$$NDK/ndk-build
这样就OK了,生成了libjni0922.so文件了,自动生成到了工程目录下的libs/armeabi/ libjni0922.so,发现jni0922是我们刚才在.mk文件里面的命名。
第三步:写应用程序:
1.在应用程序类com.example.lzm0922目录下建立一个类:TESTCLASS.java,输入如下代码,这是用来引用libjni0922.so文件的。
package com.example.lzm0922;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.util.Log;
publicclass TESTCLASS{
public native String stringFromJNI();
publicnativeint OPEN();
public nativeint IOCTL(int fd,int controlcode,int ledID);
public nativeint CLOSE();
static {
try {
System.loadLibrary("jni0922");
} catch (UnsatisfiedLinkError e) {
Log.d("HardwareControler", "HardwareControler ibrary not found!");
}
}
}
2.编写应用程序,调用TESTCLASS类中的函数OPEN()/CLOSE()/IOCTL()就可以实现底层的控制了。
添加两个按钮,用来打开和关闭LED灯,以及读取端口的状态
<Button
android:id="@+id/myButtonOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="28dp"
android:text="GPJ0_OFF" />
<Button
android:id="@+id/myButtonRd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/myButtonOff"
android:layout_centerVertical="true"
android:text="GPJ0_RD" />
<Button
android:id="@+id/myButtonOn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/myButtonOff"
android:layout_below="@+id/myButtonOff"
android:layout_marginTop="27dp"
android:text="GPJ0_ON" />
2.编写MainActivity,添加响应函数:
package com.example.lzm0922;
import java.io.DataOutputStream;
import java.io.IOException;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
publicclass MainActivity extends Activity {
private Button btn_on,btn_off;
private Button btn_rd;
publicstaticfinalintON = 0x22;
publicstaticfinalintOFF = 0x11;
publicstaticfinalintREAD = 0x33;
intfd;
intvalue = -1;
public String s;
TESTCLASS mTESTCLASS1;
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTESTCLASS1 = new TESTCLASS();
s = mTESTCLASS1.stringFromJNI().toString();
//修改驱动的权限LED_LZM_FJICC
changePerm();
fd=mTESTCLASS1.OPEN();
btn_on = (Button)findViewById(R.id.myButtonOn);
btn_off = (Button)findViewById(R.id.myButtonOff);
btn_rd = (Button)findViewById(R.id.myButtonRd);
if(fd == -1)
Toast.makeText(MainActivity.this, "没有打开设备 "+"fd="+fd, Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "打开设备"+" fd="+fd, Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this,""+s, Toast.LENGTH_SHORT).show();
btn_on.setOnClickListener(new Button.OnClickListener(){
@Override
publicvoid onClick(View arg0) {
// TODO Auto-generated method stub
mTESTCLASS1.IOCTL(fd,ON,0);
}
});
btn_off.setOnClickListener(new Button.OnClickListener(){
@Override
publicvoid onClick(View v) {
// TODO Auto-generated method stub
mTESTCLASS1.IOCTL(fd,OFF,0);
}});
btn_rd.setOnClickListener(new Button.OnClickListener(){
@Override
publicvoid onClick(View v) {
// TODO Auto-generated method stub
value = mTESTCLASS1.IOCTL(fd,READ,1);
Toast.makeText(MainActivity.this, "GPJ0_2="+value, Toast.LENGTH_SHORT).show();
}});
}
@Override
protectedvoid onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Toast.makeText(MainActivity.this, "Close fd="+fd, Toast.LENGTH_SHORT).show();
int temp = mTESTCLASS1.CLOSE();
if(temp == -1)
Toast.makeText(MainActivity.this, "Close Failed fd="+temp, Toast.LENGTH_SHORT).show();
else
Toast.makeText(MainActivity.this, "Close Success fd="+temp, Toast.LENGTH_SHORT).show();
}
void changePerm()
{
Process chperm;
try {
chperm=Runtime.getRuntime().exec("su");
DataOutputStream os =
new DataOutputStream(chperm.getOutputStream());
os.writeBytes("chmod 777 /dev/LZM_FJICC\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
chperm.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
问题一:android NDK jni下的c文件 Unresolved inclusion
原因是在eclipse编辑环境中没有找到对应的include中的文件。解决方法是将包含该文件的include目录作为新的linked folder加入工程中。具体方法如下:
1. 右击工程->New->Folder
2. 对话框中点击Advanced
3. 选择Link to alternate location (Linked Folder),选择需要的include目录
4. Finish后刷新工程,问题解决。
include 目录可以在ndk的安装目录中找到
比如:在安装的NDK目录下找到/NDKDir/android-ndk-r7b/platforms/android-8/arch-arm/usr/include
问题二:在android 里使用JNI,总是报错:in something not a structure or union
error: request for member 'GetStringUTFChars' in something not a structure or union
问题解决了,原来是这样的:
如果是c程序,要用 (*env)->
如果是C++要用 env->
在linux下如果.c文件中用 “env->” 编译会找不到此结构,必须用“(*env)->”,或者改成.cpp文件,以 c++的方式来编译
以下是两者的区别:
jni.h中
struct JNINativeInterface_;
struct JNIEnv_;
#ifdef __cplusplus
typedef JNIEnv_ JNIEnv;
#else
typedef const struct JNINativeInterface_ *JNIEnv;
#endif
/*
* We use inlined functions for C++ so that programmers can write:
* env->FindClass("java/lang/String")
* in C++ rather than:
* (*env)->FindClass(env, "java/lang/String")
* in C.
*/
即C++中使用
env->FindClass("java/lang/String")
C中使用
(*env)->FindClass(env, "java/lang/String")
问题三:直接在应用程序中获取驱动的可执行权限#chmod 777
//用来修改驱动的权限问题否则需要在终端输入 #chmod 777 /dev/LZM_FJICC
void changePerm()
{
Process chperm;
try {
chperm=Runtime.getRuntime().exec("su");
DataOutputStream os =
new DataOutputStream(chperm.getOutputStream());
os.writeBytes("chmod 777 /dev/LZM_FJICC\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
chperm.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
问题四:S5VP210端口设置小结
// 定义用到的引脚 S5PV210_GPJ0(7)
// 设置引脚的输出
s3c_gpio_cfgpin(S5PV210_GPJ0(7),S3C_GPIO_SFN(1));//设置为输出
gpio_direction_output(S5PV210_GPJ0(7),0);
//释放总线
#define OW_Pin S5PV210_GPJ0(7)
s3c_gpio_cfgpin(OW_Pin,S3C_GPIO_SFN(0));//设置为输入
s3c_gpio_setpull(OW_Pin,S3C_GPIO_PULL_UP);
gpio_get_value(OW_Pin)//获取引脚的输入电平状态
相关推荐
JNI代码需要设置GPIO引脚为输出模式,然后通过写入高电平或低电平来控制LED的亮灭。 在"LEDDemo"这个项目中,我们可以看到一个具体的示例,演示了如何通过JNI调用.so文件,控制Tiny210上的LED灯。这个例子将帮助...
JNI++用户手册主要介绍了如何利用JNI++这一工具来实现Java与C++/C之间的互操作。JNI,全称为Java Native Interface,是Java平台提供的一种原生接口,允许Java代码和其他语言编写的代码进行交互。JNI++是JNI的一个...
在Android系统中,Java Native Interface (JNI) 是一个关键组件,允许Java代码与其他语言(如C++或C)编写的代码进行交互。本项目聚焦于如何利用JNI来访问硬件资源,特别是控制LED设备。以下是对这个主题的详细阐述...
JNI(Java Native Interface)是Java平台提供的一种允许Java代码和其他语言写的代码进行交互的机制。在Java中,如果一个方法被声明为`native`,那么这个方法的实现并不在Java代码中,而是在其他语言(如C、C++)中。...
这个"一个简单的JNI实验"是一个实践教程,旨在帮助初学者理解如何在Java程序中调用本地(非Java)代码,比如C或C++。下面我们将详细探讨JNI的相关知识点。 1. **JNI的基本概念**: JNI是Java平台提供的一种机制,...
JNI(Java Native Interface)是Java平台提供的一种机制,允许Java代码和其他语言写的代码进行交互。在Java中,如果一个方法被声明为`native`,那么这个方法的实现并不在Java代码中,而是通过JNI调用其他语言(如C/...
JNI(Java Native Interface)是Java平台的一个重要特性,它允许Java代码和其他语言写的代码进行交互。在Android开发中,JNI通常用于实现性能敏感的代码、访问操作系统特定功能或调用已有的C/C++库。本教程将深入...
- **安装 JNI++:** 下载并按照官方文档的指示进行安装。 - **升级:** 如果从早期版本升级,需要遵循特定的步骤。 - **解压分发包:** 下载的分发包需要正确解压。 - **设置环境变量:** 确保环境变量正确配置。 - **...
在Android系统中,JNI(Java Native Interface)是一个关键的组件,它允许Java代码与其他语言写的代码进行交互,比如C++。JNI在很多场景下都非常有用,例如提高性能、调用操作系统底层功能,以及本例中的读取内存...
myo-java-JNI-Library 为myo-java项目构建JNI DLL所需的C ++ / C文件。 视窗 ** MSVCP100.dll是必需的,作为VC ++的一部分安装,不确定其他方法。 ** ####需要设置几个环境变量: JAVA_HOME-指向JDK的基本安装 ...
JNI(Java Native Interface)是Java平台的一个重要特性,它允许Java代码和其他语言写的代码进行交互。在Android系统中,JNI通常用于实现Java与C/C++的交互,以便利用C/C++的高性能和低级硬件访问能力。在这个场景中...
C ++中的JNI现代接口 特征 同时支持Java方法的输入和输出参数 每个类jclass缓存,每个方法jmethodID缓存,每个字段jfieldID缓存 相同的C ++ / Java链接:静态Java成员映射到C ++中的静态成员 摆脱本地参考泄漏 任何...
《Android通过JNI控制LED灯详解》 在移动设备开发领域,Android系统以其开源性和灵活性深受开发者喜爱。然而,当涉及到与硬件直接交互时,如控制LED灯这样的底层操作,Java层往往力有未逮。此时,JNI(Java Native ...
本实验“点亮一个LED灯”是一个基础但至关重要的教学环节,它涵盖了软件开发的多个层面,包括Android应用开发、JNI(Java Native Interface)、HAL(Hardware Abstraction Layer)以及硬件驱动。 首先,我们从最...
在Android系统中,JNI(Java Native Interface)是一个关键的组件,允许Java代码和其他语言写的代码进行交互。在本文中,我们将深入探讨如何通过JNI在Android平台上控制硬件LED(Light Emitting Diode)。LED控制...
内联式JNI JNI到C ++包装器,旨在使JNI更加有用JNI功能的仅标头包装器,使从C ++执行Java代码的工作变得更轻松。 该库大量使用C ++ 11用户定义的文字,使用的最低GCC版本为4.8这是做什么用的? 最初,我使用它来实现...
JNI(Java Native Interface)是Java平台的一个重要组成部分,它允许Java代码和其他语言写的代码进行交互。NDK(Native Development Kit)是Google提供的一个用于在Android平台上开发原生代码的工具集,通常用于优化...