免费注册 查看新帖 |

Chinaunix

广告
  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 5561 | 回复: 21
打印 上一主题 下一主题

有ADC驱动经验的哥哥来一下(已解决) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-12 22:42 |只看该作者 |倒序浏览
我写了个ADC驱动(中断方式),之后用应用程序不停的读ADC
程序很容易死  
内核用的2.6.22  驱动就是很简单的ADC驱动2410的
应用程序就是 读100次ADC的值 之后 求平均 之后打印出来 平均值

谢谢

[ 本帖最后由 Tim_tsang 于 2009-12-5 21:02 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-11-13 00:51 |只看该作者
程序是怎么个死法? 应用程序异常了? 内核OOPS? 内核PANIC? 先把现象描述清楚

论坛徽章:
0
3 [报告]
发表于 2009-11-13 09:23 |只看该作者

回复 #2 accessory 的帖子

没有oops 也没有内核PANIC
程序停了但是 linux 没停   crtl+z 暂停之后 fg 程序 会把停的时候读的数 快速打印到屏幕
感觉是停在内核态和用户态切换那里了

我也不知道专业术语是什么?只能这样描述
求助哇

论坛徽章:
0
4 [报告]
发表于 2009-11-14 03:56 |只看该作者
程序停了的意思是不是程序没反映了? 你用TOP看看你的程序,看它是否还在占用CPU时间,占用的多少?
看上去象是死循环了,或者把系统搞的太忙了.

可以把读ADC的次数改小 ,比如改成1 或者 10 看看.是否还有同样的现象. 还有, 你的应用程序和驱动怎么通信的?有没有BUFFER?

自己多想想

论坛徽章:
0
5 [报告]
发表于 2009-11-15 19:07 |只看该作者

回复 #4 accessory 的帖子

谢谢哥哥
我改为10次取平均 比 取100次取平均 坚持的时间要长 不过还是停了

对于你说的驱动和应用程序的通信 我直接调用的驱动的API   就是read函数呀

没有buffer的说

这个问题不知道怎么解决 我也不知道怎么下手


我问过一些人 说不是死循环 好像说程序卡在一个地方出不来了

论坛徽章:
0
6 [报告]
发表于 2009-11-16 03:39 |只看该作者
还是不明白你说的“停了”是什么意思。正常的时候是怎么样的?你的应用程序会不停得向屏幕输出?然后过一段时间就没有输出了?
可以把你的驱动和应用程序的源代码贴出来看看。

论坛徽章:
0
7 [报告]
发表于 2009-11-16 13:01 |只看该作者

回复 #5 Tim_tsang 的帖子

内存泄露

论坛徽章:
0
8 [报告]
发表于 2009-11-16 15:32 |只看该作者

回复 #7 feiyinziiu 的帖子

我来贴下我的代码吧

论坛徽章:
0
9 [报告]
发表于 2009-11-16 15:34 |只看该作者
利用2410的ADC中断  
static irqreturn_t adcdone_int_handler(int irq,void *dev_id,struct pt_regs *regs)
{
wake_up(&wait);
return IRQ_HANDLED ;
}

中断处理程序

ssize_t s3c2410_adc_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
       int i,LOOP=10000;
       clk_enable(clk); //enable clk
       writel((1<<14)|S3C2410_ADCCON_PRSCVL(19)|(ch<<3)|(0<<1)|(0<<0),base_addr+S3C2410_ADCCON); //setup channel
       for(i=0;i<LOOP;i++); //delay to set up the next channel
       writel((readl(base_addr+S3C2410_ADCCON)|0x1),base_addr+S3C2410_ADCCON); //start ADC
       interruptible_sleep_on(&wait); //zenglei
       i=readl(base_addr+S3C2410_ADCDAT0);
       i= i & 0x3ff;
       copy_to_user(buf, &i, sizeof i);
       return sizeof i;
}
这个是read 函数.

应用程序 里面的读函数 我是执行 十次 GetADresult()之后取平均  
static int GetADresult()
{
int data;
read(adc_fd, &data, sizeof(data));
return data;
}

论坛徽章:
0
10 [报告]
发表于 2009-11-16 21:07 |只看该作者

回复 #9 Tim_tsang 的帖子

我贴下代码
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/bcd.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <asm/arch-s3c2410/regs-adc.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <linux/sched.h>
#include <asm/irq.h>
#include <asm/semaphore.h>
#include <asm/arch/regs-gpio.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include "adc123.h"

MODULE_LICENSE("Dual BSD/GPL");

int adc_major;
int adc_minor;
static int zeng;
struct cdev adc_cdev;
static void __iomem *base_addr;
struct clk *clk;
static int ch;

wait_queue_head_t wait; //zenglei
static irqreturn_t adcdone_int_handler(int irq,void *dev_id)
{
zeng=readl(base_addr+S3C2410_ADCDAT0);
zeng=zeng & 0x3ff;
wake_up_interruptible(&wait);
//interruptible_sleep_on(&wait);
//printk(KERN_ERR "zenglei\n");
return IRQ_HANDLED ;
}
int adc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
       // printk(KERN_ERR "cmd %d\n",cmd);
       ch=cmd; //set up channel
       return 0;
}

ssize_t s3c2410_adc_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)
{
       int i,ret,LOOP=100;
       clk_enable(clk); //enable clk
       writel((1<<14)|S3C2410_ADCCON_PRSCVL(19)|(ch<<3)|(0<<1)|(0<<0),base_addr+S3C2410_ADCCON); //setup channel
       //for(i=0;i<LOOP;i++); //delay to set up the next channel
       writel((readl(base_addr+S3C2410_ADCCON)|0x1),base_addr+S3C2410_ADCCON); //start ADC
        //wake_up(&wait);
       interruptible_sleep_on(&wait); //zenglei
      //writel(0,base_addr+S3C2410_ADCCON); //stop ADC
       //i=readl(base_addr+S3C2410_ADCDAT0);
       //i= i & 0x3ff;
        writel(0,base_addr+S3C2410_ADCCON);
       ret=copy_to_user(buf, &zeng, sizeof zeng);
       return sizeof zeng;
}

static ssize_t s3c2410_adc_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
{
        int data,ret;
        if(count!=sizeof(data)){
                printk("the size of  input data must be %d\n", sizeof(data));
                return 0;
        }
        ret=copy_from_user(&data, buffer, count);
        ch=ADC_WRITE_GETCH(data);
        return count;
}





struct file_operations adc_fops = {
       .owner = THIS_MODULE,
       .ioctl = adc_ioctl,
       .read = s3c2410_adc_read,
       .write = s3c2410_adc_write,
};


int S3C2410_adc_init(void)

{
       int result,err,ret;
       dev_t dev =0;
       result=alloc_chrdev_region(&dev,adc_minor,0,"2410adc");
       adc_major = MAJOR(dev);
       adc_minor = MINOR(dev);
       if(result < 0)
              printk(KERN_ERR "can't get major %d\n",adc_major);
       else
              printk("adc_major: %d\n",adc_major);
       cdev_init(&adc_cdev,&adc_fops);
       adc_cdev.owner=THIS_MODULE;
       adc_cdev.ops=&adc_fops;
       err=cdev_add(&adc_cdev,dev,1);
       if (err < 0)
              printk(KERN_ERR "can't add 2410_adc");
       base_addr = ioremap(0x58000000, 0x20);
       if (base_addr == NULL) {
              printk(KERN_ERR "Failed to remap register block\n");
              return -ENOMEM;
       }


       /* get our clock */
       clk = clk_get(NULL, "adc");
       if (IS_ERR(clk) || clk == NULL) {
              printk(KERN_ERR "ADC clk_get err!!!!!!!!!!!!!\n");
       }
       /* only enable the clock when we are actually using the adc */
       printk(KERN_ERR "add 2410_adc ok!!!!!!!!!!!!\n");
      
  //zenglei
  ret = request_irq(IRQ_ADC, adcdone_int_handler, SA_INTERRUPT,"adc", NULL);
if (ret) {
  return ret;
}
init_waitqueue_head(&wait);//zenglei
printk(KERN_ERR "hahaha\n");
return 0;
}

void S3C2410_adc_exit(void)
{
       dev_t dev=MKDEV(adc_major,adc_minor);
       cdev_del(&adc_cdev);
       iounmap(base_addr);
       unregister_chrdev_region(dev,1);
        free_irq(IRQ_ADC,NULL);
}

module_init(S3C2410_adc_init);
module_exit(S3C2410_adc_exit);
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP