分类:
2010-04-14 18:03:36
I
系统的I
IIC总线的开始/停止信号如图1所示。开始信号为:时钟信号线SCL为高电平,数据线SDA从高变低。停止信号为:时钟信号线SCL为高电平,数据线SDA从低变高。
图1 IIC Start-Stop Signal
IIC总线写数据分几种格式,如字节写和页写。
字节写传送格式如图2所示。开始信号之后,总线开始发数据,第一个Byte是IIC的设备地址,第二个Byte是设备内的地址(如EEPROM中具体的某个物理地址),然后就是要传送的真正的数据DATA。
NOTE:IIC总线在传送每个Byte后,都会从IIC总线上的接收设备得到一个ACK信号来确认接收到了数据。其中,第一个Byte的设备地址中,前7位是地址码,第8位是方向位(“
图2 IIC Byte Write
Write功能的实际实现原理如图3所示:
(1)设置GPIO的相关引脚为IIC输出;
(2)设置IIC(打开ACK,打开IIC中断,设置CLK等);
(3)设备地址赋给IICDS ,并设置IICSTAT,启动IIC发送设备地址出去;从而找到相应的设备即IIC总线上的EEPROM。
(4)第一个Byte的设备地址发送后,从EEPROM得到ACK信号,此信号触发中断;
(5)在中断处理函数中把第二个Byte(设备内地址)发送出去;发送之后,接收到ACK又触发中断;
(6)中断处理函数把第三个Byte(真正的数据)发送到EEPROM中;
(7)发送之后同样接收到ACK并触发中断,中断处理函数判断,发现数据传送完毕。
(8)IIC Stop信号,关IIC中断,置位各寄存器。
图3 IIC Write Operation
NOTE:对于EEPROM,IICDS寄存器发送的数据会先放在Ring buffer中,当其收到stop信号时,开始实际写入EEPROM中。在实际写的过程中,EEPROM不响应从CPU来的信号,直到写完才会响应,因而有一段延迟代码。在page write时,注意一定要有延时!
NOTE:数据先写到EEPROM的ring buffer中,收到Stop信号时,开始实际地把数据写入EEPROM,这时不响应任何输入。即这时Write函数中后面的延时中,向其发slvaddr时,不会得到ACK,直到数据写完时,才会收到ACK。
IIC总线读数据为Current Address Read,Random Read,Sequential Read
IIC总线Random Read传送格式如图4所示。开始信号后,CPU开始写第一个Byte(IIC的设备地址),第二个Byte是设备内的地址(此地址保存在EEPROM中)。然后,开始读过程:发送设备地址找到IIC设备,然后就开始读数据。类似写过程,CPU读一个byte的实际数据后,CPU向IIC的EEPROM发ACK,ACK触发中断。读数据也在中断程序中进行。
图4 IIC Random Read Operation
Device Address格式如下:
1 |
0 |
1 |
0 |
A2 |
A1 |
A0 |
R/W |
对于A0~A2是EEPROM芯片上的引脚,按照引脚硬件上的连接方法,可以给此芯片指定具体的地址。EEPROM的寻址由device address的低3位(A
Linux的I
• I
I
• I
I
通过I
• I
I
内核中对于I
1)i
2)i
3)i
4)i
这4种结构的定义见include/linux/i
对于i
对于i
i
struct i
__u16 addr; /* slave address*/
__u16 flags;
#define I
#define I
#define I
#define I
#define I
#define I
#define I
__u16 len; /* msg length */
__u8 *buf; /* pointer to msg data */
};
它是实际传输的数据,其中包括了slave address,数据长度和实际的数据。
Linux内核源码的drivers目录下有个i
• i
这个文件实现了I
• i
实现了I
i
• chips文件夹
此目录中包含了一些特定的I
• busses文件夹
此目录中包含了一些I
• algos文件夹
实现了一些I
i
1)adapter和client相关操作
int i
int i
int i
int i
int i
int i
2)I
int i
int i
int i
i
i
struct i
int (*master_xfer)(struct i
int num);
int (*smbus_xfer) (struct i
unsigned short flags, char read_write,
u8 command, int size, union i
u32 (*functionality) (struct i
};
根据定义主要要实现i
下面以使用S
at24系列设备驱动程序在文件drivers/i
static struct i
.driver = {
.name = "at24",
.owner = THIS_MODULE,
},
.probe = at24_probe, //在此函数中注册write, read等函数
.remove = __devexit_p(at24_remove),
.id_table = at24_ids,
};
static int __init at24_init(void)
{
io_limit = rounddown_pow_of_two(io_limit);
return i
}
module_init(at24_init); //at24设备驱动初始化
at24_probe函数如下:
static int at24_probe(struct i
{
struct at24_platform_data chip;
。。。。。。
mutex_init(&at24->lock);
at24->use_smbus = use_smbus;
。。。。。。
at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
at24->bin.read = at24_bin_read; //指定read函数
。。。。。。
if (writable) {
if (!use_smbus || i
I
unsigned write_max = chip.page_size;
at24->bin.write = at24_bin_write; //指定write函数
at24->bin.attr.mode |= S_IWUSR;
if (write_max > io_limit)
write_max = io_limit;
if (use_smbus && write_max > I
write_max = I
at24->write_max = write_max;
。。。。。。
}
。。。。。。
at24->client[0] = client;
for (i = 1; i < num_addresses; i++) {
at24->client[i] = i
client->addr + i);
if (!at24->client[i]) {
dev_err(&client->dev, "address 0x%02x unavailable\n",
client->addr + i);
err = -EADDRINUSE;
goto err_clients;
}
}
err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
。。。。。。
i
。。。。。。
err_clients:
for (i = 1; i < num_addresses; i++)
if (at24->client[i])
i
。。。。。。
}
at24_bin_write函数à调用at24_eeprom_write函数如下:
mutex_lock(&at24->lock);
while (count) {
ssize_t status;
status = at24_eeprom_write(at24, buf, off, count);
if (status <= 0) {
if (retval == 0)
retval = status;
break;
}
buf += status;
off += status;
count -= status;
retval += status;
}
mutex_unlock(&at24->lock);
at24_eeprom_write函数如下:
static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf,
unsigned offset, size_t count)
{
struct i
struct i
。。。。。。
timeout = jiffies + msecs_to_jiffies(write_timeout);
do {
write_time = jiffies;
if (at24->use_smbus) {
status = i
offset, count, buf);
if (status == 0)
status = count;
} else {
status = i
if (status == 1)
status = count;
}
。。。。。。
/* REVISIT: at HZ=100, this is sloooow */
msleep(1);
} while (time_before(write_time, timeout));
。。。。。。
}
i
int i
{
。。。。。。
if (adap->algo->master_xfer) {
。。。。。。
if (in_atomic() || irqs_disabled()) {
ret = mutex_trylock(&adap->bus_lock);
if (!ret)
return -EAGAIN;
} else {
mutex_lock_nested(&adap->bus_lock, adap->level);
}
ret = adap->algo->master_xfer(adap,msgs,num);
mutex_unlock(&adap->bus_lock);
。。。。。。
}
到这里要涉及到具体CPU的I
static const struct i
.master_xfer = s
.functionality = s
};
s
static int s
struct i
{
。。。。。。
for (retry = 0; retry < adap->retries; retry++) {
ret = s
if (ret != -EAGAIN)
return ret;
。。。。。。
}
s
static int s
{
。。。。。
spin_lock_irq(&i
i
i
i
i
i
s
s
spin_unlock_irq(&i
。。。。。
}
s
static void s
struct i
{
。。。。。。
writeb(addr, i
//write slave addr to IICDS
ndelay(i
writel(iiccon, i
//write to IICCON,start
stat |= S
writel(stat, i
}
上述s
s
概括
对于I
E2PROM驱动drivers/i
I
drivers/i
drivers/i
drivers/i
实际发送数据在drivers/i