/*http://blog.csdn.net/zhengmeifu/archive/2009/12/15/5002900.aspx*/
本驱动程序经过测试,证明运行良好,下面附有驱动原码和测试程序,若有哪位引用了我的驱动,请注明出处。谢谢!
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
/****************************************************************
Copyright(c) 2009-2010,Newkoom Net Tech.Co,.Ltd
模块名称(Filename): beep_s3c2410.c
项目名称(Projectname): RPM(Remote Power Manager System)
版本号(Version): 1.0.0
创建日期(Date): 2009-11-22
作者(Author): ZMF(Zheng meifu)
功能描述(Description): buzzer(beep) driver for linux2.6.14.1
其他说明(Others):
修改记录(History): 调试成功:2009-11-23
2009-12-1:之前只能在定时任务结束后才释放锁,今天改为
设置完ioctl后立即释放,以便连续发声。
****************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/hardware.h>
#include <asm/arch/regs-timer.h>
#include <asm/arch/regs-irq.h>
#include <asm/mach/time.h>
#include <asm/hardware/clock.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#define BEEPDEV_NAME "beep" /*设备名 beep*/
#define PWM_IOCTL_SET_FREQ 1 /*定义宏常量,用于后面的ioctl中的switch case*/
#define PWM_IOCTL_STOP 2
#define SET_RIGHT_ACTION_BEEP 3 // 此处宏数字不能改,和以下beep_const序号相关
#define SET_ERROR_ACTION_BEEP 4 // 同上
#define SET_KEY_PRESS_BEEP 5 // 同上
#define BEON (1<<(sizeof(int)*8-1))
#define BEOF 0
#define PRESET_FREQ 1000
#define KEY_DELAYMS(X) (HZ/(1000/(X)))
static struct semaphore lock; /*定义信号量 lock*/
static struct semaphore ioctl_lock;
/* freq: pclk/50/16/65536 ~ pclk/50/16
* if pclk = 50MHz, freq is 1Hz to 62500Hz
* human ear : 20Hz~ 20000Hz
*/
const int beep_const[3][8]={
{500|BEON,100|BEOF,0,0,0,0,0,0}, // right
{100|BEON,50|BEOF,100|BEON,50|BEOF,100|BEON,50|BEOF,0,0}, // error
{100|BEON,50|BEOF,0,0,0,0,0,0}, // key
};
struct timer_list beep_timer;
static int beep_step;
static void PWM_Set_Freq(unsigned long freq);
static void PWM_Stop(void);
static void beep_timer_handler(unsigned long data){
int onofftime=beep_const[data][beep_step++];
if(onofftime !=0){
beep_timer.data = data;
mod_timer(&beep_timer, jiffies+ KEY_DELAYMS(onofftime&(~BEON)));
if(onofftime&BEON)
PWM_Set_Freq(PRESET_FREQ);
else PWM_Stop();
}else{
PWM_Stop();
del_timer(&beep_timer);
//up(&ioctl_lock);
}
}
static void set_beep_type(int type){
int tmp_time= beep_const[type-3][0]&(~BEON);
del_timer(&beep_timer);
init_timer(&beep_timer);
beep_timer.expires = jiffies + KEY_DELAYMS(tmp_time);
beep_timer.function = beep_timer_handler;
beep_timer.data = type-3;
beep_step=1;
add_timer(&beep_timer);
PWM_Set_Freq(PRESET_FREQ);
}
static void PWM_Set_Freq( unsigned long freq ) /*设置pwm的频率,配置各个寄存器*/
{
unsigned long tcon, tcnt, tcfg1, tcfg0,pclk;
struct clk *clk_p;
/*set GPB0 as tout0, pwm output 设置GPB0为tout0,pwm输出*/
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0);
tcon = __raw_readl(S3C2410_TCON); /*读取寄存器TCON到tcon*/
tcfg1 = __raw_readl(S3C2410_TCFG1); /*读取寄存器TCFG1到tcfg1*/
tcfg0 = __raw_readl(S3C2410_TCFG0); /*读取寄存器TCFG0到tcfg0*/
//prescaler = 50
tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; /* S3C2410_TCFG_PRESCALER0_MASK定时器0和*/
/* 1的预分频值的掩码,TCFG[0~8]*/
tcfg0 |= (50 - 1); /* 预分频为50 */
//mux = 1/16
tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK; /*S3C2410_TCFG1_MUX0_MASK定时器0分割值的掩*/
/*码:TCFG1[0~3]*/
tcfg1 |= S3C2410_TCFG1_MUX0_DIV16; /*定时器0进行16分割*/
__raw_writel(tcfg1, S3C2410_TCFG1); /*把tcfg1的值写到分割寄存器S3C2410_TCFG1中*/
__raw_writel(tcfg0, S3C2410_TCFG0); /*把tcfg0的值写到预分频寄存器S3C2410_TCFG0中*/
clk_p = clk_get(NULL, "pclk"); /*得到pclk*/
pclk = clk_get_rate(clk_p);
tcnt = (pclk/50/16)/freq; /*得到定时器的输入时钟,进而设置PWM的调制频率*/
__raw_writel(tcnt, S3C2410_TCNTB(0)); /*PWM脉宽调制的频率等于定时器的输入时钟 */
__raw_writel(tcnt/2, S3C2410_TCMPB(0)); /*占空比是50%*/
tcon &= ~0x1f;
tcon |= 0xb; /*disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0*/
__raw_writel(tcon, S3C2410_TCON);
tcon &= ~2; /*clear manual update bit*/
__raw_writel(tcon, S3C2410_TCON); /*把tcon写到计数器控制寄存器S3C2410_TCON中*/
}
static void PWM_Stop( void ){
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP); /*设置GPB0为输出*/
s3c2410_gpio_setpin(S3C2410_GPB0, 0); /*设置GPB0为低电平,使蜂鸣器停止*/
}
static int s3c24xx_pwm_open(struct inode *inode, struct file *file){
if (!down_trylock(&lock)) /*是否获得信号量,是down_trylock(&lock)=0,否则非0*/
return 0;
else
return -EBUSY; /*返回错误信息:请求的资源不可用*/
}
static int s3c24xx_pwm_close(struct inode *inode, struct file *file){
up(&lock); /*释放信号量lock*/
return 0;
}
/*cmd 是1,表示设置频率;cmd 是2 ,表示停止pwm*/
static int s3c24xx_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){
if(!down_trylock(&ioctl_lock)){
switch (cmd) {
case PWM_IOCTL_SET_FREQ: /*if cmd=1 即进入case PWM_IOCTL_SET_FREQ*/
if (arg == 0) /*如果设置的频率参数是0*/
return -EINVAL; /*返回错误信息,表示向参数传递了无效的参数*/
PWM_Set_Freq(arg); /*否则设置频率*/
break;
case PWM_IOCTL_STOP: /* if cmd=2 即进入case PWM_IOCTL_STOP*/
PWM_Stop(); /*停止蜂鸣器*/
break;
case SET_RIGHT_ACTION_BEEP:
case SET_ERROR_ACTION_BEEP:
case SET_KEY_PRESS_BEEP:
set_beep_type(cmd);
break;
default:
break;
}
up(&ioctl_lock);
return 0; /*成功返回*/
}else return -EBUSY;
}
/*初始化设备的文件操作的结构体*/
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = s3c24xx_pwm_open,
.release = s3c24xx_pwm_close,
.ioctl = s3c24xx_pwm_ioctl,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = BEEPDEV_NAME,
.fops = &dev_fops,
.devfs_name[0] = '/0',
};
static int __init dev_init(void){
int ret;
init_MUTEX(&lock); /*初始化一个互斥锁*/
init_MUTEX(&ioctl_lock);
misc.devfs_name[0]='/0'; // 这句使/dev/misc/下产生beep设备文件
ret = misc_register(&misc); /*注册一个misc设备*/
if(ret){
printk (BEEPDEV_NAME "/tinit error!!/n");
}
else
printk (BEEPDEV_NAME "/tinitialized by newkoom.com/n");
return ret;
}
static void __exit dev_exit(void){
del_timer(&beep_timer);
misc_deregister(&misc); /*注销设备*/
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("newkoom<zhengmeifu@sina.com>");
MODULE_DESCRIPTION("S3C2410 RPM or yls3c2410 devlp board beep driver");
/*
1 计数器控制寄存器
1)配置定时器输入时钟
TCFG0-时钟配置寄存器0,用于获得预分频值(1~255)
TCFG1-时钟配置寄存器1,用于获得分割值(2,4,8,16,32)
定时器输入时钟频率=PLCK/{预分频+1}/{分割值}
2)配置PWM的占空比
TCNTB0-定时器0计数缓存寄存器 ,是由定时器的输入时钟分频得到,
是脉宽调制的频率
TCMTB0-定时器0比较缓存寄存器 ,用于设定PWM的占空比 ,寄存器值为高定平的
假设TCNTB0的频率是160,如果TCMTB0是110,则PWM在110个周期是高定平,
50周期是低电平,从而占空比为11:5
3)定时器控制寄存器TCON
TCON[0~4]用于控制定时器0
2.__raw_readl和__raw_writel
读端口寄存器用__raw_readl(a ),该函数从端口a 返回一个32 位的值。
相关的定义在include/asm-arm/io.h 中。#define __raw_readl(a) (*(volatile unsigned int*)(a)),
写端口寄存器用__raw_writel(v,a),该函数将一个32 位的值写入端口a 中。
相关的定义在include/asm-arm/io.h 中。#define __raw_writel(v,a) (*(volatile unsigned int*)(a) = (v))。
此处设置功能控制寄存器,将相应的引脚设为输出状态。
3 .gpio操作
gpio_cfgpin 配置相应GPIO口的功能
gpio_setpin IO口为输出功能时,写引脚
4 基于信号量的Llinux 的并发控制
在驱动程序中,当多个线程同时访问相同的资源时,可能会引发“竞态”,
因此必须对共享资源进行并发控制。信号量(绝大多数作为互斥锁使用)
是一种进行并发控制的手段(还有自旋锁,它适合于保持时间非常短的时间)。
信号量只能在进程的上下文中使用。
void init_MUTEX(&lock)初始化一个互斥锁,即他把信号量lock设置为1
void up (&lock) 释放信号量,唤醒等待者
int down_trylock(&lock) 尝试获得信号量lock ,如果能够立刻获得,就获得信号量,
并返回为0.否则返回非0.并且它不会导致休眠,可以在中断上下文中使用。
在PWM中,当计数值溢出时,就会引发计数中断。所以在这里用这个函数来
获得信号。
*/
/****************************************************************
Copyright(c) 2009-2010,Newkoom Net Tech.Co,.Ltd
模块名称(Filename): beep.cpp
项目名称(Projectname): RPM(Remote Power Manager System)
版本号(Version): 1.0.0
创建日期(Date): 2009-11-22
作者(Author): ZMF(Zheng meifu)
功能描述(Description): beep class define
其他说明(Others):
修改记录(History): 调试成功:
****************************************************************/
class Cbeep{
protected:
int beep_fd;
int freq;
int cmd;
public:
Cbeep();
~Cbeep();
int close_buzzer(void);
int open_buzzer(void); //打开蜂鸣器
int stop_buzzer(void);
int set_buzzer(int freq, int cmd);
};
#include <stdio.h> /*标准输入输出定义*/
#include <termios.h> /*POSIX终端控制定义*/
#include <unistd.h> /*Unix 标准函数定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "beep.h"
Cbeep::Cbeep(){
beep_fd=-1;
freq=1000;
cmd = SET_BEEP_OFF;
}
Cbeep::~Cbeep(){
close_buzzer();
}
int Cbeep::open_buzzer(void) //打开蜂鸣器
{
beep_fd = open(BEEP_FILE, 0); //打开pwm设备驱动文件
if (beep_fd < 0) {
perror("open /dev/misc/beep device");
exit(1); //打开错误,则终止进程。退出参数为1
}
return beep_fd;
// any function exit call will stop the buzzer
// atexit(close_buzzer); //退出回调close_buzzer
}
int Cbeep::close_buzzer(void){ //关闭蜂鸣器
int ret=0;
if (beep_fd >= 0) {
close(beep_fd); //关闭设备驱动文件
beep_fd = -1;
ret=ioctl(beep_fd, SET_BEEP_OFF); //停止蜂鸣器
if(ret<0)
perror("close_buzzer ioctl");
}
return ret;
}
int Cbeep::set_buzzer(int freqt, int cmdt){
// this IOCTL command is the key to set frequency
int ret = ioctl(beep_fd, cmdt, freqt); //设置频率
if(ret < 0) { //如果输入的频率错误
perror("set buzzer freq & cmd");
// exit(1); //退出,返回1
}
return ret;
}
int Cbeep::stop_buzzer(void){
int ret = ioctl(beep_fd, SET_BEEP_OFF); //关闭蜂鸣器
if(ret < 0) { //如果无法关闭蜂鸣器
perror("stop the buzzer");
exit(1); //退出返回1
}
return ret;
}
/****************************************************************
Copyright(c) 2009-2010,Newkoom Net Tech.Co,.Ltd
模块名称(Filename): beep_s3c2410.c
项目名称(Projectname): RPM(Remote Power Manager System)
版本号(Version): 1.0.0
创建日期(Date): 2009-11-22
作者(Author): ZMF(Zheng meifu)
功能描述(Description): buzzer(beep) driver for linux2.6.14.1
其他说明(Others):
修改记录(History): 调试成功:2009-11-23
2009-12-1:之前只能在定时任务结束后才释放锁,今天改为
设置完ioctl后立即释放,以便连续发声。
****************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/hardware.h>
#include <asm/arch/regs-timer.h>
#include <asm/arch/regs-irq.h>
#include <asm/mach/time.h>
#include <asm/hardware/clock.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#define BEEPDEV_NAME "beep" /*设备名 beep*/
#define PWM_IOCTL_SET_FREQ 1 /*定义宏常量,用于后面的ioctl中的switch case*/
#define PWM_IOCTL_STOP 2
#define SET_RIGHT_ACTION_BEEP 3 // 此处宏数字不能改,和以下beep_const序号相关
#define SET_ERROR_ACTION_BEEP 4 // 同上
#define SET_KEY_PRESS_BEEP 5 // 同上
#define BEON (1<<(sizeof(int)*8-1))
#define BEOF 0
#define PRESET_FREQ 1000
#define KEY_DELAYMS(X) (HZ/(1000/(X)))
static struct semaphore lock; /*定义信号量 lock*/
static struct semaphore ioctl_lock;
/* freq: pclk/50/16/65536 ~ pclk/50/16
* if pclk = 50MHz, freq is 1Hz to 62500Hz
* human ear : 20Hz~ 20000Hz
*/
const int beep_const[3][8]={
{500|BEON,100|BEOF,0,0,0,0,0,0}, // right
{100|BEON,50|BEOF,100|BEON,50|BEOF,100|BEON,50|BEOF,0,0}, // error
{100|BEON,50|BEOF,0,0,0,0,0,0}, // key
};
struct timer_list beep_timer;
static int beep_step;
static void PWM_Set_Freq(unsigned long freq);
static void PWM_Stop(void);
static void beep_timer_handler(unsigned long data){
int onofftime=beep_const[data][beep_step++];
if(onofftime !=0){
beep_timer.data = data;
mod_timer(&beep_timer, jiffies+ KEY_DELAYMS(onofftime&(~BEON)));
if(onofftime&BEON)
PWM_Set_Freq(PRESET_FREQ);
else PWM_Stop();
}else{
PWM_Stop();
del_timer(&beep_timer);
//up(&ioctl_lock);
}
}
static void set_beep_type(int type){
int tmp_time= beep_const[type-3][0]&(~BEON);
del_timer(&beep_timer);
init_timer(&beep_timer);
beep_timer.expires = jiffies + KEY_DELAYMS(tmp_time);
beep_timer.function = beep_timer_handler;
beep_timer.data = type-3;
beep_step=1;
add_timer(&beep_timer);
PWM_Set_Freq(PRESET_FREQ);
}
static void PWM_Set_Freq( unsigned long freq ) /*设置pwm的频率,配置各个寄存器*/
{
unsigned long tcon, tcnt, tcfg1, tcfg0,pclk;
struct clk *clk_p;
/*set GPB0 as tout0, pwm output 设置GPB0为tout0,pwm输出*/
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_TOUT0);
tcon = __raw_readl(S3C2410_TCON); /*读取寄存器TCON到tcon*/
tcfg1 = __raw_readl(S3C2410_TCFG1); /*读取寄存器TCFG1到tcfg1*/
tcfg0 = __raw_readl(S3C2410_TCFG0); /*读取寄存器TCFG0到tcfg0*/
//prescaler = 50
tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK; /* S3C2410_TCFG_PRESCALER0_MASK定时器0和*/
/* 1的预分频值的掩码,TCFG[0~8]*/
tcfg0 |= (50 - 1); /* 预分频为50 */
//mux = 1/16
tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK; /*S3C2410_TCFG1_MUX0_MASK定时器0分割值的掩*/
/*码:TCFG1[0~3]*/
tcfg1 |= S3C2410_TCFG1_MUX0_DIV16; /*定时器0进行16分割*/
__raw_writel(tcfg1, S3C2410_TCFG1); /*把tcfg1的值写到分割寄存器S3C2410_TCFG1中*/
__raw_writel(tcfg0, S3C2410_TCFG0); /*把tcfg0的值写到预分频寄存器S3C2410_TCFG0中*/
clk_p = clk_get(NULL, "pclk"); /*得到pclk*/
pclk = clk_get_rate(clk_p);
tcnt = (pclk/50/16)/freq; /*得到定时器的输入时钟,进而设置PWM的调制频率*/
__raw_writel(tcnt, S3C2410_TCNTB(0)); /*PWM脉宽调制的频率等于定时器的输入时钟 */
__raw_writel(tcnt/2, S3C2410_TCMPB(0)); /*占空比是50%*/
tcon &= ~0x1f;
tcon |= 0xb; /*disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0*/
__raw_writel(tcon, S3C2410_TCON);
tcon &= ~2; /*clear manual update bit*/
__raw_writel(tcon, S3C2410_TCON); /*把tcon写到计数器控制寄存器S3C2410_TCON中*/
}
static void PWM_Stop( void ){
s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP); /*设置GPB0为输出*/
s3c2410_gpio_setpin(S3C2410_GPB0, 0); /*设置GPB0为低电平,使蜂鸣器停止*/
}
static int s3c24xx_pwm_open(struct inode *inode, struct file *file){
if (!down_trylock(&lock)) /*是否获得信号量,是down_trylock(&lock)=0,否则非0*/
return 0;
else
return -EBUSY; /*返回错误信息:请求的资源不可用*/
}
static int s3c24xx_pwm_close(struct inode *inode, struct file *file){
up(&lock); /*释放信号量lock*/
return 0;
}
/*cmd 是1,表示设置频率;cmd 是2 ,表示停止pwm*/
static int s3c24xx_pwm_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){
if(!down_trylock(&ioctl_lock)){
switch (cmd) {
case PWM_IOCTL_SET_FREQ: /*if cmd=1 即进入case PWM_IOCTL_SET_FREQ*/
if (arg == 0) /*如果设置的频率参数是0*/
return -EINVAL; /*返回错误信息,表示向参数传递了无效的参数*/
PWM_Set_Freq(arg); /*否则设置频率*/
break;
case PWM_IOCTL_STOP: /* if cmd=2 即进入case PWM_IOCTL_STOP*/
PWM_Stop(); /*停止蜂鸣器*/
break;
case SET_RIGHT_ACTION_BEEP:
case SET_ERROR_ACTION_BEEP:
case SET_KEY_PRESS_BEEP:
set_beep_type(cmd);
break;
default:
break;
}
up(&ioctl_lock);
return 0; /*成功返回*/
}else return -EBUSY;
}
/*初始化设备的文件操作的结构体*/
static struct file_operations dev_fops = {
.owner = THIS_MODULE,
.open = s3c24xx_pwm_open,
.release = s3c24xx_pwm_close,
.ioctl = s3c24xx_pwm_ioctl,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = BEEPDEV_NAME,
.fops = &dev_fops,
.devfs_name[0] = '/0',
};
static int __init dev_init(void){
int ret;
init_MUTEX(&lock); /*初始化一个互斥锁*/
init_MUTEX(&ioctl_lock);
misc.devfs_name[0]='/0'; // 这句使/dev/misc/下产生beep设备文件
ret = misc_register(&misc); /*注册一个misc设备*/
if(ret){
printk (BEEPDEV_NAME "/tinit error!!/n");
}
else
printk (BEEPDEV_NAME "/tinitialized by newkoom.com/n");
return ret;
}
static void __exit dev_exit(void){
del_timer(&beep_timer);
misc_deregister(&misc); /*注销设备*/
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("newkoom<zhengmeifu@sina.com>");
MODULE_DESCRIPTION("S3C2410 RPM or yls3c2410 devlp board beep driver");
/*
1 计数器控制寄存器
1)配置定时器输入时钟
TCFG0-时钟配置寄存器0,用于获得预分频值(1~255)
TCFG1-时钟配置寄存器1,用于获得分割值(2,4,8,16,32)
定时器输入时钟频率=PLCK/{预分频+1}/{分割值}
2)配置PWM的占空比
TCNTB0-定时器0计数缓存寄存器 ,是由定时器的输入时钟分频得到,
是脉宽调制的频率
TCMTB0-定时器0比较缓存寄存器 ,用于设定PWM的占空比 ,寄存器值为高定平的
假设TCNTB0的频率是160,如果TCMTB0是110,则PWM在110个周期是高定平,
50周期是低电平,从而占空比为11:5
3)定时器控制寄存器TCON
TCON[0~4]用于控制定时器0
2.__raw_readl和__raw_writel
读端口寄存器用__raw_readl(a ),该函数从端口a 返回一个32 位的值。
相关的定义在include/asm-arm/io.h 中。#define __raw_readl(a) (*(volatile unsigned int*)(a)),
写端口寄存器用__raw_writel(v,a),该函数将一个32 位的值写入端口a 中。
相关的定义在include/asm-arm/io.h 中。#define __raw_writel(v,a) (*(volatile unsigned int*)(a) = (v))。
此处设置功能控制寄存器,将相应的引脚设为输出状态。
3 .gpio操作
gpio_cfgpin 配置相应GPIO口的功能
gpio_setpin IO口为输出功能时,写引脚
4 基于信号量的Llinux 的并发控制
在驱动程序中,当多个线程同时访问相同的资源时,可能会引发“竞态”,
因此必须对共享资源进行并发控制。信号量(绝大多数作为互斥锁使用)
是一种进行并发控制的手段(还有自旋锁,它适合于保持时间非常短的时间)。
信号量只能在进程的上下文中使用。
void init_MUTEX(&lock)初始化一个互斥锁,即他把信号量lock设置为1
void up (&lock) 释放信号量,唤醒等待者
int down_trylock(&lock) 尝试获得信号量lock ,如果能够立刻获得,就获得信号量,
并返回为0.否则返回非0.并且它不会导致休眠,可以在中断上下文中使用。
在PWM中,当计数值溢出时,就会引发计数中断。所以在这里用这个函数来
获得信号。
*/
/****************************************************************
Copyright(c) 2009-2010,Newkoom Net Tech.Co,.Ltd
模块名称(Filename): beep.cpp
项目名称(Projectname): RPM(Remote Power Manager System)
版本号(Version): 1.0.0
创建日期(Date): 2009-11-22
作者(Author): ZMF(Zheng meifu)
功能描述(Description): beep class define
其他说明(Others):
修改记录(History): 调试成功:
****************************************************************/
class Cbeep{
protected:
int beep_fd;
int freq;
int cmd;
public:
Cbeep();
~Cbeep();
int close_buzzer(void);
int open_buzzer(void); //打开蜂鸣器
int stop_buzzer(void);
int set_buzzer(int freq, int cmd);
};
#include <stdio.h> /*标准输入输出定义*/
#include <termios.h> /*POSIX终端控制定义*/
#include <unistd.h> /*Unix 标准函数定义*/
#include <stdlib.h> /*标准函数库定义*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "beep.h"
Cbeep::Cbeep(){
beep_fd=-1;
freq=1000;
cmd = SET_BEEP_OFF;
}
Cbeep::~Cbeep(){
close_buzzer();
}
int Cbeep::open_buzzer(void) //打开蜂鸣器
{
beep_fd = open(BEEP_FILE, 0); //打开pwm设备驱动文件
if (beep_fd < 0) {
perror("open /dev/misc/beep device");
exit(1); //打开错误,则终止进程。退出参数为1
}
return beep_fd;
// any function exit call will stop the buzzer
// atexit(close_buzzer); //退出回调close_buzzer
}
int Cbeep::close_buzzer(void){ //关闭蜂鸣器
int ret=0;
if (beep_fd >= 0) {
close(beep_fd); //关闭设备驱动文件
beep_fd = -1;
ret=ioctl(beep_fd, SET_BEEP_OFF); //停止蜂鸣器
if(ret<0)
perror("close_buzzer ioctl");
}
return ret;
}
int Cbeep::set_buzzer(int freqt, int cmdt){
// this IOCTL command is the key to set frequency
int ret = ioctl(beep_fd, cmdt, freqt); //设置频率
if(ret < 0) { //如果输入的频率错误
perror("set buzzer freq & cmd");
// exit(1); //退出,返回1
}
return ret;
}
int Cbeep::stop_buzzer(void){
int ret = ioctl(beep_fd, SET_BEEP_OFF); //关闭蜂鸣器
if(ret < 0) { //如果无法关闭蜂鸣器
perror("stop the buzzer");
exit(1); //退出返回1
}
return ret;
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhengmeifu/archive/2009/12/15/5002900.aspx