欢迎光临
我们一直在努力

linux蜂鸣器怎么设置,嵌入式linux设备驱动程序开发指南

驱动描述:该驱动是一个完整的蜂鸣器驱动程序,考虑到了竟态的情况,实现了一个驱动只

能由一个应用程

序打开。该驱动面向应用层提供了强大的操作接口。应用程序操?作蜂鸣器只需要调用write函数写入相应的1或0即可,调用read可以查看当前蜂鸣器的电平状态。然后再驱动层的write和read就会进行相应的动作,当然在应用程序打开驱动时,将会调用open函数初始化gpio等资源,和实现竟态机制。

下面是源代码:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define?ALLOW_OPEN_TIMES?2

//定义硬件相关的数据结构

struct?button_resource?{

char?*name;

//名称

unsigned?int?gpio;

//GPIO编号

};

//定义驱动私有的数据结构

struct?button_priv{

struct?cdev?btn_cdev;

//为了利用container_of

atomic_t?av;

//整型原子变量

int?open_times;

//记录设备打开的次数

spinlock_t?lock;

//分配自旋锁

struct?semaphore?sema;?//分配信号量

};

static?struct?button_priv?*pbtn?=?NULL;

//主设备号

static?int?major;

//设备类

static?struct?class?*cls;

static?int?buzzer_open(struct?inode?*inode,?struct?file?*file)

{

unsigned?long?flags;

struct?button_priv?*pbtnp?=?container_of(inode->i_cdev,

struct?button_priv,?btn_cdev);

file->private_data?=?pbtnp;

gpio_request(S5PV210_GPD0(1),?”buzzer”);

gpio_direction_output(S5PV210_GPD0(1),?0);

#if?0

if?(!atomic_dec_and_test(&pbtnp->av))?{

printk(“button?can?be?open?only?once!\n”);

atomic_inc(&pbtnp->av);

return?-EBUSY;

}

spin_lock_irqsave(&pbtnp->lock,?flags);?//加锁

if?(pbtnp->open_times?>=?2)?{

printk(“allow?open?%d?times\n”,?ALLOW_OPEN_TIMES);

spin_unlock_irqrestore(&pbtnp->lock,?flags);//释放锁

return?-EBUSY;

}

pbtnp->open_times++;

spin_unlock_irqrestore(&pbtnp->lock,?flags);?//释放锁

#endif

#if?0

if(down_trylock(&pbtnp->sema))?{

printk(“button?can?be?open?only?once!\n”);

return?-EBUSY;

}

#endif

//down(&pbtnp->sema);

if?(down_interruptible(&pbtnp->sema))?{

printk(“Proccess?is?INT!\n”);

return?-EINTR;

}

printk(“open?button?successfully!\n”);

return?0;

}

static?int?buzzer_close(struct?inode?*inode,

struct?file?*file)

{

struct?button_priv?*pbtnp?=?file->private_data;

gpio_direction_output(S5PV210_GPD0(1),?0);

gpio_free(S5PV210_GPD0(1));

//atomic_inc(&pbtnp->av);

美国高防vps

#if?0

unsigned?long?flags;

spin_lock_irqsave(&pbtnp->lock,?flags);

pbtnp->open_times–;

spin_unlock_irqrestore(&pbtnp->lock,?flags);

#endif

up(&pbtnp->sema);

return?0;

}

static?int?status;

static?ssize_t?buzzer_read(struct?file?*file,?char?__user?*buf,

size_t?count,?loff_t?*ppos)

{

copy_to_user(buf,?&status,?4);

return?0;

}

static?ssize_t?buzzer_write(struct?file?*file,?char?__user?*buf,

size_t?count,?loff_t?*ppos)

{

int?val;

copy_from_user(&val,?buf,?4);

if?(val?==?1)?{

gpio_set_value(S5PV210_GPD0(1),?1);

}?else?{

gpio_set_value(S5PV210_GPD0(1),?0);

}

status?=?val;

return?0;

}

//设备的操作集合

static?struct?file_operations?btn_fops?=?{

.owner?=?THIS_MODULE,

.open?=?buzzer_open,

.release?=?buzzer_close,

.read?=?buzzer_read,

.write=?buzzer_write

};

static?int?button_init(void)

{

dev_t?dev_id;

if?(major)?{

dev_id?=?MKDEV(major,?0);

register_chrdev_region(dev_id,?1,?”button”);

}?else?{

alloc_chrdev_region(&dev_id,?0,?1,?”button”);

major?=?MAJOR(dev_id);

}

pbtn?=?kmalloc(sizeof(struct?button_priv),?GFP_KERNEL);

memset(pbtn,?0?,sizeof(struct?button_priv));

cdev_init(&pbtn->btn_cdev,?&btn_fops);

atomic_inc(&pbtn->av);

spin_lock_init(&pbtn->lock);

sema_init(&pbtn->sema,?1);?//互斥信号量

cdev_add(&pbtn->btn_cdev,?dev_id,?1);

cls?=?class_create(THIS_MODULE,?”button”);

device_create(cls,?NULL,?dev_id,?NULL,?”button”);

return?0;

}

static?void?button_exit(void)

{

dev_t?dev_id?=?MKDEV(major,?0);

device_destroy(cls,?dev_id);

class_destroy(cls);

cdev_del(&pbtn->btn_cdev);

unregister_chrdev_region(dev_id,?1);

kfree(pbtn);

pbtn?=?NULL;

}

module_init(button_init);

module_exit(button_exit);

MODULE_LICENSE(“GPL?v2”);

赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。