读书人

adc电压采集驱动有关问题

发布时间: 2013-06-19 10:26:41 作者: rapoo

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 加载时,好像有参数的还要

记不清楚了,多年没弄了

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

读书人网 >驱动开发

热点推荐