我的DIY Android之旅--驱动并控制你的Android开发板蜂鸣器
来源:互联网 发布:知乎我是歌手林俊杰 编辑:程序博客网 时间:2024/05/16 03:18
这些天一直在想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 callint buzzer_open(struct inode *minode,struct file *mfile){//if device is already opened if(buzzer_usage != 0)return -EBUSY;//mapping physical address to virtual addressbuzzer_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 regionrequest_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 callint buzzer_release(struct inode *mnode,struct file *mfile){//Release mapped virtual addressiounmap(buzzer_ioremap);//Release registed I/O memory regionrelease_mem_region((unsigned long)buzzer_ioremap,BUZZER_ADDRESS_RANGE);buzzer_usage = 0; return 0;}//It is called when program calls write() system callsize_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 structurestatic 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 drvierresult = register_chrdev(BUZZER_MAJOR,BUZZER_NAME,&buzzer_fops);if(result < 0){//registration failedprintk(KERN_WARNING "Can't get any major \n");return result;}//print MAJOR_NUMBERprintk(KERN_WARNING "Init Module ,Buzzer Major number %d \n",BUZZER_MAJOR);return 0 ;}// remove module from kernelvoid buzzer_exit(void){//Unregister character device driverunregister_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-gccobj-m := buzzer.oKDIR := /Android/linux-2.6.32PWD := $(shell pwd)default :$(MAKE) -C $(KDIR) SUBDIRS=$(PWD modulesrm -f defaultclean:rm -f *.korm -f *.orm -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.22import 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;@Overrideprotected 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 stubif(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);@Overridepublic 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;}}
整个工程目录:
直接运行,在开发板上查看运行结果。。。
- 我的DIY Android之旅--驱动并控制你的Android开发板蜂鸣器
- 我的DIY Android之旅--下载编译并运行你的Android内核
- 我的DIY Android之旅--单独改造你的Android模块
- 我的DIY Android之旅--Android应用层APP调用底层驱动实例(辛酸历程实记)
- 我的DIY Android之旅--Android2.3源码初识
- 友善之臂4412开发板android应用层通过jni直接控制除LED、蜂鸣器外的其它IO口,系统直接重启问题
- linux驱动开发之路(三)——嵌入式 Linux 的蜂鸣器控制实验(misc设备)
- 我的DIY Android之旅--在(32位)ubuntu11.04编译运行Android2.3.源码
- 我的DIY Android 之旅--gps框架及简析
- 飞凌Fl2440开发板蜂鸣器pwm的驱动
- 基于S3C2440芯片的蜂鸣器驱动开发
- 基于fl2440开发板的按键以及蜂鸣器控制
- 驱动蜂鸣器的实验
- 我的Android开发之旅《1》
- tiny4412开发板蜂鸣器驱动
- 我的android开发之旅 1、关于android
- 我的Android进阶之旅------>Android开发错误汇总
- android驱动的开发
- 关于编写高性能服务器的资料汇总(Linux)
- java:struts.xml配置解析
- 对数组的操作(群里提出的一些问题)
- 学习笔记之arraylist限定初始容量的实际size
- android系统中自带的各种图标
- 我的DIY Android之旅--驱动并控制你的Android开发板蜂鸣器
- 关于JS获取select值的两种实现方法
- T400 修改显卡选项设置
- sencha touch 压缩js,css遇到的问题
- SQL server 2005服务启动不了
- 如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态答
- 软件工程导论实验报告
- kmp next函数 kmp的周期问题,深入了解kmp中next的原理(kmp)
- ant的配置及使用