samsung ADC 通用驱动
来源:互联网 发布:大数据hadoop指令 编辑:程序博客网 时间:2024/05/16 11:42
ADC是嵌入式产品常用的设备,它的驱动并不是很难,但是如果有多个这类设备的话,就得考虑ADC中断共享的问题了,这样反而是驱动变得较复杂,且不易控制。在2.6.29内核后在arch/arm/plat-samsung目录下加入了adc.c这个代码,这是一个通用adc驱动代码。这个代码用来初始化adc设备并构建了一个客户请求列表,用来接受客户请求转换数据。
下面这个结构体用来描述adc设备
struct adc_device { struct platform_device *pdev; struct platform_device *owner; struct clk *clk; struct s3c_adc_client *cur; struct s3c_adc_client *ts_pend; void __iomem *regs; spinlock_t lock; unsigned int prescale; int irq;};
下面这个结构体用来描述一个客户端:
structs3c_adc_client { structplatform_device *pdev; structlist_head pend; //用来构建客户请求列表 wait_queue_head_t *wait; //等待队列头,用来睡眠 unsignedint nr_samples; int result; unsignedchar is_ts; //是否是触摸屏 unsignedchar channel; //通道 void (*select_cb)(struct s3c_adc_client *c,unsigned selected); void (*convert_cb)(struct s3c_adc_client *c, unsigned val1, unsigned val2, unsigned *samples_left); //转换回调函数};下面就是结构图
我们需要在我们的驱动中构建这个结构体,并且向adc通用驱动中注册这个结构体。注册函数为:
structs3c_adc_client *s3c_adc_register(struct platform_device *pdev, void(*select)(struct s3c_adc_client *client, unsigned int selected), void(*conv)(struct s3c_adc_client *client, unsigned d0, unsigned d1, unsigned *samples_left), unsignedint is_ts)然后我们就可以读取相应通道的数据了:
ints3c_adc_read(struct s3c_adc_client *client, unsigned int ch);
现在我们开始写我们的驱动:
1、 构建我们的设备结构体
在arch/arm/mach-s3c2410/mach-smdk2410.c中添加如下内容structplatform_device s3c_device_adc_convert = {.name ="adc_convert",.id =-1,.dev.parent =&s3c_device_adc.dev,};
2、 注册我们的设备
修改arch/arm/mach-s3c2410/mach-smdk2410.c,在结构体数组smdk2410_devices中添加我们的设备:
staticstruct platform_device *smdk2410_devices[] __initdata = {……&s3c_device_adc, //添加内容&s3c_device_adc_convert, //添加内容……};
修改后重新编译内核
3、 构建我们的驱动
#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/cdev.h>#include <asm/uaccess.h>#include <linux/platform_device.h>#include <plat/adc.h>#include <plat/regs-adc.h>MODULE_LICENSE ("GPL");int adc_major = 250;int adc_minor = 0;int number_of_devices = 1;struct s3c_adc_client *client;struct cdev cdev;dev_t devno = 0;static ssize_t adc_convert_read(struct file *file, char __user *buff, size_t count, loff_t *offset) {unsigned data;unsigned ch;data = 10;ch = 0;data = s3c_adc_read(client, ch);printk("data0 = %d\n", data);if(copy_to_user(buff, (char *)&data, sizeof(data)))return -EFAULT;return 0;}static int adc_convert_open(struct inode *inode, struct file *file){return 0;}static int adc_convert_release(struct inode *inode, struct file *file){return 0;}static struct file_operations adc_convert_fops = {.owner = THIS_MODULE,.read= adc_convert_read,.open = adc_convert_open,.release= adc_convert_release,};static int __devinit adc_convert_probe( struct platform_device *pdev ){struct device *dev = &pdev->dev;int ret = -EINVAL;printk("function = %s\n", __func__);devno = MKDEV(adc_major, adc_minor);ret = register_chrdev_region(devno, number_of_devices, "adc_convert");if( ret ){dev_err(dev, "failed to register device number\n");goto err_register_chrdev_region;}cdev_init(&cdev, &adc_convert_fops);cdev.owner = THIS_MODULE;ret = cdev_add(&cdev, devno, number_of_devices);if( ret ){dev_err(dev, "failed to add device\n");goto err_cdev_add;}client = s3c_adc_register (pdev, NULL, NULL, 0);if(IS_ERR( client )){dev_err(dev, "failed to register adc client\n");goto err_s3c_adc_register;}return 0;err_s3c_adc_register:cdev_del( &cdev );err_cdev_add:unregister_chrdev_region(devno, number_of_devices);err_register_chrdev_region:return ret; }static int __devexit adc_convert_remove(struct platform_device *pdev){s3c_adc_release(client);cdev_del( &cdev );unregister_chrdev_region(devno, number_of_devices);return 0;}static struct platform_driver adc_convert_driver = {.driver = {.name = "adc_convert",.owner = THIS_MODULE,},.probe= adc_convert_probe,.remove = __devexit_p(adc_convert_remove)};static int __init adc_convert_init (void){return platform_driver_register( &adc_convert_driver );}static void __exit adc_convert_exit (void) {platform_driver_unregister( &adc_convert_driver );}module_init (adc_convert_init);module_exit (adc_convert_exit);
4、 编译驱动,并加载到内核里,使用下面代码测试,即可读到相应通道的数据
#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <stdlib.h>#include <fcntl.h>int main (void) {int fd;int data;fd = open ("/dev/adc",O_RDWR);if (fd < 0) {perror("open"); exit(0);}while(1){read (fd, (char *)&data, sizeof(data));printf("Voltage = %.2f\n", 3.3/1024*data);sleep(1);}close (fd);printf ("/dev/adc closed :)\n");return 0;}
- samsung ADC 通用驱动
- samsung ADC 通用驱动
- samsung ADC 通用驱动
- samsung ADC 通用驱动
- S3C2410驱动分析之ADC通用驱动
- S3C2410驱动分析之ADC通用驱动
- S3C2410驱动分析之ADC通用驱动
- S3C2410驱动分析之ADC通用驱动
- linux adc驱动(基于三星通用adc api)
- ADC驱动
- Linux 驱动--ADC驱动
- Linux 驱动--ADC驱动 .
- Linux 驱动--ADC驱动
- 基于linux(2.6.32)通用adc接口的简单测试驱动
- samsung i5700 android驱动安装
- adc驱动基于mini2440
- S3C2440的ADC驱动
- ADC 驱动移植
- axis webservice返回List 对象数组
- linux 中 set,env,export,declare显示shell变量的区别
- kinect使用手册
- JAVA 比较常用的函数方便积累
- Something about the HTK tool
- samsung ADC 通用驱动
- SQL 物理查询原理(上)
- template函数
- 程序员面试、算法研究、编程艺术、红黑树4大系列集锦与总结
- zhuan
- 二.实现Menu按键的功能
- aix 安装gcc编译器
- 数据库表及字段命名规范
- php实现原型模式