TQ210搭载Android4.0.3系统构建之BEEP从驱动到HAL到JNI到应用程序(驱动篇)

发布者:BlissfulBliss最新更新时间:2025-02-14 来源: cnblogs关键字:TQ210  BEEP  驱动 手机看文章 扫描二维码
随时随地手机看文章

上篇LED的驱动程序编写采用混杂设备的方式,此篇Beep的驱动程序的编写采用platform设备驱动,并对platform的机制做个简单的分析。


先看硬件电路图

通过一个NPN的三极管控制BUZZER,因为BUZZER是直流电压式驱动,需要三级管提供的放大电流才能发声, 所以只要三极管导通,给XpwmTOUT1高电平,BUZZER即可发声。


platform_device的编写


  beep_under_device.c


#include

#include

#include

#include

#include



static struct resource ress[]=  //设备拥有的资源

{

[0]={

.start=S5PV210_GPD0(1),

.end=S5PV210_GPD0(1),

.flags=IORESOURCE_IO,

}

};


static void beep_release(struct device *dev)

{


}


static struct platform_device platform_device_beep_under=  //platform设备

{

.name='beep_under',  //platform_device 与platform_driver下的driver->name进行匹配

.id=-1,

.num_resources=ARRAY_SIZE(ress),

.resource=ress,

.dev={

.release=beep_release,

},

};


static int __init beep_init(void)  //模块加载初始化

{

int ret=platform_device_register(&platform_device_beep_under);

if(ret==0) printk(KERN_INFO 'platform device beep _init success.n');

else printk(KERN_INFO 'platform device beep _init failed.n');

return ret;

}


static void __exit beep_exit(void)  //模块卸载

{

platform_device_unregister(&platform_device_beep_under);

printk(KERN_INFO 'platform device beep _exit success.n');

}








module_init(beep_init);

module_exit(beep_exit);

MODULE_LICENSE('GPL');


platform_device的Makefile文件


obj-m :=beep_under_device.o


KERNELDIR :=~/java/Kernel_3.0.8_TQ210_for_Android_v1.0/

PWD :=$(shell pwd)


build:kernel_module

kernel_module:

make -C $(KERNELDIR) M=$(PWD) modules

clean:

make -C $(KERNELDIR) M=$(PWD) clean




platform_driver的编写


beep_under_driver.c


#include    

#include

#include

#include

#include

#include

#include


#define DEVICE_NAME 'beep_unders'  //设备文件名

#define BEEP_ON 1   //蜂鸣器发声

#define BEEP_OFF 0

int major;  //主设备号

unsigned long port_beep; //蜂鸣器端口


static struct class *cls;//用于建立class 给device_create使用,让udev自动建立设备文件节点




static int beep_open(struct inode *inode,struct file *file)  //蜂鸣器打开

{

s3c_gpio_cfgpin(port_beep, S3C_GPIO_SFN(1)); //设置引脚为输出

gpio_direction_output(port_beep, 0); //设置引脚输出为0

printk(KERN_INFO 'beep_open success.n');

return 0;

}


static long beep_ictl(struct file *file,unsigned int cmd, unsigned long arg)  //蜂鸣器控制函数

{

switch(cmd)

{

case BEEP_ON:

gpio_direction_output(port_beep, BEEP_ON); //设置引脚输出为1

break;

case BEEP_OFF:

gpio_direction_output(port_beep, BEEP_OFF); //设置引脚为0

break;

}

return 0;

}


struct file_operations fops=   //驱动的文件操作

{

.owner=THIS_MODULE,

.open=beep_open,

.unlocked_ioctl=beep_ictl,

};




static int beep_probe(struct platform_device *pdev)  //蜂鸣器探针函数

{

struct resource *res;  //存储pdev中的设备资源

res=platform_get_resource(pdev,IORESOURCE_IO, 0); //获取到pdev中的资源

if(res==NULL) { printk(KERN_INFO 'can not get the resource.n'); return -1;}

port_beep=res->start;  //获取到控制beep的端口

major=register_chrdev(0, DEVICE_NAME, &fops); //注册字符设备,分配主设备号,添加到chrdev数组中

cls=class_create(THIS_MODULE, 'beep_under_class');  //创建类cls

device_create(cls, NULL, MKDEV(major,0), NULL, DEVICE_NAME);  //创建设备节点

return 0;

}


static int beep_remove(struct platform_device *pdev)  //蜂鸣器删除函数

{

device_destroy(cls, MKDEV(major,0));  //删除设备节点

class_destroy(cls);   //删除类

unregister_chrdev(major, DEVICE_NAME); //卸载字符设备

return 0;

}


struct platform_driver platform_driver_beep_under=  //蜂鸣器平台驱动

{

.probe=beep_probe,

.remove=beep_remove,

.driver={

.name='beep_under',  //驱动名称

},

};


static int __init beep_under_init(void)  //蜂鸣器初始化函数

{

int ret=platform_driver_register(&platform_driver_beep_under);  //注册platform_driver

if(ret==0) printk(KERN_INFO 'beep_under_init success.n');  //判断是否成功注册

else printk(KERN_INFO 'beep_under_init failed.n');

return ret;

}


static void __exit beep_under_exit(void)  //蜂鸣器卸载函数

{

platform_driver_unregister(&platform_driver_beep_under); //卸载platform_driver

printk(KERN_INFO 'beep_under_exit success.n');

}



module_init(beep_under_init);

module_exit(beep_under_exit);

MODULE_LICENSE('GPL');


platform_driver的Makefile编写

obj-m :=beep_under_driver.o


KERNELDIR :=~/java/Kernel_3.0.8_TQ210_for_Android_v1.0/

PWD :=$(shell pwd)


build:kernel_module

kernel_module:

make -C $(KERNELDIR) M=$(PWD) modules

clean:

make -C $(KERNELDIR) M=$(PWD) clean


最后是测试文件的编写

beep_under_test.c


#include

#include

#include

#include



#define DEVICE_NAME '/dev/beep_unders'

#define BEEP_ON 1

#define BEEP_OFF 0


int main(void)

{

       int fd;

   fd=open(DEVICE_NAME,O_RDWR);

   if(fd<0) { printf('can not open fd.n'); }

   ioctl(fd,BEEP_ON,1);

sleep(2);

    ioctl(fd,BEEP_OFF,1);

          close(fd);

  return 0;

}


测试文件的编译文件Android.mk

LOCAL_PATH :=$(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS :=eng

LOCAL_SRC_FILES :=beep_under_test.c

LOCAL_MODULE :=beep_test

LOCAL_MODULE_PATH :=$(LOCAL_PATH)

include $(BUILD_EXECUTABLE)


platform设备模型---个人理解 

  platform_device与platform_driver通过共同的name字段,即platform_device->name与platform_driver->driver->name字段,在platform_bus_type的努力下(也就是platform_bus_type的match函数),匹配在一起(实际上,追踪platform_driver_register的源代码就会发现,最终的匹配函数是在really_probe里面,有三条语句,



dev->driver = drv;

drv->probe(dev);

driver_bound(dev);

)。


上诉代码的第一条语句就是将驱动绑定在了dev上,第二条语句就是调用驱动drv的probe函数(其实也就是platform_driver的probe函数,也就是我们自己编写的probe函数,例如上面驱动代码里面的beep_probe,实现字符设备的创建与注册,设备文件的创建与注册),第三条语句就是将设备dev绑定在驱动drv上。


这里面还有一点我觉得还是有些疑问的,可能我的水平不够,


就是platform_device的name字段与device_create时 的设备name字段可以不相同,就是说platform_device与platform_driver相互绑定的name字段与我在/dev/下面所建的设备名可以不一样。正如上面缩写的,platform_device与platform_driver绑定的时候使用的是beep_under,而创建设备文件的时候,使用的确实beep_unders,但是是没问题的。


对于这个问题,我接着查看源码,发现device_create创建的时候是会向sysfs注册的,而platform_device_register是不会向sysfs注册,但是platform_device与/dev/beep_unders 这两个设备之间有什么关系呢?我还是没搞懂,或者说platform_device只是单纯的为platform_driver提供资源,而/dev/beep_unders是用来操作的。嗯,还是不懂了。


关键字:TQ210  BEEP  驱动 引用地址:TQ210搭载Android4.0.3系统构建之BEEP从驱动到HAL到JNI到应用程序(驱动篇)

上一篇:TQ210搭载Android4.0.3系统构建之LED从驱动到HAL到JNI到应用程序(总结篇)
下一篇:TQ210搭载Android4.0.3系统构建之BEEP从驱动到HAL到JNI到应用程序(HAL篇)

推荐阅读最新更新时间:2026-03-20 12:18

TQ210搭载Android4.0.3系统构建之BEEP驱动到HAL到JNI到应用程序(驱动篇)
上篇LED的驱动程序编写采用混杂设备的方式,此篇Beep的驱动程序的编写采用platform设备驱动,并对platform的机制做个简单的分析。 先看硬件电路图 通过一个NPN的三极管控制BUZZER,因为BUZZER是直流电压式驱动,需要三级管提供的放大电流才能发声, 所以只要三极管导通,给XpwmTOUT1高电平,BUZZER即可发声。 platform_device的编写 beep_under_device.c #include linux/module.h #include linux/init.h #include linux/printk.h #include linux/platform_
[单片机]
<font color='red'>TQ210</font>搭载Android4.0.3<font color='red'>系统</font>构建之<font color='red'>BEEP</font>从<font color='red'>驱动</font>到HAL到JNI到应用程序(<font color='red'>驱动</font>篇)
IMX257 BEEP驱动程序实现
1.确定相关寄存器基址 确定IOMUX地址 0x43fa_c000 0x43fa_ffff GPIO1的地址 0x53fc_c000 0x53fc_ffff MUX_CTL寄存器偏移地址 0x011c PAD-CTL 寄存器偏移 0x0314 GPIO寄存器偏移地址 2.编译测试 本驱动程序亲测成功: 附上驱动程序代码: 1 #include linux/cdev.h 2 #include linux/module.h 3 #include linux/types.h 4 #include linux/fs.h 5 #include linux/errno.h 6 #in
[单片机]
IMX257 <font color='red'>BEEP</font><font color='red'>驱动</font>程序实现
TQ210搭载Android4.0.3系统构建之LED从驱动到HAL到JNI到应用程序(JNI篇)
开发板:TQ210 OS:Android 4.0.3 以下所有内容都是在TQ210开发板上实现,并且很多内容也是天嵌公司提供,我将一些内容进行了删减、替换,然后加入了一些自己的理解,同时也是记录自己学习的旅程。 led_unders_led_jni.c #include jni.h //包含jint JNINativeMethod... #include android/log.h //包含__android_log_print... #include hardware/led_unders_led_hal.h #include hardware/hardware.h #include stdio.h
[单片机]
S5PV210(TQ210)学习笔记——按键驱动程序
经过前面的配置,S5PV210开发已经可以成功进入Linux控制台了,那么,有了这个环境就可以开始学习Linux驱动的编写和测试了。学习Linux设备驱动,通常是从字符设备驱动开始。由于linux驱动开发具有比较系统的体系结构,我很难在一篇文章中阐述其开发思路,为了简单起见,从本文开始,自行编写的驱动将直接附上代码,对开发过程中感触比较深的地方稍作陈述。 我写的第一个驱动程序是Led的,但是感觉没有必要发出来了,S5PV210(TQ210)的按键驱动程序源码,仅供参考: #include linux/types.h #include linux/module.h #include linux/cdev.h #incl
[单片机]
TQ210搭载Android4.0.3系统构建之ADC从驱动到HAL到JNI到应用程序(应用程序篇)
adc的上层应用:在UI主线程中,通过Handler机制,在自定义的线程与主线程之间进行消息的传递,从而更新文本控件显示ADC转换的值 AdcActivity.java package com.under.adc; import java.text.DecimalFormat; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.app.AlertDialog; import android.view.Me
[单片机]
S5PV210(TQ210)学习笔记——输入子系统驱动
前面的文章简单的讲述了字符设备驱动程序的编写,用字符设备驱动的方式实现了按键驱动,但是,出了我们的自己编写的针对我们的这个驱动程序的应用程序之外,其他应用程序都无法接收我们这个驱动的键值输入,为了让所有应用程序都可以接收我们的按键驱动解析的键值,Linux内核定义了 输入子系统 的概念,也就是说,只要我们按照这个模型进行驱动开发,并为其提供必须的接口函数,那么,Linux内核就可以正常来获取我们的键盘值了。 输入子系统的原理分析强烈推荐观看韦东山老师的视频讲座,讲的非常清楚,我这里是按照输入子系统的方式实现的按键驱动,下面是源码,放在这里做个备份: #include linux/types.h #include linux
[单片机]
S5PV210(TQ210)学习笔记——Nand flash驱动编写
跟裸机程序一样,S5PV210的Nand flash模块跟S3C2440的Nand flash模块非常相似,如果不引入ECC,驱动程序的编写也非常简单,具体的分析及编写过程强烈推荐观看韦东山老师的视频教程,我是使用的Linux-3.8.6(Linux-3.8.3也一样)内核,驱动的API函数有些变化,不过原理是相通的,稍微看一下内核源码并参考下其他平台的相关代码就可以自己写出Nand flash驱动了,下面是Nand flash驱动的源码,没有启用ECC,当然,你也可以改成软件ECC,但是我的觉得既然软件ECC不如HWECC快,我就采用硬件ECC吧,我会在下篇文章中加入HWECC。 #include linux/module.h
[单片机]
STM8 开发故事--之蜂鸣器 BEEP设计坑爹的引脚(一)
为什么选stm? 最近才又开始搞stm8开发。虽然以前从来没用过stm的产品,但是stm在嵌入界鼎鼎大名可是早有耳闻。据某IC供应商提供的数据当今(2019年)56%的MCU都是stm的。要说为什么这么火,最直接的原因:便宜而且功能强大。淘宝上stm8s的最小系统板才1块多RMB。 因为要要开发的产品要用液晶显示数字,而且是用电池供电。所以选择了stm8L052c6t6。有朋友推荐我用华大的HC32L136。本想支持国行的,但是供应商不跟进就涮了,还有一个原因又怕资料太少,还是暂时放弃了。我以前做过51的项目,同样的51atmel的质量就好过华邦,华邦掉程序的概率要高很多。这也是我选stm的原因。于是在tb买了一块带液晶显示的
[单片机]
STM8 开发故事--之蜂鸣器 <font color='red'>BEEP</font>设计坑爹的引脚(一)
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved