20150223 IMX257 BEEP驱动程序实现

20150223 IMX257 BEEP驱动程序实现

2015-02-23 李海沿

和我们今天上午编写的LED驱动程序一样,此处我们实现一个beep蜂鸣器的鸣叫驱动程序

我们知道我们蜂鸣器的引脚由 GPIO1_26控制的,所以我们此处只需要将前面led驱动程序的相关引脚修改为GPIO1_26 就可以了

(和前面几乎一样,LED驱动程序参考:http://www.cnblogs.com/lihaiyan/p/4297923.html

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 #include<linux/mm.h>
  7 #include<linux/sched.h>
  8 #include<linux/init.h>
  9 #include<asm/io.h>
 10 #include<asm/system.h>
 11 #include<asm/uaccess.h>
 12 #include<linux/device.h>
 13 #include <linux/delay.h>
 14
 15 #define Driver_NAME "beep_dev"
 16 #define DEVICE_NAME "beep_dev"
 17
 18 static int major = 0;
 19
 20 //auto to create device node
 21 static struct class *drv_class = NULL;
 22 static struct class_device *drv_class_dev = NULL;
 23
 24 //beep
 25 //寄存器基址;
 26 static unsigned long mem_iomux;
 27 static unsigned long mem_gpio1;
 28 static unsigned long base_iomux;      //iomux基址 0X 43FA C000 -  0X 43FA FFFF
 29 static unsigned long base_gpio1;    //gpio3      0X 53FC C000 -  0X 53FC FFFF
 30 // MUX_CTL模式选择  配置寄存器
 31 #define MUX_CTL  (*(volatile unsigned long *)(base_iomux + 0x011c))
 32 // PAD_CTL GPIO常用功能设置
 33 #define PAD_CTL  (*(volatile unsigned long *)(base_iomux + 0x0314))
 34 // GPIO DR   数据寄存器  DR
 35 #define DR_GPIO1 (*(volatile unsigned long *)(base_gpio1 + 0x0000))
 36 // GPIO GDIR 方向控制寄存器  GDIR
 37 #define GDIR_GPIO1 (*(volatile unsigned long *)(base_gpio1 + 0x0004))
 38
 39
 40 static int key_open(struct inode *inode, struct file *file)
 41 {
 42     printk("<0>function open!\n\n");
 43     return 0;
 44 }
 45
 46 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
 47 {
 48     return 0;
 49 }
 50
 51 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
 52 {
 53     printk("<0>function write!\n\n");
 54     return 1;
 55 }
 56
 57 static int  key_release(struct inode *inode, struct file *filp)
 58 {
 59     printk("<0>function write!\n\n");
 60     return 0;
 61 }
 62
 63 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)
 64 {
 65     printk("<0>function ioctl!\n\n");
 66     return 0;
 67 }
 68 static struct file_operations key_fops = {
 69     .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
 70     .open   =   key_open,
 71     .read   =   key_read,
 72     .write  =   key_write,
 73     .release=   key_release,
 74     .ioctl  =   key_ioctl,
 75 };
 76
 77 void gpio_addr(void){
 78     printk("<0>addr base_iomux : %x \n",base_iomux);
 79     printk("<0>addr base_gpio1 : %x \n",base_gpio1);
 80     printk("<0>addr MUX_CTL : %x \n",&MUX_CTL);
 81     printk("<0>addr PAD_CTL : %x \n",&PAD_CTL);
 82     printk("<0>addr GDIR_GPIO1 : %x \n",&GDIR_GPIO1);
 83     printk("<0>addr DR_GPIO1 : %x \n",&DR_GPIO1);
 84 }
 85
 86 void beep_on_off(void){
 87     ssleep(1);
 88     DR_GPIO1 |= (0x01 << 26);        //将GPIO1_26置1
 89     ssleep(1);
 90     DR_GPIO1 &= ~(0x01 << 26);        //将GPIO1_26清零
 91     ssleep(1);
 92     DR_GPIO1 |= (0x01 << 26);        //将GPIO1_26置1
 93     ssleep(1);
 94     DR_GPIO1 &= ~(0x01 << 26);        //将GPIO1_26清零
 95     ssleep(1);
 96     DR_GPIO1 |= (0x01 << 26);        //将GPIO1_26置1
 97     ssleep(1);
 98     DR_GPIO1 &= ~(0x01 << 26);        //将GPIO1_26清零
 99     ssleep(1);
100     DR_GPIO1 |= (0x01 << 26);        //将GPIO1_26置1
101     ssleep(1);
102     DR_GPIO1 &= ~(0x01 << 26);        //将GPIO1_26清零
103     ssleep(1);
104     DR_GPIO1 |= (0x01 << 26);        //将GPIO1_26置1
105     ssleep(1);
106     DR_GPIO1 &= ~(0x01 << 26);        //将GPIO1_26清零
107 }
108
109 static int __init  key_irq_init(void)
110 {
111     printk("<0>\nHello,this is %s module!\n\n",Driver_NAME);
112     //register and mknod
113     major = register_chrdev(0,Driver_NAME,&key_fops);
114     drv_class = class_create(THIS_MODULE,Driver_NAME);
115     drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME);  /*/dev/key_query*/
116
117     //IO端口申请 ioremap  可以直接通过指针来访问这些地址
118     base_iomux = ioremap(0x43FAC000,0xFFF);
119     base_gpio1 = ioremap(0x53FCC000,0xFFF);
120
121     //MUX_CTL
122     MUX_CTL &= ~(0x07 << 0);
123     MUX_CTL |= (0X05 << 0);    //设置为ALT5  GPIO1_26 BEEP
124     //PAD_CTL
125     PAD_CTL &= ~(0x01<<13 | 0x01<<3 | 0x03<<1 | 0x01<<0);   //1.8v 不需要上拉下拉  CMOS输出 slew rate
126     //GDIR_GPIO1    配置为输出模式
127     GDIR_GPIO1 &= ~(0x01 << 26);
128     GDIR_GPIO1 |= (0x01 << 26);    //配置为输出模式
129
130     //DR_GPIO1        配置为输出0 点亮ERR_LED
131     DR_GPIO1 &= ~(0x01 << 26);        //将GPIO1_26清零
132     DR_GPIO1 &= ~(0x01 << 26);        //将GPIO1_26清零
133     gpio_addr();
134     beep_on_off();
135     return 0;
136 }
137
138 static void __exit key_irq_exit(void)
139 {
140     gpio_addr();
141     printk("<0>\nGoodbye,%s!\n\n",Driver_NAME);
142     beep_on_off();
143
144        unregister_chrdev(major,Driver_NAME);
145     device_unregister(drv_class_dev);
146     class_destroy(drv_class);
147
148     //释放IO端口
149     iounmap(base_iomux);
150     iounmap(base_gpio1);
151 }
152
153
154 /* 这两行指定驱动程序的初始化函数和卸载函数 */
155 module_init(key_irq_init);
156 module_exit(key_irq_exit);
157
158 /* 描述驱动程序的一些信息,不是必须的 */
159 MODULE_AUTHOR("Lover雪儿");
160 MODULE_VERSION("0.1.0");
161 MODULE_DESCRIPTION("IMX257 key Driver");
162 MODULE_LICENSE("GPL");

时间: 2024-12-16 00:48:42

20150223 IMX257 BEEP驱动程序实现的相关文章

20150223 IMX257 LED驱动程序实现

20150223 IMX257 LED驱动程序实现 2015-02-23 李海沿 由于昨天对IMX257的地址分配不了解,所以前面只能用s3c24xx的驱动程序来了解ioremap等对IO端口的工作原理. 但是经过昨晚对IMX257芯片的细细梳理,今天早上起来又把IMX257的芯片资料看了一遍,终于成功看懂了,下面意义给大家道来. 我们此处使用ERR_LED 也就是GPIO3_23引脚 一.IMX257 芯片资料分析 1.确定相关寄存器基址 确定IOMUX地址 GPIO3的地址 2.确定相关寄存

20150223 IMX257 设备驱动模型之Kobject(一)

20150223 IMX257 设备驱动模型之Kobject(一) 2015-02-23 李海沿 接下来我们开始涉及设备驱动模型,从简入深,我们先写一个驱动,实现的功能就是在sys目录下建立一个目录和一个属性文件,可读可写. 所以今天的任务就是把这个程序搞定,只要把这几个结构体了解,知道有这个结构体就够了,很晚了,剩下的我们交给明天吧. 一.结构体参数解释 1. kobject kobject是设备驱动模型的基础.sysfs是基于kobject建立起来的. struct kobject{ con

20150218【改进】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

[改进]IMX257实现GPIO-IRQ中断按键获取键值驱动程序 2015-02-18 李海沿 一.使用struct pin_desc 管理按键的值 1.定义结构体 2.将前面我们申请中断时写的(void *)1修改为 &pins_desc[n] 在ioctl中,设置中断中修改 在key_release中释放中修改 3.在中断程序中利用我们定义的struc pins_desc判断并得到按键的值 4.得到按键键值后,唤醒程序,在read函数中返回键值 附上驱动源程序: 1 /***********

20150218【改进信号量】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

[改进信号量]IMX257实现GPIO-IRQ中断按键获取键值驱动程序 2015-02-18 李海沿 前面我们使用POLL查询方式来实现GPIO-IRQ按键中断程序 这里我们来使用信号量,让我们的驱动同时只能有一个应用程序打开. 一.首先在前面代码的基础上来一个简单的信号 1.定义一个全局的整形变量 2.在打开函数中,每次进入打开函数canopen都自减1, 3.当我们不使用时,在realease 中canopen自加1 4.这样就实现了一个简单的信号量,我们编译,测试 当我们使用两个应用程序来

20150218【改进Poll定时查询】IMX257实现GPIO-IRQ中断按键获取键值驱动程序

[改进Poll定时查询]IMX257实现GPIO-IRQ中断按键获取键值驱动程序 2015-02-18 李海沿 按键驱动程序中,如果不使用read函数中使程序休眠的,而是还是使用查询方式的话,可以使用Poll函数,来控制一定时间内,如果有按键发生,则立即返回键值. 同时,poll也可以同时监控多个(比如说按键,鼠标,等)一旦发生事件则立即返回. 我们在linux查看帮助: 从帮助中的说明得知, poll, ppoll - wait for some event on a file descrip

20150216 IMX257实现GPIO-查询按键驱动程序

20150216IMX257实现GPIO-查询按键驱动程序 2015-02-16 李海沿 前面我们介绍了简单的通用字符设备驱动程序,接下来,我们在它的基础上来实现GPIO的查询按键功能. 先附上驱动程序代码 1 /****************************** 2 linux key_query 3 *****************************/ 4 #include <linux/module.h> 5 #include <linux/init.h>

20150220【改进定时器】IMX257实现GPIO-IRQ定时器消抖驱动程序

[改进定时器]IMX257实现GPIO-IRQ定时器消抖驱动程序 2015-02-20 李海沿 前面我们的GPIO-IRQ按键的驱动程序实现了中断,阻塞,信号量,poll查询等功能,具体请进博客http://www.cnblogs.com/lihaiyan/ 本文,我们还是在前面的按键驱动程序的基础上,引入定时器,来消除抖动. 一.内核定时器详解 1.timer_list结构体 在/include/linux/timer.h中. struct timer_list { struct list_h

IMX257实现GPIO-IRQ中断按键驱动程序

IMX257实现GPIO-IRQ中断按键驱动程序 2015-02-18 李海沿 ????昨天我们已经实现了中断查询的方式实现GPIO按键驱动程序,但是,有一个缺点就是,当我们把应用程序放在后台执行时,即便没有按键,应用程序while循环中的read函数也不断的在运行,严重的导致了CPU资源的浪费. ????本文中,我们在前面按键查询驱动程序的基础上来修改. ????大概介绍一下设计思路吧: ????和前面的差不多,当我们加载驱动时,首先在init函数中,对GPIO功能进行模式设置,都设置为GPI

IMX257虚拟网卡vnet驱动程序

20150419 IMX257虚拟网卡vnet驱动程序 2015-04-19 Lover雪儿 一.一个简单的虚拟网卡驱动 1 static struct net_device *vnet_dev; //定义一个网络设备结构体 2 3 4 static const struct net_device_ops virt_netdev_ops = { 5 .ndo_start_xmit = NULL, 6 }; 7 8 9 static int virt_net_init(void){ 10 11 /