Chinaunix首页 | 论坛 | 博客
  • 博客访问: 66530
  • 博文数量: 13
  • 博客积分: 620
  • 博客等级: 上士
  • 技术积分: 190
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-16 15:02
文章分类

全部博文(13)

文章存档

2010年(13)

我的朋友

分类: LINUX

2010-04-24 15:55:12

    MagicARM2410开发板上的i2c驱动包含四个文件:i2c-core.c、i2c-dev.c、i2c-algo-s3c2410.c、i2c-s3c2410.c。每个文件都编译为一个模块,驱动加载时要严格按照上面四个文件的顺序,否则将会出错。其中前两个是晕i2c控制器无关的模块,后两个便是与控制器直接相关的模块。加载到内存后四个模块的依赖关系为:i2c-dev——>i2c-core——>i2c-algo-s2c2410——>i2c-s3c2410.发送和接收的实现过程相似,仅以接收数据为例,在应用层调用read函数时i2c驱动的实现流程:


简单的分析如下:

(1)i2cdev_read()为应用程序调用read后对应的函数,在i2c-dev.c文件中有对应关系(i2cdev_fops)和函数的实现,struct i2cdev_fops如下:
static struct file_operations i2cdev_fops = {
#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
  owner:    THIS_MODULE,
#endif     /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
#if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,9)
  llseek:    i2cdev_lseek,
#else
  llseek:    no_llseek,
#endif
  read:    i2cdev_read,
  write:    i2cdev_write,
  ioctl:    i2cdev_ioctl,
  open:    i2cdev_open,
  release:  i2cdev_release,
};
(2)i2cdev_read ()函数的实现中调用i2c_master_recv(client,tmp,count),其中的参数:
client:从该设备接收数据;tmp:接收到数据存放的位置;count:接收的数据个数。
该函数将将tmp和count以及其他的一些参数填充到结构体struct i2c_msg,然后将该结构的地址作为参数传递给函数adap->algo->master_xfer()。该函数即为结构体struct i2c_algorithm中的s3c2410_xfer(),该结构体的填充是在i2c-algo-s3c2410.c文件中,struct i2c_algorithm的填充如下
static struct i2c_algorithm s3c2410_algo = {
  "Samsung S3C2410X algorithm",
  I2C_ALGO_S3C2410,
  s3c2410_xfer,
  NULL,
  NULL,      /* slave_xmit    */
  NULL,      /* slave_recv    */
  algo_control,    /* ioctl    */
  s3c2410_func,    /* functionality  */
};
(3) adap->algo->master_xfer(adap,&msg,1)中的参数:
adap:即为:struct i2c_adapter *adap=client->adapter;
msg:传送给该函数的struct i2c_msg结构体的起始地址。
s3c2410_xfer()函数的实现过程:
首先对adap进行一些初始化操作,然后调用s3c2410_readbytes (),该函数通过调用s3c2410_outb()和s3c2410_inb()进行数据的的发送和接收,如起始、应答、停止和发送地址、接收或发送数据等,其中s3c2410_outb()和s3c2410_inb()为两个宏定义,即:
#define s3c2410_inb(adap, reg) adap->getiic(adap->data, reg)
#define s3c2410_outb(adap, reg, val) adap->setiic(adap->data, reg, val)
宏定义中此处的adap为struct i2c_algo_s3c2410_data,getiic()和setiic()两个函数为该机构体中的对应的函数,是在i2c-s3c2410.c文件中对该结构体进行得填充,如下:
static struct i2c_algo_s3c2410_data iic_s3c2410_data = {
  NULL,
  iic_s3c2410_setbyte,    /* 写字节 */
  iic_s3c2410_getbyte,    /* 读字节 */
  iic_s3c2410_getown,
  iic_s3c2410_getclock,
  iic_s3c2410_waitforpin,
  80, 80, 100,    /*  waits, timeout */
};
(4)i2c-s3c2410.c文件中对结构体i2c_algo_s3c2410_data中各函数的实现很简单,对硬件操作,实现简单的功能。如函数iic_s3c2410_setbyte(写一个字节到硬件中)的实现:
static void iic_s3c2410_setbyte(void *data, int ctl, int val)
{
       *(volatile unsigned char *)(ctl) = (val);    
}
ctl:为硬件的地址,也就是寄存器的地址。
val:为要写入的数据。

总结:
(1)i2c-s3c2410.c文件中有一个struct i2c_algo_s3c2410_data结构,该结构提供了最简单的硬件操作函数:iic_s3c2410_setbyte(发送一个字节)、iic_s3c2410_getbyte(读取一个字节)、iic_s3c2410_getown、iic_s3c2410_getclock,  iic_s3c2410_waitforpin。
(2)i2c-algo-s3c2410.c文件中有一个struct i2c_algorithm结构,该结构是对上面struct i2c_algo_s3c2410_data中一些函数进行的封装,提供了高一级的数据传输函数,如:s3c2410_xfer(数据传输,可以发送也可以接收)、algo_control、s3c2410_func。
(3)i2c-core.c文件,都是一些函数的实现,供其他文件中的函数调用。
(4)i2c-dev.c文件。即为驱动的最顶层,包含struct file_operations i2cdev_fops结构的填充,和里面一些函数的实现。
阅读(2043) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~