需求:应用层输入1蜂鸣器响,输入0蜂鸣器关闭。
一、beep.c文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#define GPIO5_DR 0x020AC000
unsigned int *vir_gpio5_dr;
int misc_open(struct inode *inode,struct file *file)
{
printk("open ok\n");
return 0;
}
int misc_release(struct inode *inode,struct file *file)
{
printk("close ok\n");
return 0;
}
ssize_t misc_read(struct file *file,char __user *ubuf,size_t size,loff_t *loff_t)
{
char kbuf[64] = "hehehe";
if(copy_to_user(ubuf,kbuf,strlen(kbuf)) != 0)
{
printk("copy_to_user error\n");
return -1;
}
printk("read ok\n");
return 0;
}
ssize_t misc_write(struct file *file,char __user *ubuf,size_t size,loff_t *loff_t)
{
char kbuf[64] = {0};
if(copy_from_user(kbuf,ubuf,size) != 0)
{
printk("copy_from_user error\n");
return -1;
}
printk("kbuf is %s\n",kbuf);
if(kbuf[0] == 1)
{
*vir_gpio5_dr |= (1<<1);
}else
{
*vir_gpio5_dr &= ~(1<<1);
}
return 0;
}
struct file_operations misc_fops = {
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_release,
.read = misc_read,
.write = misc_write
};
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "hello_misc",
.fops = &misc_fops
};
static int misc_init(void)
{
int ret;
ret = misc_register(&misc_dev);
if(ret < 0)
{
printk("misc register is error\n");
return -1;
}
printk("misc register is succeed\n");
vir_gpio5_dr = ioremap(GPIO5_DR,4);
if(vir_gpio5_dr == NULL)
{
printk("GPIO5_DR ioremap error\n");
return -EBUSY;
}
printk("GPIO5_DR ioremap OK\n");
return 0;
}
static void misc_exit(void)
{
misc_deregister(&misc_dev);
iounmap(vir_gpio5_dr);
printk("misc bye bye\n");
}
module_init(misc_init);
module_exit(misc_exit);
MODULE_LICENSE("GPL");
解释:
1、底板原理图找到BEEP蜂鸣器的引脚名称 SNVS TAMPER1,6ULL开发手册找到这个引脚,然后对应GPIO5_1,然后找到GPIO5_DR的物理地址20A_C000,GPIO5是一个32位的寄存器。注意:因为Linux中已经有了蜂鸣器的驱动程序,所以只需要修改DR数据寄存器就可以了,我们写的驱动是基于Linux 在应用层操作硬件。
2、添加头文件<linux/io.h> 使用 ioremap函数 物理地址 --> 虚拟地址,iounmap --> 接触虚拟地址。在Linux中只能操作虚拟地址,所以要进行转换。
3、应用层输入1(就是在命令行执行 ./app 1),则调用 fops中的 write函数,向GPIO5 的虚拟地址的bit1位置1 打开蜂鸣器。
二、app.c文件
#include <stdio.h>
int main(int argc,char *argv[])
{
int fd;
char buf[64] = {0};
fd = open("/dev/hello_misc",O_RDWR);
if(fd < 0)
{
perror("open error");
return fd;
}
buf[0] = atio(argv[1]);
write(fd,buf,sizeof(buf));
close(fd);
return 0;
}
注意:atio函数是将字符串转换成int类型