我想利用PWM定时器中断来驱动蜂鸣器,但是总是神情中断失败,以下是我的驱动代码!!跪求高手指点!!!
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/clk.h>
#include <linux/cdev.h>
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
//#include <linux/regs-timer.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <mach/regs-irq.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
#include <asm/io.h>
#include <asm/errno.h>
#include <asm/irq.h>
#include <asm/mach/time.h>
#include <plat/regs-timer.h>
#define SRCPND 0x4a000000
#define INTMSK 0x4a000008
#define TCFG0 0x51000000
#define TCFG1 0x51000004
#define TCON 0x51000008
#define TCNTB0 0x5100000c
#define TCMPB0 0x51000010
#define DEVICE_NAME "ablyy_buzzer"
#define timer_irq IRQ_TIMER0
static int proc_number = 0;
static int timer0_cmd;
static int DevMajor = 269;
static int irq_timer = 0;
static int irq_time_value;
static int *tcfg0,*tcfg1,*tcon,*tcntb0,*tcmpb0,*intmsk,*srcpnd;
//驱动初始化函数,设置定时器0控制寄存器
void ablyy_init(void)
{
//s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
//s3c2410_gpio_setpin(S3C2410_GPB0, 0);
__raw_writel((readl(S3C2410_GPBCON)&0xfffffffc)|2,S3C2410_GPBCON);
__raw_writel((readl(S3C2410_GPBDAT)&0xfffffffe)|1,S3C2410_GPBDAT);
srcpnd = ioremap_nocache(SRCPND,0x00000004);
intmsk = ioremap_nocache(INTMSK,0x00000004);
tcfg0 = ioremap_nocache(TCFG0,0x00000004);
tcfg1 = ioremap_nocache(TCFG1,0x00000004);
tcon = ioremap_nocache(TCON,0x00000004);
tcntb0 = ioremap_nocache(TCNTB0,0x00000004);
tcmpb0 = ioremap_nocache(TCMPB0,0x00000004);
__raw_writew((__raw_readw(tcfg0)&0xfff0)|0x9f,tcfg0);
__raw_writel((__raw_readl(tcfg1)&0xfffffff0)|0x03,tcfg1);
__raw_writew(0xff,tcntb0);
__raw_writew(0x8f,tcmpb0);
__raw_writel((__raw_readl(tcon)&0xfffffff0)|0x00000007,tcon);
__raw_writel((__raw_readl(tcon)&0xfffffff0)|0x0000000a,tcon);
__raw_writel(__raw_readl(intmsk)&0xffffffbf,intmsk);
}
static void startimer0(void)
{
__raw_writel((__raw_readl(tcon)&0xfffffffe)|0x01,tcon);
//__raw_writel((__raw_readl(tcon)&0xfffffff0)|0x00000009,tcon);
}
static void stoptimer0(void)
{
__raw_writel((__raw_readl(tcon)&0xfffffffe)|0x00,tcon);
}
/*static void starbuzzer(void)
{
__raw_writel((__raw_readl(tcon)&0xfffffff0)|0x0000000b,tcon);
__raw_writel((__raw_readl(tcon)&0xfffffff0)|0x00000009,tcon);
}
struct timer0_irq_desc {
int irq;
char *name;
};
static struct timer0_irq_desc timer0_irq[] ={
{IRQ_TIMER0,DEVICE_NAME},
};*/
//定时器中断函数,发生中断时进入此函数
static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
//struct timer0_irq_desc *timer0_irqs = (struct timer0_irq_desc *)dev_id;
__raw_writel(__raw_readl(srcpnd)&0xfffffdff,srcpnd);
printk("Timer0 interrupt running!!\n");
irq_timer++;
//printk("Timer0 interrupt running!!\n");
//printk("\nirq_time = %d\n",irq_time);
return IRQ_HANDLED;
}
static int ablyy_buzzer_open(struct inode *inode, struct file *file)
{
// ablyy_init();
if(0 == proc_number)
{
ablyy_init();
proc_number = 1;
return 0;
}
else
{
printk("ablyy_buzzer Busy!!\n");
return -1;
}
}
static int ablyy_buzzer_close(struct inode *inode, struct file *file)
{
if(proc_number == 1)
{
iounmap(tcfg0);
iounmap(tcfg1);
iounmap(tcon);
iounmap(tcntb0);
iounmap(tcmpb0);
free_irq(timer_irq,NULL);
proc_number = 0;
return 0;
}
else
{
return -1;
}
}
static int ablyy_buzzer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
timer0_cmd = cmd;
switch(cmd)
{
case 0: startimer0();
while(2000 == irq_timer)
printk("irq_time = %d\n",irq_timer);
irq_time_value = irq_timer;
irq_timer = 0;
stoptimer0();
s3c2410_gpio_setpin(S3C2410_GPB0, 0);
break;
case 1: startimer0();
while(5000 == irq_timer)
printk("irq_time = %d\n",irq_timer);
irq_time_value = irq_timer;
irq_timer = 0;
stoptimer0();
s3c2410_gpio_setpin(S3C2410_GPB0, 0);
break;
default:printk("UNKNOW CMD!\n");break;
}
return irq_time_value;
}
static struct file_operations ablyy_buzzer_fops = {
.owner = THIS_MODULE,
.open = ablyy_buzzer_open,
.release = ablyy_buzzer_close,
.ioctl = ablyy_buzzer_ioctl,
};
/*static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &ablyy_buzzer_fops,
};*/
static struct class *ablyy_class;
static int __init ablyy_buzzer_init(void)
{
int ret;
int err;
//申请设备号
ret = register_chrdev(DevMajor,DEVICE_NAME,&ablyy_buzzer_fops);
if(ret<0)
{
printk("<1>Error: This major number has been used by another device!\n");
return ret;
}
else
{
printk("<1>Info: Device ablyy_buzzer initialized!\n");
//return 0;
}
//ret = request_irq(timer_irq,timer_interrupt,IRQF_DISABLED,DEVICE_NAME,NULL);
//err = request_irq(timer_irq,(void *)&timer_interrupt,SA_INTERRUPT,DEVICE_NAME,NULL);
//申请中断
err = request_irq(timer_irq,(void *)&timer_interrupt,IRQF_DISABLED,DEVICE_NAME,NULL);
//err = request_irq(IRQ_TIME0,(void *)&timer_interrupt,IRQF_DISABLED,DEVICE_NAME,NULL);
if(err<0)
{
printk("Register IRQ_TIMER0 failed!\n");
return err;
}
else
{
printk("Register IRQ_TIMER0 OK!\n");
}
ablyy_class = class_create(THIS_MODULE,DEVICE_NAME);
if(IS_ERR(ablyy_class))
{
printk("Err: failed in ablyy_buzzer class. \n");
return -1;
}
//创建一个设备节点,节点名称为 DEVICE_NAME
device_create(ablyy_class, NULL, MKDEV(DevMajor, 0), NULL, DEVICE_NAME);
printk(DEVICE_NAME"initialized\n");
return 0;
}
static void __exit ablyy_buzzer_exit(void)
{
if(DevMajor>=0)
unregister_chrdev(DevMajor,DEVICE_NAME);
device_destroy(ablyy_class, MKDEV(DevMajor, 0)); //删除设备节点
class_destroy(ablyy_class); //注销类
//free_irq(timer_irq,NULL); //注销中断
printk(DEVICE_NAME"initialized\n");
}
MODULE_LICENSE("GPL");
module_init(ablyy_buzzer_init);
module_exit(ablyy_buzzer_exit); |