首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 驱动开发 >

adc电压采集驱动有关问题,

2013-06-19 
adc电压采集驱动问题,求助!大家好, 开发环境:linux2.6.35+imx287处理器 本人参照网上的adc驱动模板,写了个

adc电压采集驱动问题,求助!
大家好,
 开发环境:linux2.6.35+imx287处理器
 本人参照网上的adc驱动模板,写了个LRADC0单通道的电池电压采集代码,编译成lradc0.ko后,insmod可以加载成功,在/dev下可以看见设备节点,但是一执行测试代码,系统就抱死,卡主不动了,通过调试串口输入任何按键都没反应,包括ctrl+z或者ctrl+c,都没有反应。
 
附上驱动代码和测试代码,请各位帮忙分析下,给点思路,本人是新手:
 驱动代码:
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <linux/jiffies.h>
 #include <linux/io.h>
 #include <linux/sched.h>
 #include <linux/clk.h>
 #include <mach/ddi_bc.h>
 //#include "ddi_bc_internal.h"
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/driver.h>
 #include <mach/regulator.h>
 #include <mach/regs-power.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/clock.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
 #include <linux/interrupt.h>
 #include <asm/fiq.h>
 #include <mach/mx28.h>
 #include <mach/regs-lradc.h>
 #include <linux/miscdevice.h>
 #include <asm/uaccess.h>
 

#define DEVICE_NAME  "lradc0" 
static struct clk *adc_clock;
 static void __iomem *base_addr;
 static wait_queue_head_t adc_waitqueue;
 struct resource *lradc_ch0_irq;
 
DECLARE_MUTEX(adc_lock);
 EXPORT_SYMBOL(adc_lock);
 
static volatile int is_read_ok = 0;
 static volatile int adc_data;
 
static int lradc0_open(struct inode *inode, struct file *file);
 static ssize_t lradc0_read(struct file *filp, char *buffer, size_t count, loff_t *ppos);
 static int lradc0_close(struct inode *inode, struct file *filp);
 
static struct file_operations lradc0_fops =  
 {  
     .owner   = THIS_MODULE,  
     .open    = lradc0_open,  
     .read    = lradc0_read,     
     .release = lradc0_close,  
 };  
 
static struct miscdevice adc_miscdev =  
 {  
     .minor  = MISC_DYNAMIC_MINOR,
     .name   = DEVICE_NAME,  
     .fops   = &lradc0_fops,
 }; 


static irqreturn_t lradc0_irq(int irq, void *dev_id)  
 {  

     if(!is_read_ok)  
     {      
         adc_data = readl(base_addr +HW_LRADC_CHn(0)) & 0x3ffff;  
    
          is_read_ok = 1;  
        wake_up_interruptible(&adc_waitqueue);  
     }  


    
     return IRQ_RETVAL(IRQ_HANDLED);  
 }  
 


static int lradc0_open(struct inode *inode, struct file *file)  
 {  
     int ret;
     
    ret = request_irq(IRQ_LRADC_CH0, lradc0_irq, IRQF_SHARED, DEVICE_NAME, (void *)1);  
     if (ret)  
     {  
         printk(KERN_ERR "Could notallocate ts IRQ_ADC !\n";  
         return -EBUSY;  
     }  
     return 0;  
 }  
 

static void adc_run(void)  
 {  
     volatile unsigned int lradccon;  
     
//ctrl0
     lradccon = readl(base_addr);
 //31 30
     lradccon &= ~(3 << 30);//3
 //0
     lradccon |= (1 << 0);
     writel(lradccon, base_addr);
 
//ctrl1 16
     lradccon = (1 << 16);
     writel(lradccon, base_addr + HW_LRADC_CTRL1);
 
//ctrl3 25 24
     lradccon = (0x01 << 24);
     writel(lradccon, base_addr + HW_LRADC_CTRL3);
 
//ctrl4 0 1 2 3
     lradccon = (0x7 << 0);
     writel(lradccon, base_addr + HW_LRADC_CTRL4);
       
 }  
 


static ssize_t lradc0_read(struct file *filp, char *buff, size_t count, loff_t *offp)  
 {  
     int err;  
   
     down_interruptible(&adc_lock);  
      adc_run();   
      wait_event_interruptible(adc_waitqueue,is_read_ok);  
      is_read_ok = 0;  
       err = copy_to_user(buff, (char*)&adc_data, min(sizeof(adc_data),count));  
     up(&adc_lock);  
    
     return err ? -EFAULT : sizeof(adc_data);  
 }  
 

  
 static int lradc0_close(struct inode *inode, struct file *filp)  
 {  
     free_irq(IRQ_LRADC_CH0, (void *)1);     
     return 0;  
 }  
    
 static int __init lradc0_init(void)
 {  
     int ret;  
      
     adc_clock = clk_get(NULL, "lradc";  


     if (!adc_clock)  
     {  
         printk(KERN_ERR "failed to get lradcclock source\n";  
         return -ENOENT;  
     }  
    
     clk_enable(adc_clock);  
    

     base_addr = ioremap(LRADC_PHYS_ADDR, 0x2A;  
     if (base_addr == NULL)  
     {  
         printk(KERN_ERR "Failed to remapregister block\n";  
         return -ENOMEM;  
         goto fail1;  
     }  
      
 
    init_waitqueue_head(&adc_waitqueue);  
    
      
     ret = misc_register(&adc_miscdev);  
     if (ret)  
     {  
         printk(KERN_ERR "Failed toregister miscdev\n";  
         goto fail2;  
     }  
    
     printk(DEVICE_NAME "initialized!\n";  
    
     return 0;  
      
 fail2:  
     iounmap(base_addr);  
 fail1:  
     clk_disable(adc_clock);  
     clk_put(adc_clock);  
    
     return ret;  
 }  
    
 static void __exit lradc0_exit(void)
 {  
 
    iounmap(base_addr);  
    
 
    if (adc_clock)              
     {  
         clk_disable(adc_clock);  
         clk_put(adc_clock);  
         adc_clock = NULL;  
     }  
    
 
    misc_deregister(&adc_miscdev);  
 }  
    
 module_init(lradc0_init);  
 module_exit(lradc0_exit);  
    
 MODULE_AUTHOR("");  
 MODULE_DESCRIPTION("IMX287 LRADC0 Misc Device Driver");  
 MODULE_VERSION("IMX287 LRADC0 1.0");  
 MODULE_LICENSE("GPL"); 


测试代码:
 
#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <fcntl.h> 



#define DEVICE_NAME "/dev/lradc0"
 
int main(void)  
 {  
     int fd;  
     char buf[4];  
     int i,res,adc_data;  
   
     if ((fd = open(DEVICE_NAME, O_RDONLY)) < 0) 
        {  
         printf("open adc_dev failed\n");  
         return -1;  
     }  
     printf("adc_test result:\n"); 

    if ((res =read(fd, buf, 4)) != 4) 
        {  
         printf("read adc_dev failed \n");
         return -1;  
     }
         printf("adc value = %d", res);
     close(fd);  
   
     return 0;
 }
 

现象如下:
 root@freescale /$ insmod fs_lradc.ko 
lradc0initialized!
 root@freescale /$ ./lradc0_test 
adc_test result:
 

之后系统就没有任何反应了,只能按复位键,请各位帮忙解答,谢谢 adc Linux 驱动
[解决办法]
 insmod fs_lradc.ko  加载时,好像有参数的还要

记不清楚了,多年没弄了

[解决办法]
中断处理李是不是应该清下中断,否则中断一直存在。

热点排行