/*头文件*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/hardware.h>
/*一些定义*/
#define BEEP_MAJOR 245/* 主设备号*/
#define BEEP_ON 1
#define BEEP_OFF 2
/*定义了蜂鸣器操作的结构体*/
struct beep_dev
{
struct cdev cdev;
unsigned char value;
};
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
/*定义了蜂鸣器操作的结构体的成员*/
struct beep_dev *beepdev;
/*硬件初始化函数,初始化GPIO口*/
static void sep4020_beep_setup(void)
{
*(volatile unsigned long*)GPIO_PORTA_SEL_V |= (0x1<<6); //作为通用用途
*(volatile unsigned long*)GPIO_PORTA_DIR_V &= ~(0x1<<6 );//输出
*(volatile unsigned long*)GPIO_PORTA_DATA_V &= ~(0x1<<6 );//初始输出拉低
}
/*蜂鸣器驱动的open函数*/
int sep4020_beep_open(struct inode *inode, struct file *filp)
{
sep4020_beep_setup();
return 0;
}
/*蜂鸣器程序的relesase函数*/
int sep4020_beep_release(struct inode *inode, struct file *filp)
{
return 0;
}
/*蜂鸣器程序的read和write函数,
因为我们不需要使用read和write,
所以直接返回0*/
static ssize_t sep4020_beep_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
return 0;
}
static ssize_t sep4020_beep_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
return 0;
}
/*应用程序就是通过调用ioctl这个函数来控制硬件*/
int sep4020_beep_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case BEEP_ON:
*(volatile unsigned long*)GPIO_PORTA_DATA_V |= 0x1<<6; //beep is open;
break;
case BEEP_OFF:
*(volatile unsigned long*)GPIO_PORTA_DATA_V &= ~0x1<<6; //beep is close;
break;
default:
return -ENOTTY;
}
return 0;
}
/*将我们自己写的文件操作函数与系统提供的函数结构想挂钩*/
static const struct file_operations sep4020_beep_fops =
{
.owner = THIS_MODULE,
.read = sep4020_beep_read,
.write = sep4020_beep_write,
.ioctl = sep4020_beep_ioctl,
.open = sep4020_beep_open,
.release = sep4020_beep_release,
};
/*加载驱动时执行的init函数*/
static int __init sep4020_beep_init(void)
{
int err,result;
dev_t devno = MKDEV(BEEP_MAJOR, 0);
if(BEEP_MAJOR)
result = register_chrdev_region(devno, 1, "sep4020_beep");
else
result = alloc_chrdev_region(&devno, 0, 1, "sep4020_beep");
if(result < 0)
return result; /*动态申请设备结构体的内存*/
beepdev = kmalloc(sizeof(struct beep_dev),GFP_KERNEL);
if (!beepdev)
{
result = -ENOMEM; //如果申请失败,跳转到错误处理函数
goto fail_malloc;
}
/*将结构体清空*/
memset(beepdev,0,sizeof(struct beep_dev));
/*注册设备进内核*/
cdev_init(&(beepdev->cdev), &sep4020_beep_fops);
beepdev->cdev.owner = THIS_MODULE;
err = cdev_add(&beepdev->cdev, devno, 1); // 创建设备文件
if(err)
printk("adding err\r\n");
return 0;
fail_malloc: unregister_chrdev_region(devno,1);
return result;
}
/*卸载模块执行的函数*/
static void __exit sep4020_beep_exit(void)
{
cdev_del(&beepdev->cdev);
kfree(beepdev);
unregister_chrdev_region(MKDEV(BEEP_MAJOR, 0),1);
}
module_init(sep4020_beep_init); //向Linux系统记录设备初始化的函数名
module_exit(sep4020_beep_exit); //向Linux系统记录设备退出的函数名称
MODULE_AUTHOR("fpmystar");
MODULE_LICENSE("GPL");
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
下面是一个蜂鸣器简单的测试程序:
#include <stdio.h>
#include <fcntl.h>
#define OPEN 1
#define CLOSE 2
int main(int argc,char **argv)
{
int fd;
int i,j;
fd = open("/dev/beep",O_RDWR);
if(fd == -1)
{
printf("wrong\r\n");
exit(-1);
}
for(j=0; j<20; j++)
{
ioctl(fd, OPEN,0);
for(i=0; i<1000000; i++);
ioctl(fd, CLOSE,0);
for(i=0; i<1000000; i++);
}
close(fd);
return 0;
}
文章评论(0条评论)
登录后参与讨论