Android字符设备驱动及应用层从jni控制GPIO实战

本文详述如何通过JNI控制Android字符设备驱动GPIO,实现加密芯片的上下电功能。首先介绍GPIO驱动实现,包括配置GPIO口、解决Intel平台特殊问题。然后搭建JNI开发环境,最后展示应用层调用JNI接口的代码实现,提供完整的apk调用流程。
摘要由CSDN通过智能技术生成

 本文主要讲述从实际项目中一个GPIO口控制一个加密芯片上下电的功能,提供动态库给客户,并有Android应用层apk调用.so库文件的例子,希望能为大家字符设备驱动以及jni开发入门带来帮助!

以下描述参考摘录了别人的话:http://koliy.iteye.com/blog/1424304

android应用层要访问驱动,一般有三种方法。 
1.应用层 ---> framwork层JNI ---> 驱动c 
2.应用层 ---> framwork层JNI ---> 硬件抽象层HAL ----> 驱动c 

3.应用层-->驱动c(读写字符设备)


三种方法,各有各的好处,第1种,方便与驱动调试实验,只要编译好ko文件和libxxx.so文件,放入系统中编译好就可以立即调试了。 

第2种JNI方法有些改变和增加了HAl,对驱动有了封装,简单来讲,硬件驱动程序一方面分布在Linux内核中,另一方面分布在用户空间的硬件抽象层中。不要误会android把驱动分成两半了,其实android只是在驱动的调用接口上在增加一层对应接口功能来让framwork层JNI来调用。比如,驱动有read接口,HAl层就是封装read接口,做一个 hal_read接口,里面调用read接口,然后把hal_read接口给JNI调用。 

明白了吗?这方面有人讲得非常好,有兴趣的可以点击: 
http://blog.csdn.net/luoshengyang/article/details/6575988 
好处就是对对厂家来说能把商业秘密隐藏起来,我们做驱动实验的话,操作会极其复杂,不过对理解android整个系统都是极其用用的,因为它从下到上涉及到了android系统的硬件驱动层,硬件抽象层,运行时库和应用程序框架层等等。 

第3种涉及到Android上层读写设备节点,由于我们现在要讲的GPIO口是一个字符设备驱动,也会创建节点,所以可以通过此方法配置

这里由于客户需要我们的*.so库目前只讲第1种方法的实现:在此之前,请大家了解下JNI的编程方法,JNI是一种为JAVA和C、C++之间能互相访问所提供的编程接口(自行百度了解)

下面详细讲解开发过程(android系统大同小异),主要分为三部分:1.GPIO口字符设备驱动的实现,2.jni环境搭建及代码编写,3.应用层调用jni代码的实现

GPIO口字符设备驱动的实现
关于GPIO口字符设备驱动我们要做如下步骤:
1  找到原理图对应的GPIO口并配置它为输出管脚
gpio口配置(不同平台配置不一样)但目的是一样的 设置GPIO口输出,并默认低电平,我们接的是57管脚
<&range 56 1 0x1500>
<&range 57 1 0x1500>   代表57管脚做为gpio口使用,并默认低电平    
这个io口寄存器地址:0xe46002e4


但是调试过程中发现
#define gpio_lp 57 
gpio_request(gpio_lp,"pos_pwr");
gpio_set_value(gpio_lp,1);

GPIO调用request报错,导致GPIO不能用但是换个GPIO口后换个gpio口就不报错了,

这种原因是由于intel的特殊性:gpio在vmm的地方被调用,在kernel下就不能操作它(一般平台这样操作没问题的)

后续,想到了另外一种方法

void __iomem *ldo_mmio_base = ioremap(0xe46002e4, 4);

iowrite32(0x1700, ldo_mmio_base);   //1700代表设置寄存器(0xe46002e4)为GPIO口,输出  为高

iowrite32(0x1500, ldo_mmio_base);//1500代表设置寄存器(0xe46002e4)为GPIO口,输出 为底  

实现了IO口的控制

1.2  源代码我们放到linux-3.10/drivers/char下面让系统生成设备节点:/dev/mypos
   
 linux-3.10依据自己的kernel名字不同而不同

linux-3.10/drivers/char/lp6252_switch.c    

 
 
 
#include <linux/module.h>               /* For module specific items */  
#include <linux/moduleparam.h>          /* For new moduleparam's */  
#include <linux/types.h>                /* For standard types (like size_t) */  
#include <linux/errno.h>                /* For the -ENODEV/... values */  
#include <linux/kernel.h>               /* For printk/panic/... */  
#include <linux/fs.h>                   /* For file operations */^M  
#include <linux/ioport.h>               /* For io-port access */  
#include <linux/platform_device.h>      /* For platform_driver framework */  
#include <linux/init.h>                 /* For __init/__exit/... */  
#include <linux/uaccess.h>              /* For copy_to_user/put_user/... */  
#include <linux/io.h>                   /* For inb/outb/... */  
#include <linux/gpio.h>  
#include <linux/device.h>  
#include <linux/cdev.h>  
#include <linux/slab.h>               /*kamlloc */  
//#include <asm-generic/ioctl.h>  
   
 //ioctl 
#define CMD_FLAG  'i'  
#define POS_PWR_ON      _IOR(CMD_FLAG,0x00000001,__u32)    
#define POS_PWR_OFF     _IOR(CMD_FLAG,0x00000000,__u32) 
#define gpio_lp			57 
  
static int  major =0;  
static struct class *pos_class;  
struct cdev_pos {  
    struct cdev cdev;  
};   
struct cdev_pos *pos_dev;  
  
static int pos_ioctl(struct file* filp,unsigned int cmd,unsigned long argv)  
{  
    printk(KERN_INFO "entry kernel.... \n");  
	printk(KERN_INFO "%d\n", POS_PWR_ON);
	<span style="color:#ff0000;">void __iomem *ldo_mmio_base = ioremap(0xe46002e4, 4);</span>
  
    switch(cmd)  
    {  
        case POS_PWR_ON:  
        {  
#if 0
            gpio_set_value(gpio_lp,1);  // 
            printk(KERN_INFO "POS on\n"); 
#endif
			iowrite32(0x1700, ldo_mmio_base)
            break;  
        }  
        case POS_PWR_OFF:  
        {  
#if 0
            gpio_set_value(gpio_lp,0);
            printk(KERN_INFO "POS off \n");
#endif</span>
			iowrite32(0x1500, ldo_mmio_base);
            break;  
        }  
        default:  
            return -EINVAL;  
    }  
    return 0;  
}  
  
  
//open  
static int pos_open(struct inode* i_node,struct file* filp)  
{  
    printk(KERN_INFO "taosong open init.... \n");  
    int err; 
#if 0	
    err = gpio_request(gpio_lp,"pos_pwr");
    if(err<0)  
    {  
        printk(KERN_INFO "gpio request faile \n");  
        return err;  
    }  
    gpio_direction_output(gpio_lp,1);
 #endif
    return 0;  
}  
  
//close  
static void pos_close(struct inode* i_node,struct file* filp)  
{  
printk(KERN_INFO "taosong close init \n");
#if 0  
    gpio_free(gpio_lp); 
#endif
    return ;  
}  
  
/* file operations */  
struct file_operations fops={  
    .owner  = THIS_MODULE,  
    .open   = pos_open,  
    .unlocked_ioctl = pos_ioctl, 
    .release= pos_close,  
};  
  
static int __init pos_init(void)  
{  
printk(KERN_INFO "init .... \n");  
    dev_t dev_no;  
    int result,err;  
    err = alloc_chrdev_region(&dev_no,0,1,"my_pos"); //dynamic request device number  
    if(err<0)  
    {  
        printk(KERN_INFO "ERROR\n");  
        return err;  
    }  
    major = MAJOR(dev_no);  
    pos_dev = kmalloc(sizeof(struct cdev_pos),GFP_KERNEL);  
    if(!pos_dev)  
    {  
        result = -ENOMEM;  
        goto fail_malloc;  
    }  
    memset(pos_dev,0,sizeof(pos_dev));  
      
    cdev_init(&pos_dev->cdev,&fops);  
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值