android jni控制gpio (rk3288)

时间:2023-01-01 23:02:49

1.添加驱动程序

2.编写jni c程序编译为库给java调用

3.app调用jni静态链接库操作底层驱动

 1.添加驱动程序

 修改/work/rk3288/firefly-rk3288_android5.1_git_20180126/kernel/drivers/Makefile
    添加一行obj-y     += carroll/
    
    将carroll文件夹添加至此目录下/work/rk3288/firefly-rk3288_android5.1_git_20180126/kernel/drivers/
    文件夹包含驱动源码及Makefile
    # carroll
    obj-y        = test_led.o

 test_led.源码

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#endif #include <linux/fb.h>
#include <linux/device.h>
#include <linux/miscdevice.h> #define INVALID_GPIO -1
int led1_gpio = INVALID_GPIO;
int led2_gpio = INVALID_GPIO;
int led_gpio_active = ; static int led_open(struct inode *inode, struct file *file)
{
printk("carroll led_open ok \n"); return ;
} static int led_release(struct inode *inode, struct file *file)
{
printk("carroll led_close \n"); return ;
} /* app : ioctl(fd, cmd, arg) */
static long led_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
/* 根据传入的参数设置GPIO */
/* cmd : 0-off, 1-on */
/* arg : 0-1, which led */ if ((cmd != ) && (cmd != ))
return -EINVAL; if (arg > )
return -EINVAL; if(arg == )
{
if(led1_gpio != INVALID_GPIO)
gpio_set_value(led1_gpio, !cmd);
}
else if(arg == )
{
if(led2_gpio != INVALID_GPIO)
gpio_set_value(led2_gpio, !cmd);
} printk("carroll led_ioctl: %d \n", cmd); return ;
} static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.release = led_release,
.unlocked_ioctl = led_ioctl,
}; static struct miscdevice led_dev =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "test_led",
.fops = &led_fops,
}; static int firefly_led_probe(struct platform_device *pdev)
{
int ret = -;
enum of_gpio_flags flags;
struct device_node *hello_node = pdev->dev.of_node; printk("%s-%d: carroll \n",__FUNCTION__,__LINE__); /* register test_led dev file */
ret = misc_register(&led_dev);
if (ret < ){
printk("carroll led register err!\n");
return ret;
} /* led1 init */
led1_gpio = of_get_named_gpio_flags(hello_node,"led1", ,&flags);
if (!gpio_is_valid(led1_gpio)){
printk("carroll: invalid gpio : %d\n",led1_gpio);
return -;
}
ret = gpio_request(led1_gpio, "test_led");
if (ret != ) {
gpio_free(led1_gpio);
printk("carroll: led1_gpio free\n");
return -EIO;
}
gpio_direction_output(led1_gpio, !led_gpio_active); /* led2 init */
led2_gpio = of_get_named_gpio_flags(hello_node,"led2", ,&flags);
if (!gpio_is_valid(led2_gpio)){
printk("carroll: invalid gpio : %d\n",led2_gpio);
return -;
}
ret = gpio_request(led2_gpio, "test_led");
if (ret != ) {
gpio_free(led2_gpio);
printk("carroll: led2_gpio free\n");
return -EIO;
}
gpio_direction_output(led2_gpio, !led_gpio_active); gpio_set_value(led1_gpio, led_gpio_active);
gpio_set_value(led2_gpio, led_gpio_active);
mdelay();
gpio_set_value(led1_gpio, !led_gpio_active);
gpio_set_value(led2_gpio, !led_gpio_active); return ; //return Ok
} static int firefly_led_remove(struct platform_device *pdev)
{
return ;
} #ifdef CONFIG_OF
static const struct of_device_id of_firefly_led_match[] = {
{ .compatible = "firefly,test_led" },
{ /* Sentinel */ }
};
#endif static struct platform_driver firefly_led_driver = {
.probe = firefly_led_probe,
.remove = firefly_led_remove,
.driver = {
.name = "test_led",
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = of_firefly_led_match,
#endif
}, }; static int major;
static struct class *cls; static int __init led_init(void)
{
printk(KERN_INFO "carroll register led dev %s\n", __FUNCTION__); return platform_driver_register(&firefly_led_driver);
} static void __exit led_exit(void)
{
platform_driver_unregister(&firefly_led_driver);
printk(KERN_INFO "carroll unregister led dev %s\n", __FUNCTION__);
} subsys_initcall(led_init);
module_exit(led_exit); MODULE_AUTHOR("carroll <1247627668@qq.com>");
MODULE_DESCRIPTION("carroll led driver");
MODULE_LICENSE("GPL");

  

修改/work/rk3288/firefly-rk3288_android5.1_git_20180126/kernel/arch/arm/boot/dts/firefly-rk3288.dts
    firefly-led{
        compatible = "firefly,led";
        led-work = <&gpio8 GPIO_A2 GPIO_ACTIVE_LOW>;
        led-power = <&gpio8 GPIO_A1 GPIO_ACTIVE_LOW>;
        //carrol add start
        status = "disabled";
    };

test-led{
        compatible = "firefly,test_led";
        led1= <&gpio8 GPIO_A1 GPIO_ACTIVE_LOW>;
        led2= <&gpio8 GPIO_A2 GPIO_ACTIVE_LOW>;
        status = "okay";
    };
        //carrol add end
    编译内核烧录即可

 内核启动过程中闪烁一次,并产生/dev/test_led文件
    添加可执行权限
    su
    chmod 777 /dev/test_led

2.编写jni c程序编译为库给java调用

  hardcontrol.c源码

#include <jni.h>  /* /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h> #include <android/log.h> /* liblog */ //__android_log_print(ANDROID_LOG_DEBUG, "JNIDemo", "native add ..."); #if 0
typedef struct {
char *name; /* Java里调用的函数名 */
char *signature; /* JNI字段描述符, 用来表示Java里调用的函数的参数和返回值类型 */
void *fnPtr; /* C语言实现的本地函数 */
} JNINativeMethod;
#endif static jint fd; jint ledOpen(JNIEnv *env, jobject cls)
{
fd = open("/dev/test_led", O_RDWR);
__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledOpen /dev/test_led: %d", fd);
if (fd >= )
return ;
else
return -;
} void ledClose(JNIEnv *env, jobject cls)
{
__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledClose ...");
close(fd);
} jint ledCtrl(JNIEnv *env, jobject cls, jint which, jint status)
{
int ret = ioctl(fd, status, which);
__android_log_print(ANDROID_LOG_DEBUG, "LEDDemo", "native ledCtrl : %d, %d, %d", which, status, ret);
return ret;
} static const JNINativeMethod methods[] = {
{"ledOpen", "()I", (void *)ledOpen},
{"ledClose", "()V", (void *)ledClose},
{"ledCtrl", "(II)I", (void *)ledCtrl},
}; /* System.loadLibrary */
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *jvm, void *reserved)
{
JNIEnv *env;
jclass cls; if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {
return JNI_ERR; /* JNI version not supported */
}
cls = (*env)->FindClass(env, "com/thisway/hardlibrary/HardControl");
if (cls == NULL) {
return JNI_ERR;
} /* 2. map java hello <-->c c_hello */
if ((*env)->RegisterNatives(env, cls, methods, sizeof(methods)/sizeof(methods[])) < )
return JNI_ERR; return JNI_VERSION_1_4;
}

根据rk3288 android5.1 linux3.1编译库,必须使用arm-linux-gcc库(也可采用android studio cmake或ndk编译)

  arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.-openjdk-amd64/include/  -nostdlib /work/rk3288/firefly-rk3288_android5.1_git_20180126/prebuilts/ndk//platforms/android-/arch-arm/usr/lib/libc.so  -I /work/rk3288/firefly-rk3288_android5.1_git_20180126/prebuilts/ndk//platforms/android-/arch-arm/usr/include  /work/rk3288/firefly-rk3288_android5.1_git_20180126/prebuilts/ndk//platforms/android-/arch-arm/usr/lib/liblog.so

没有安装arm-linux-gcc的可以按照以下方法

安装交叉编译工具

    sudo tar xvzf arm-linux-gcc-4.5.-v6-vfp-.tgz -C /

    注意: C 后面有个空格,并且 C 是大写的,它是英文单词“ Change”的第一个字母,在此 是改变目录的意思。
执行该命令,将把 arm-linux-gcc 安装到/opt/FriendlyARM/toolschain/4.5. 目录。 Step2:把编译器路径加入系统环境变量,运行命令
sudo gedit ~/.bashrc
编辑 /root/.bashrc 文件, 注意“bashrc”前面有一个“.”,修改最后一行为
export PATH=$PATH:/opt/FriendlyARM/toolschain/4.5./bin
注意路径一定要写对,否则将不会有效。
如图,保存退出

编译产生libhardcontrol.so库文件,app将会使用到

3.app调用jni静态链接库操作底层驱动

android app包结构必须相同,上边jni程序已经指定class名为 "com/thisway/hardlibrary/HardControl",

在app/libs/armeabi/目录下添加编译好的库,没有目录自己新建目录

android jni控制gpio (rk3288)

MainActivity.java

package com.thisway.app_0001_leddemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.view.View;
import android.widget.CheckBox;
import android.widget.Toast;
import com.thisway.hardlibrary.*; public class MainActivity extends AppCompatActivity { private boolean ledon = false;
private Button button = null;
private CheckBox checkBoxLed1 = null;
private CheckBox checkBoxLed2 = null;
private CheckBox checkBoxLed3 = null;
private CheckBox checkBoxLed4 = null; class MyButtonListener implements View.OnClickListener {
@Override
public void onClick(View v) {
ledon = !ledon;
if (ledon) {
button.setText("ALL OFF");
checkBoxLed1.setChecked(true);
checkBoxLed2.setChecked(true);
checkBoxLed3.setChecked(true);
checkBoxLed4.setChecked(true); for (int i = 0; i < 4; i++)
HardControl.ledCtrl(i, 1);
}
else {
button.setText("ALL ON");
checkBoxLed1.setChecked(false);
checkBoxLed2.setChecked(false);
checkBoxLed3.setChecked(false);
checkBoxLed4.setChecked(false); for (int i = 0; i < 4; i++)
HardControl.ledCtrl(i, 0);
}
}
} public void onCheckboxClicked(View view) {
// Is the view now checked?
boolean checked = ((CheckBox) view).isChecked(); // Check which checkbox was clicked
switch(view.getId()) {
case R.id.LED1:
if (checked) {
// Put some meat on the sandwich
Toast.makeText(getApplicationContext(), "LED1 on", Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(0, 1);
}
else {
// Remove the meat
Toast.makeText(getApplicationContext(), "LED1 off", Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(0, 0);
}
break;
case R.id.LED2:
if (checked) {
// Put some meat on the sandwich
Toast.makeText(getApplicationContext(), "LED2 on", Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(1, 1);
}
else {
// Remove the meat
Toast.makeText(getApplicationContext(), "LED2 off", Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(1, 0);
}
break; case R.id.LED3:
if (checked) {
// Put some meat on the sandwich
Toast.makeText(getApplicationContext(), "LED3 on", Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(2, 1);
}
else {
// Remove the meat
Toast.makeText(getApplicationContext(), "LED3 off", Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(2, 0);
}
break; case R.id.LED4:
if (checked) {
// Put some meat on the sandwich
Toast.makeText(getApplicationContext(), "LED4 on", Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(3, 1);
}
else {
// Remove the meat
Toast.makeText(getApplicationContext(), "LED4 off", Toast.LENGTH_SHORT).show();
HardControl.ledCtrl(3, 0);
}
break;
// TODO: Veggie sandwich
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.BUTTON); HardControl.ledOpen(); checkBoxLed1 = (CheckBox) findViewById(R.id.LED1);
checkBoxLed2 = (CheckBox) findViewById(R.id.LED2);
checkBoxLed3 = (CheckBox) findViewById(R.id.LED3);
checkBoxLed4 = (CheckBox) findViewById(R.id.LED4); button.setOnClickListener(new MyButtonListener());
/*
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
ledon = !ledon;
if (ledon)
button.setText("ALL OFF");
else
button.setText("ALL ON");
}
});
*/
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId(); //noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
} return super.onOptionsItemSelected(item);
}
}

HardControl.java

package com.thisway.hardlibrary;

public class HardControl {
public static native int ledCtrl(int which, int status);
public static native int ledOpen();
public static native void ledClose(); static {
try {
System.loadLibrary("hardcontrol");
} catch (Exception e) {
e.printStackTrace();
}
}
}

然后就可通过app控制两个gpio

android jni控制gpio (rk3288)的更多相关文章

  1. Android&lpar;Linux&rpar;控制GPIO的方法及实时性分析

    Linux下控制GPIO的方法有N种,详细请参考<RPi GPIO Code Samples>,文中用十多种语言演示了如何控制GPIO,非常全面详尽.因此,这里不再多做赘述,仅把调试过程中 ...

  2. Android&lpar;Linux&rpar;控制GPIO方法二

    前文<Android(Linux)控制GPIO的方法及实时性分析>主要使用Linux shell命令控制GPIO,该方法可在调试过程中快速确定GPIO硬件是否有问题,即对应的GPIO是否受 ...

  3. Android&lpar;Java&rpar;控制GPIO的方法及耗时分析

    前面两篇分别介绍了通过脚本和C代码读写/sys/class/gpio以控制GPIO.实际项目调试时经常还需要在Java代码里控制GPIO,其实现与C代码类似,唯一不同是Android权限.本文重点介绍 ...

  4. android JNI调用(转)

    Android jni开发资料--NDK环境搭建 android开发人员注意了 谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,如果使用的NDK是r7之前的版本,必须要安装Cygwi ...

  5. android JNI 简单demo(2)它JNI demo 写

    android JNI 简单demo(2)它JNI demo 写 一.搭建Cygwin 环境:http://blog.csdn.net/androidolblog/article/details/25 ...

  6. android jni——helloworld

    看了网上好多牛人写的学习系列都是用HelloWorld作为开始,我们这里也用HelloWorld来开始我们的学习,首先我们来介绍下JNI吧. JNI作为java代码和C/C++的桥梁而存在的,为了让j ...

  7. Android JNI的Android&period;mk文件语法详解

    Android.mk简介: Android.mk文件用来告知NDK Build 系统关于Source的信息. Android.mk将是GNU Makefile的一部分,且将被Build System解 ...

  8. rk3128 通过串口控制 GPIO

    2019-04-24 关键字: rk平台控制GPIO功能.rk串口控制引脚电平 本篇文章介绍了如何通过串口来控制 RK3128.RK3288 平台的 GPIO . 我们可以很便捷地通过串口命令来控制 ...

  9. Android JNI学习&lpar;四&rpar;——JNI的常用方法的中文API

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...

随机推荐

  1. jQuery ClockPicker 圆形时钟

    ClockPicker.js是一款时钟插件,其实还可以改进,里面的分可以改成短横线. 在线实例 实例预览  jQuery ClockPicker 圆形时钟 使用方法 <div class=&qu ...

  2. (原创)JAVA多线程一传统多线程

    一,多线程 多线程是提高程序效率,避免资源浪费的很好的解决方案,下面来慢慢的介绍多线程的一些基本知识,而这些是晋级高级不可或缺的一部分 1,Thread类 类实现多线程需要实现Runnable接口,我 ...

  3. C 封装一个简单二叉树基库

    引文 今天分享一个喜欢佩服的伟人,应该算人类文明极大突破者.收藏过一张纸币类型如下 那我们继续科普一段关于他的简介 '高斯有些孤傲,但令人惊奇的是,他春风得意地度过了中产阶级的一生,而  没有遭受到冷 ...

  4. hdu 3572 Task Schedule(最大流)2010 ACM-ICPC Multi-University Training Contest(13)——Host by UESTC

    题意: 告诉我们有m个任务和k个机器.第i个任务需要ci天完成,最早从第ai天开始,最晚在第bi天结束.每台机器每天可以执行一个任务.问,是否可以将所有的任务都按时完成? 输入: 首行输入一个整数t, ...

  5. Part 6 AngularJS ng repeat directive

    ng-repeat is similar to foreach loop in C#. Let us understand this with an example. Here is what we ...

  6. android登陆接口调试

    最近项目要开始调API,于是自己写了个关于登陆界面调试的Demo,为了保护项目,接口文档里面的内容都是被我改过的,不涉及任何项目内容.当然,代码在运行成功后,上传至博客前,相应内容我也根据改过后的文档 ...

  7. QT 报错:Project ERROR&colon; Xcode not set up properly&period; You may need to confirm the license agreement by running &sol;usr&sol;bin&sol;xcodebuild&period;

    1.打开终端,输入指令并按回车键: sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer 2.如果电脑设置有密码,终 ...

  8. Wcf host

    Uri baseAddress = new Uri(uri);//var binding = new WebHttpBinding(WebHttpSecurityMode.None); var bas ...

  9. 【双目备课】《学习OpenCV第18章》相机模型与标定整编

    一.相机模型 针孔模型.在这个简单模型中,想象光线是从场景或一个很远的物体发射过来的,但只有一条光线从该场景中的任意特定点进入针孔. 我们将这个图像进行抽象,就能够得到这样的结果: 其中,f为像到针孔 ...

  10. 注入攻击&lpar;SQL注入&rpar;

    注入攻击是web安全领域中一种最为常见的攻击方式.注入攻击的本质,就是把用户输入的数据当做代码执行.这里有两个关键条件,第一是用户能够控制输入,第二个就是原本程序要执行的代码,将用户输入的数据进行了拼 ...