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结构的填充,和里面一些函数的实现。
阅读(2098) | 评论(0) | 转发(0) |