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