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/目录下添加编译好的库,没有目录自己新建目录

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(Linux)控制GPIO的方法及实时性分析

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

  2. Android(Linux)控制GPIO方法二

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

  3. Android(Java)控制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.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学习(四)——JNI的常用方法的中文API

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

随机推荐

  1. Kotlin学习笔记(9)- 数据类

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步! Kotlin学习笔记(1)- 环境配置 Kotlin学习笔记(2)- 空安 ...

  2. 一个历时五天的 Bug

    一个程序员在没有成长成为架构师之前,几乎都要跟 Bug为伴,程序员有很多时间都是花在了查找各种 Bug上. 我印象深刻的一个Bug, 是一个服务器网络框架无锁队列的 Bug .那个 Bug 连续查找了 ...

  3. bzoj4987 Tree 树上背包

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4987 题解 一道还不错的题咯. 很容易发现一个结论:这 \(k\) 个点构成的一定是一个连通块 ...

  4. MySQL添加主键、索引

    查看索引  SHOW INDEX FROM  数据库表名 比如:SHOW INDEX FROM order_info; 添加索引 alter table 数据库add index 索引名称(数据库字段 ...

  5. win7系统下IIS7.5配置MVC5环境注意事项与CentOS的MVC5设置

    注意事项: 1.IIS程序应用池更换为4.0net集成 2.网站目录加入IIS帐号的权限(基本设置里是administrators组帐号)注:服务器拒绝时是这里的问题 3.在“ISAPI和CGI限制” ...

  6. 百度小程序-图片画廊-使用previewImage方法实现

    .swan <!-- 轮播图 S--> <view class="swiper-box"> <swiper style='height:{{swipe ...

  7. 【锁】synchronized的实现(偏向锁、轻量级锁、重量级锁)

    synchronized的三种应用方式 一. 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁. 二. 修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁. 三. ...

  8. 拦截Restful API的三种方式

    如题, 方式有三种. (1). 过滤器filter javaEE规范 (2). 拦截器interceptor springmvc提供 (3). 切片 aspect 一. Filter使用示例 impo ...

  9. PHP curl_multi_close函数

    curl_multi_close — 关闭一组cURL句柄 说明 void curl_multi_close ( resource $mh ) 关闭一组cURL句柄. 参数 mh 由 curl_mul ...

  10. 圆周率Pi是如何计算出来的

    object SparkPi { def main(args: Array[String]) { val spark = SparkSession .builder .appName("Sp ...