天嵌 ARM开发社区

 找回密码
 注册
查看: 2822|回复: 3

跪求linux驱动高手指点啊!!

[复制链接]
nmxbz 发表于 2010-7-13 13:47:17 | 显示全部楼层 |阅读模式
我想利用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);
亚瑟王 发表于 2010-7-14 19:20:06 | 显示全部楼层
建议你阅读天嵌科技提供的蜂鸣器驱动的代码。在2.6.30.4内核下的:drivers/char/EmbedSky_pwm.c。
 楼主| nmxbz 发表于 2010-7-16 09:27:01 | 显示全部楼层
2# 亚瑟王
你说的代码里面只有PWM驱动,没有定时器中断方面的。
亚瑟王 发表于 2010-7-17 12:24:06 | 显示全部楼层
没搞明白你的用法,PWM驱动里面就是用的定时器0啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号-2 )

GMT+8, 2024-10-6 02:25 , Processed in 1.028360 second(s), 18 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表