Chinaunix

标题: 写PWM驱动玩,居然发现一个奇怪的问题!(附代码) [打印本页]

作者: vincent_zs    时间: 2009-03-29 13:56
标题: 写PWM驱动玩,居然发现一个奇怪的问题!(附代码)
今天没事把以前写好的pwm裸机程序,弄成了驱动程序,运行测试程序,示波器观察,结果ok!
但开发板上跑的linux系统“死机”了!  ctrl+c 也没有反应。

和以前的驱动程序,测试程序对比没有发现特殊的地方啊?
到底怎么回事呀? 请高手们指点!
  小弟初学!先谢谢了!!!

[ 本帖最后由 vincent_zs 于 2009-3-30 09:15 编辑 ]
作者: vincent_zs    时间: 2009-03-29 13:56
标题: 呼呼~~~~
在线等答案~~~~~~:wink:
作者: vincent_zs    时间: 2009-03-29 14:48
标题:
大家有碰到过类似的问题吗?
  有的,请指点一下。thanks!
作者: .kaka    时间: 2009-03-29 17:13
你肯定是在驱动中加入了while(1)或者类似while(1)的函数了~

就是这个样子~
作者: vincent_zs    时间: 2009-03-29 17:36
标题: 啊!
谢谢ls的,哥们
但应用程序的close(fd)都运行了,调用了驱动中的XX_close()函数,
也打印出了信息!示波器观察输出波形正确! 然后,系统“死了”!
  还有别的什么地方可能出问题导致系统死了呀?
作者: .kaka    时间: 2009-03-29 17:43
用过中断没?
就是这个样子~
作者: .kaka    时间: 2009-03-29 17:45
你是退出驱动之后用示波器观察?为什么~
就是这个样子~
作者: vincent_zs    时间: 2009-03-29 18:31
没注册中断
理想程序是这个样的:运行./XXXX 1 50 //第一个参数为开PWM,第二为占空比
程序运行一次,退出。示波器出现占空比为50%的矩形波!再,运行./XXX  1 80
改变占空比为80%
但设置一次,系统就死了。
就是这个样子~
作者: vincent_zs    时间: 2009-03-29 18:39
新手,碰到奇怪的就无从下手了
哎~~~~~    先放一放得了
作者: .kaka    时间: 2009-03-29 22:16
先贴一下代码吧~(方便的话)

就是这个样子~
作者: vincent_zs    时间: 2009-03-30 08:29
标题: 代码来了!再问个问题
代码是按照我写的裸机程序改过来的,写的比较简单。有什么不好的地方,还请过路的高手们指出来!  还有就是看看为什么会引起死机啊?(考虑了一下,会不会是代码影响了串口啊?或者使跑的系统出了点问题?) 最后一个问题就是在代码中,我起初在犹豫要不要用clk_get(NULL, "pwmt";等函数来获取时钟,但我又不知道第二个参数可以写什么。(以前写触摸屏驱动,可以用“ADC”的),结果是在这个驱动中不需要这个函数。到底怎么用呢?

#include<linux/module.h>
#include<linux/ioctl.h>
#include<linux/types.h>
#include<linux/init.h>
#include<linux/fs.h>
#include <asm/arch/regs-timer.h>
#include<linux/cdev.h>
#include<asm/semaphore.h>
#include <linux/delay.h>
#include<linux/slab.h>
#include<linux/mm.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <asm/arch/regs-irq.h>
#include <asm/mach/time.h>
#include <asm/hardware/clock.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define STOP_PWM 1
#define SET_PWM  2
#define DEVICE_NAME "WM"
#define PWM_MAJOR 233
//static struct clk       *pwm_clock;

struct pwm_device
{
        struct cdev cdev;
        struct semaphore sem;
       
};

struct pwm_device *pwm_dev;

void PWM_Freq_Init(void)
{
        unsigned long tcon=0;
        //unsigned long tcnt;
        unsigned long tcfg1;
        unsigned long tcfg0;
        tcfg0=__raw_readl(S3C2410_TCFG0);
        tcfg1=__raw_readl(S3C2410_TCFG1);
        tcfg0&=0;
        tcfg0|=1;
        tcfg1&=0;
         __raw_writel(tcfg0, S3C2410_TCFG0);
         __raw_writel(tcfg1, S3C2410_TCFG1);
        // tcfg1 = __raw_readl(S3C2410_TCFG1);

        __raw_writel(100, S3C2410_TCNTB(1));
        __raw_writel(20, S3C2410_TCMPB(1));
        tcon|=((0<<11)|(1<<10)|(1<<9)|(0<<);//manual updata
        __raw_writel(tcon,S3C2410_TCON);
        mdelay(10);
        tcon&=0;
        tcon|=((1<<11)|(1<<10)|(0<<9)|(1<<);//auto load
        __raw_writel(tcon,S3C2410_TCON);
      // printk(KERN_INFO"init ok!\n";

}
void PWM_Stop( void )
{
        //set GPB0 as output
        s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB0_OUTP);
        s3c2410_gpio_setpin(S3C2410_GPB1, 0);
        //printk(KERN_INFO"stop Pwm ok!\n";
}
static int pwm_dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
//  volatile unsigned int dd;
//        down((&pwm_dev->sem));
        //        dd=cmd;
//                dd=dd+1;
//                printk(KERN_INFO"%d\n",dd);
            arg=100-arg;
           switch (cmd)
       {
                case SET_PWM:
                        if (arg == 0)
                                return -EINVAL;
                         __raw_writel(arg, S3C2410_TCMPB(1));       
                         printk(KERN_INFO"set pwm ok!\n";
                        //PWM_Set_Freq(arg);
                        break;
                                                                                
               case STOP_PWM:
                      PWM_Stop();
                      printk(KERN_INFO"stop Pwm ok!\n";
                      break;
                default:
                   //   printk(KERN_INFO"default>????!\n";
                         
                break;

        
        }
//        printk(KERN_INFO"set pwm ok!\n";
     // up(&(pwm_dev->sem));
     return 0;

       
}
static int pwm_dev_open(struct inode *inode, struct file *file)
{   
         // pwm_clock = clk_get(NULL, "pwmt";
        //if (!pwm_clock)
//        {
             //   printk(KERN_ERR "failed to get adc clock source\n";
             //   return -ENOENT;
      //  }
      //  clk_use(pwm_clock);
      //  clk_enable(pwm_clock);
        //down(&(pwm_dev->sem));

        init_MUTEX(&(pwm_dev->sem));
        down(&(pwm_dev->sem));
        s3c2410_gpio_cfgpin(S3C2410_GPB0, S3C2410_GPB0_OUTP);
        s3c2410_gpio_setpin(S3C2410_GPB0,0);
        s3c2410_gpio_cfgpin(S3C2410_GPB1, S3C2410_GPB1_TOUT1);
        PWM_Freq_Init();
        printk(KERN_INFO"open ok!\n";
        return 0;
}
static int pwm_dev_close(struct inode *inode, struct file *file)
{
       
    printk(KERN_INFO"close file  ok!\n");
    up(&(pwm_dev->sem));
    return 0;

}
                                                                                

static const struct file_operations pwm_fops=
{
        .owner=THIS_MODULE,
        .open=pwm_dev_open,
        .release=pwm_dev_close,
        .ioctl=pwm_dev_ioctl,
};




static int __init pwm_dev_init(void)
{
        int ret,err;
        dev_t devno;
        devno=MKDEV(PWM_MAJOR,0);
        ret=register_chrdev_region(devno,1,DEVICE_NAME);
        if(ret<0)
        {
        unregister_chrdev_region(devno,1);
        return ret;
        }
        pwm_dev=kmalloc(sizeof(struct pwm_device),GFP_KERNEL);//GHP_KERNEL can cause blocking when erro occurs
        if(!pwm_dev)
        {
           ret = -ENOMEM;
          goto fail_kmalloc;
        }

         memset(pwm_dev,0,sizeof(struct pwm_device));
        cdev_init(&pwm_dev->cdev,&pwm_fops);
        pwm_dev->cdev.owner=THIS_MODULE;
        err=cdev_add(&pwm_dev->cdev,devno,1);
        //if success, return 0;
        if(err)
        {
        printk(KERN_INFO"add cdev failing!\n");
        }
        printk(KERN_INFO"success add  modules\n");
        return 0;
        fail_kmalloc:unregister_chrdev_region(devno,1);
                    printk(KERN_ERR"fail to register the device\n");
                   return 1;
}

static void __exit pwm_dev_exit(void)
{
  cdev_del(&pwm_dev->cdev);
  unregister_chrdev_region(MKDEV(PWM_MAJOR,0),1);
  kfree(pwm_dev);
  printk(KERN_INFO"module exit!\n");
}


module_init(pwm_dev_init);
module_exit(pwm_dev_exit);
                                                                                
                                                                                
MODULE_AUTHOR("vincent_zou");
MODULE_DESCRIPTION("wm driver");
MODULE_LICENSE("GPL");




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2