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

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

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

其实可以斟酌先编写驱动代码,然后使用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,这个库就能够直接在应用层停止调用

在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;
} }

全部工程目录:

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

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

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

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

android驱动[置顶] 我的DIY Android之旅--驱动并控制你的Android开发板蜂鸣器的更多相关文章

  1. [置顶] 自娱自乐1之Linux UDC驱动(形式模板)

    首先,我不是做驱动的开发人员.所以只能用自娱自乐来表示我的行为. 我不知道udc和gadget驱动是不是冷门的驱动,资料真是不多.我之前买了一本书,上面说到这些,就教你如何调试已写好的驱动.这样也可以 ...

  2. [置顶] 自娱自乐7之Linux UDC驱动2(自编udc驱动,现完成枚举过程,从驱动代码分析枚举过程)

    花了半个月,才搞定驱动中的枚举部分,现在说linux的枚举,windows可能有差别. 代码我会贴在后面,现在只是实现枚举,你可能对代码不感兴趣,我就不分析代码了,你可以看看 在<自娱自乐1&g ...

  3. [置顶] 自娱自乐6之Linux gadget驱动5(自编gadget驱动,包涵与之通讯的主机usb驱动,已调试通过)

    这个代码调试,你首先要保证你的udc驱动没用问题,这个有些矛盾,应为我本来要用gadget驱动来调试udc驱动,结果反过来了. 这是在zero基础改的,大概的改动 1. 去掉loop. 2. sink ...

  4. RecyclerView实现侧滑删除、置顶、滑动

    1.首先在build.gradle里添加 compile 'com.github.mcxtzhang:SwipeDelMenuLayout:V1.2.1' 2.设置recyclerView的item布 ...

  5. iTOP-iMX6开发板Android系统下LVDS和HDMI双屏异显方法

    迅为iMX6 开发板 android 系统下 LVDS 和 HDMI 双屏异显的使用过程. 注意,iTOP-iMX6 开发板的 android 系统想要实现对 LVDS 和 HDMI 双屏异显功能的支 ...

  6. Digispark(ATTINY85) 微型开发板驱动安装与开发环境配置教程

    前几天无聊就弄了弄这个玩,网上教程可能有点杂,在这里就总结一下. Digispark开发板(也就是badusb)能干什么,自己搜去,/坏笑. 1.准备材料:Attiny85微型 USB接口开发板 Di ...

  7. Android自定义ScrollView实现一键置顶功能

    效果图如下: (ps:动态图有太大了,上传不了,就给大家口述一下要实现的功能吧) 要实现的功能:当ScrollView向上滑动超过一定距离后,就渐变的出现一个置顶的按钮,当滑动距离小于我们指定的距离时 ...

  8. Android的SwipeToDismiss第三方开源框架模拟QQ对话列表侧滑删除,置顶,将头像图片圆形化处理。

      <Android SwipeToDismiss:左右滑动删除ListView条目Item> Android的SwipeToDismiss是github上一个第三方开源框架(github ...

  9. android linearlayout imageview置顶摆放

    在练习android时,想在Linearlayout内放一图片,使其图片置顶,预期效果是这样的: 但xml代码imageview写成这样后, <ImageView android:layout_ ...

随机推荐

  1. OSI模型七层模型结构

    OSI模型,即开放式通信系统互联参考模型(Open System Interconnection,OSI/RM,Open Systems Interconnection Reference Model ...

  2. 将OutLook.exe注册为服务,让其一直保持开启状态

    类似于TaobaoProtect.exe是由TBSecSvc服务启动的 http://stackoverflow.com/questions/3582108/create-windows-servic ...

  3. Windows 8 自带定时关机的4种实现方法

    问题描述:前几天发布了一篇文章[ Windows 7/8 自带定时关机命令 ],文章中的用到的命令我在Windows 7都运行成功,但没有在Windows 8 上进行测试,因为我认为Windows 8 ...

  4. win设置壁纸

    默认壁纸图片位置: C:\Windows\Web\Wallpaper\Scenes 你可以自己建文件夹,放自己喜欢的桌面壁纸. 设置壁纸: 桌面右键  ->  个性化 然后点击 “桌面背景” - ...

  5. BZOJ3258: 秘密任务

    题解: 其实就是一个简单的最小割判断是否唯一解... 可是我写了一上午还没过...T_T 把1-n的最短路上的边提出来做最小割. 然后从s,t分别bfs判断必须在某个割的点.如果有的点没有被bfs到, ...

  6. LeetCode Product of Array Except Self (除自身外序列之积)

    题意:给一个序列nums,要求返回一个序列ans,两序列元素个数相同,ans第i个元素就是除了nums[i]之外所有的数相乘之积. 思路:时间O(n),额外空间O(0). 第一次扫一遍,处理nums[ ...

  7. Java中的volatile

    关于volatile 在JVM 1.2之前,Java的内存模型实现总是从主存读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程环境下 volatile关键字的使用变得非常重要. ...

  8. 《C#并行编程高级教程》第9章 异步编程模型 笔记

    这个章节我个人感觉意义不大,使用现有的APM(异步编程模型)和EAP(基于时间的异步模型)就很够用了,针对WPF和WinForm其实还有一些专门用于UI更新的类. 但是出于完整性,还是将一下怎么使用. ...

  9. HTML.ActionLink 和 Url.Action 的区别

    html.ActionLink生成一个<a href=".."></a>标记.而Url.Action只返回一个url.例如:@Html.ActionLink ...

  10. 【原创】使用Nmon_Analyzer处理较大nmon文件的方法

    1 编写目的 进行性能测试时,测试服务器使用的操作系统是Linux或Unix时,我们一般会使用Nmon工具进行操作系统资源监控数据的收集.Nmon工具是一款非常优秀的性能监控和分析工具,它能够实时地收 ...