改章节个人在深圳游玩的时候突然想到的…这几周就有想写几篇关于android驱动的博客,所以回家到之后就奋笔疾书的写出来发布了

     这些天一直在想Android驱动框架层的实现,本文借助老罗教师的博客和现有通过过分析台湾的Jollen的mokoid 工程代码,并尝试在Android开发板上驱动一个简单的蜂鸣器,来解析Android下驱动的调用。    

 

  HAL架构由Patrick Brady (Google) 在2008 Google  I/O报告中提出的,如下图。

    android和驱动

  其实可以斟酌先编写驱动代码,然后使用NDK编译库层的代码,最后在Android应用层来直接完成对硬件驱动层的调用!

 

    先编写一个简单的蜂鸣器驱动程序,根据开发板上的硬件IO接口和Android驱动规范,在kernel中的driver目录中新建一个Buzzer文件,新建一个buzzer.c的源文件

#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/ioport.h>
#include<linux/fs.h>
#include<asm/io.h>
#include<asm/uaccess.h>

#define DRIVER_AUTHOR "canjianfantasy"
#define DRIVER_DESCRIBLE "buzzer test program"

#define BUZZER_MAJOR 248 //Device Driver Major Number
#define BUZZER_NAME "BUZZER_IO_PORT" //Device Name

#define BUZZER_DRIVER_VERSION "BUZZER IO PORT V0.1" //Device Driver Version

#define BUZZER_ADDRESS 0x88000050 //physical address 
#define BUZZER_ADDRESS_RANGE 0x1000 // I/O region  range

//Glable variable 
static int buzzer_usage = 0;  //if device is already used ?
static unsigned long *buzzer_ioremap ; //io address region


//It is called when program called open() system call

int buzzer_open(struct inode *minode,struct file *mfile)
{
	//if device is already opened 
	if(buzzer_usage != 0)
		return -EBUSY;

	//mapping physical address to virtual address
	buzzer_ioremap = ioremap(BUZZER_ADDRESS,BUZZER_ADDRESS_RANGE);

	//check if it is usable virtual address.
	if(!check_mem_region((unsigned long)buzzer_ioremao,BUZZER_ADDRESS_RANGE))
		{
			//register I/O address region
			request_mem_region((unsigned long)buzzer_ioremap,BUZZER_ADDRESS_RANGE,BUZZER_NAME);
		}
	else 	{
			printk(KERN_WARNING"Can\'t get I/O region 0x%x\n",(unsigned int)buzzer_ioremap);
		}
	buzzer_usage = 1;
	return 0;
}

//It is called when program called close() system call
int buzzer_release(struct inode *mnode,struct file *mfile)
{
	//Release mapped virtual address
	iounmap(buzzer_ioremap);

	//Release registed I/O memory region
	release_mem_region((unsigned long)buzzer_ioremap,BUZZER_ADDRESS_RANGE);

	buzzer_usage = 0;
 	return  0;

}

//It is called when program calls write() system call
size_t buzzer_write_byte(struct file *inode, const char* gdata, size_t length,
loff_t *off_what)
{
	unsigned char *addr;
	unsigned char c;

	//copy data from gdata to c 
	get_user(c,gdata);

	addr = (unsigned char *)(buzzer_ioremap);
	*addr = c;

	return length;
}

//file operations structure
static struct file_operations buzzer_fops = {
	.owner = THIS_MODULE,
	.open = buzzer_open,
	.write = buzzer_write_byte,
	.release = buzzer_release,
};


// insert module to kernel 
int buzzer_init( void )
{
	int result;
	//Register character device drvier
	result = register_chrdev(BUZZER_MAJOR,BUZZER_NAME,&buzzer_fops);
	
	if(result < 0)
	{
	//registration  failed
	printk(KERN_WARNING "Can\'t get any major \n");

	return result;
	}
	//print MAJOR_NUMBER
	printk(KERN_WARNING "Init Module ,Buzzer Major number %d \n",BUZZER_MAJOR);

	return 0 ;
}


// remove module from kernel

void buzzer_exit(void)
{

	//Unregister character device driver
	unregister_chardev(BUZZER_MAJOR,BUZZER_NAME);

	printk(KERN_INFO"driver: %s DRIVER EXIT \n",BUZZER_NAME);

}

module_init(buzzer_init);
module_exit(buzzer_exit);

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
MODULE_LICENSE("Dual BSD/GPL");
    每日一道理
俄国作家契诃夫说:“有大狗,有小狗,小狗不该因为大狗的存在而心慌意乱。所有的狗都应该叫,就让他各自用上帝给他的声音。

    
在目录下创建一个Makefile文件,文件内容如下

CC = /usr/local/arm-2009q3/bin/arm-none-linux-gnueabi-gcc

obj-m := buzzer.o

KDIR := /Android/linux-2.6.32

PWD := $(shell pwd)

default :
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD modules
	rm -f default
clean:
	rm -f *.ko
	rm -f *.o
	rm -f *.mod.*
	rm -f .*.cmd

    
先运行make clean命令清楚到编译生成的一些工程文件,执行make命令,重新编译驱动程序。将编译生成的buzzer.ko内核镜像文件拷贝出来,adb push buzzer.ko /fpga/moudles

    然后插入内核镜像文件到系统中,insmod buzzer.ko,并且装载设备驱动程序,mknod  /dev/buzzer c 248 0

    当初就能够在库层直接编写C/C++文件来调用这个驱动程序,这个可以在ubuntu中安装NDK编译环境,新建buzzer文件,编译生成一个库文件,那样就能够直接在应用层使用这个库提供的JNI方法,那样调用会显得更加的简单,当然这个调用方法google并不倡导,我在这里只是想展示这类调用方法而已

    构建一个jni工程,新建一个buzzer.c的源文件,内容如下:

#include<errno.h>

#include<android/log.h>

#define LOG_TAG "BuzzerDriver"
//#define LOGW(a) __android_log_write(ANDROID_LOG_WARN,LOG_TAG,a)
#define LOGW(a)  __android_log_write(ANDROID_LOG_WARN,LOG_TAG,a)

jint java_com_fantasy_buzzer_BuzzerActivity_BuzzerControl(JNIEnv *env,jobject thiz,jint value)
{
	int fd,ret;
	int data=value;

	fd=open("/dev/buzzer",O_WRONLY);
	
	if(fd < 0)
	  {     
		LOGW("Android Open Driver buzzer failed!");
		 return -errno;
          }

	ret=write(fd ,&data ,1);
        if(ret < 0)
	   close(fd);

	if(ret == 1)
	  return 0;

    
停止NDK编译,生成libbuzzer.so,这个库就能够直接在应用层停止调用

    android和驱动

 

 在eclipse中编写应用程序直接调用这个库,实现对底层驱动的调用!!

 主要源代码:

package com.fantasy.buzzer;
//@ canjianfantasy 2013.6.22
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;

public class BuzzerActivity extends Activity {
	Button BuzzerButton;
	int BuzzerData =0;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_buzzer);
		
//		BuzzerControl(BuzzerData);
		BuzzerButton =(Button)findViewById(R.id.On);
		
		BuzzerButton.setOnClickListener(new Button.OnClickListener() {
		
			public void onClick(View v) {
				// TODO Auto-generated method stub
				if(BuzzerData == 0){
					BuzzerData = 1;
					BuzzerButton.setText("Buzzer off");
				}
				else{
					BuzzerData = 0;
					BuzzerButton.setText("Buzzer On");
				}
//				BuzzerControl(BuzzerData);
			}
		});
		
	}
	static{
		System.loadLibrary("buzzer");
	}
	public native int BuzzerControl(int Value);
	
	@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_buzzer, menu);
		return true;
	}

}

    全部工程目录:

    android和驱动

    直接运行,在开发板上查看运行结果。。。
 

文章结束给大家分享下程序员的一些笑话语录:

大家喝的是啤酒,这时你入座了。
你给自己倒了杯可乐,这叫低配置。
你给自已倒了杯啤酒,这叫标准配置。
你给自己倒了杯茶水,这茶的颜色还跟啤酒一样,这叫木马。
你给自己倒了杯可乐,还滴了几滴醋,不仅颜色跟啤酒一样,而且不冒热气还有泡泡,这叫超级木马。
你的同事给你倒了杯白酒,这叫推荐配置。
菜过三巡,你就不跟他们客气了。
你向对面的人敬酒,这叫p2p。
你向对面的人敬酒,他回敬你,你又再敬他……,这叫tcp。
你向一桌人挨个敬酒,这叫令牌环。
你说只要是兄弟就干了这杯,这叫广播。
有一个人过来向这桌敬酒,你说不行你先过了我这关,这叫防火墙。
你的小弟们过来敬你酒,这叫一对多。
你是boss,所有人过来敬你酒,这叫服务器。
酒是一样的,可是喝酒的人是不同的。
你越喝脸越红,这叫频繁分配释放资源。
你越喝脸越白,这叫资源不释放。
你已经醉了,却说我还能喝,叫做资源额度不足。
你明明能喝,却说我已经醉了,叫做资源保留。
喝酒喝到最后的结果都一样
你突然跑向厕所,这叫捕获异常。
你在厕所吐了,反而觉得状态不错,这叫清空内存。
你在台面上吐了,觉得很惭愧,这叫程序异常。
你在boss面前吐了,觉得很害怕,这叫系统崩溃。
你吐到了boss身上,只能索性晕倒了,这叫硬件休克。

———————————
原创文章 By
android和驱动
———————————

版权声明:本文为xinyuyuanm原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/xinyuyuanm/p/3150269.html