i 2 cサブシステムのwrite()


アプリケーション層がwrite()関数を呼び出して最初に入るのはi 2 cクラスデバイスのwrite関数、すなわちi 2 cdev_fopsのwriteメソッド.
ここのi 2 cdev_fopsは,システム内のすべてのi 2 c系デバイスの動作に対応する.すなわち,システム内のすべてのi 2 c adapterのread()
write()open()close()ioctl()などの操作は、まずi 2 cクラスi 2 cdev_を呼び出すfopsでのメソッド、i 2 cクラスでのメソッド
さらにadapter対応アルゴリズムi 2 c_を探しますAlgorithm、ここでs 3 c 2440はs 3 c 24 xx_に対応するi2c_algorithm.
i 2 cの操作方法
1.まずopen
2.ioctl at 24 c 02のアドレス設定
3.write()
1.openデバイス/dev/i 2 c-0
Openシステム呼び出しによりfopsに最後に呼び出されたi 2 cdev_Open関数.
static int i2cdev_open(struct inode *inode, struct file *file)
{
	。。。 。。。
	adap = i2c_get_adapter(i2c_dev->adap->nr);
	if (!adap)
		return -ENODEV;

	。。。 。。。
	client = kzalloc(sizeof(*client), GFP_KERNEL);
	if (!client) {
		i2c_put_adapter(adap);
		return -ENOMEM;
	}
	snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
	client->driver = &i2cdev_driver;

	client->adapter = adap;
	file->private_data = client;

	return 0;
}

この関数の役割は、/dev/i 2 c-0のデバイス番号に基づいて対応するadapterを見つけ、新しいclientに保存することです.
なお、ここでのclientは、i 2 c駆動モデルのコードに関係なく、ドライバ内のclientとは異なり、ここでのclientはバスに登録されません.
ここでのクライアントは,クライアントアドレス情報などを保存するためにのみ用いられる.
最後にこのclietnをfile->private_に保存します.dataではioctl()write()open()などの操作で使用します.
2. ioctl
アプリケーションレイヤがioctlを呼び出すとi 2 cdev_に呼び出されます.ioctl()関数、ここではI 2 C_を使用しますSLAVE_FORCEは、at 24 c 02のアドレスを設定するために使用される.
3.write
writeはシステム呼び出しによってfopsのi 2 cdev_を最後に実行するwrite関数
static ssize_t i2cdev_write(struct file *file, const char __user *buf,
		size_t count, loff_t *offset)
{
	。。。 。。。
	struct i2c_client *client = file->private_data;
        。。。 。。。
	tmp = memdup_user(buf, count);
	。。。 。。。
	ret = i2c_master_send(client, tmp, count);
	。。。 。。。
}

write関数では、open操作でfile->private_に保存することが最初に行われていることがわかります.dataのクライアント取り出し
そしてmemdup_を通ってuser関数は、ユーザ空間のバッファをカーネル空間にコピーします.最後の呼び出し関数i 2 c_master_send()
int i2c_master_send(struct i2c_client *client, const char *buf, int count)
{
	。。。 。。。	
	ret = i2c_transfer(adap, &msg, 1);
        。。。 。。。
}

i 2 c_でmastr_send関数ではまずmsg構造体を初期化し,clientのアドレス,現在コピーが必要なデータ長などの情報を
msgに充填します.最後にこのmsgをパラメータとしてi 2 c_に渡すtransfer関数.i 2 cの読み書き中、送信された情報はすべて
msgによって完成したのは、device addressを除いて.デバイスaddress情報は単独で送信、残りはmsg.bufで完了
ここでi 2 c_Transferの3番目のパラメータは1で、このパラメータは駆動が送信するたびにmsgの個数を教えて、ここでは1に設定します
毎回msgを1つしか送信できないことを示します.
i2c_Transfer()関数は次のとおりです.
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
                 。。。 。。。
               orig_jiffies = jiffies;
               for (ret = 0, try = 0; try <= adap->retries; try++) {
			ret = adap->algo->master_xfer(adap, msgs, num);
			if (ret != -EAGAIN)
				break;
			if (time_after(jiffies, orig_jiffies + adap->timeout))
				break;
		}
		 。。。 。。。
}
この関数が関連処理を完了した後、adapterのalgorithmを直接呼び出してデータを送信します.ここで、i 2 c-s 3 c 2440ファイルです.
s3c24xx_i2c_probe総登録アルゴリズム
i2c->adap.algo    = &s3c24xx_i2c_algorithm;

s3c24xx_i2c_Algorithmアルゴリズムは具体的に以下の通りです.
static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
	.master_xfer		= s3c24xx_i2c_xfer,
	.functionality		= s3c24xx_i2c_func,
};

したがって、関数s 3 c 24 x_を直接呼び出すことに相当する.i2c_xfer
s3c24xx_i2c_xferはs 3 c 24 xx_に対してのみi2c_doxferの簡単なパッケージ、実際の処理
関数s 3 c 24 xx_i2c_doxferで.このs 3 c 24 x_を重点的に分析します.i2c_doxfer関数
static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
			      struct i2c_msg *msgs, int num)
{
	。。。 。。。
	ret = s3c24xx_i2c_set_master(i2c);
	。。。 。。。
        i2c->msg     = msgs;
        i2c->msg_num = num;
        i2c->msg_ptr = 0;
        i2c->msg_idx = 0;
        i2c->state   = STATE_START;
        
        s3c24xx_i2c_enable_irq(i2c);
        s3c24xx_i2c_message_start(i2c, msgs);
	spin_unlock_irq(&i2c->lock);

	timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
        。。。 。。。

}

この関数で最初に呼び出されたのはs 3 c 24 xx_です.i2c_set_master関数、master(すなわちadapter)が
忙しい状態にある.忙しいと休眠して1 ms後に再度照会し、合計400回照会し、400 ms後にi 2 cがまだ忙しい状態であると放棄することに相当する.
マスターが空いたら、初期化に関する操作をします.初期化操作で注意が必要なのはi 2 c->state=STATE_START、この状態で
ビットは、i 2 cが現在開始状態であるか、書き込み状態であるか、読み取り状態であるかを示す.
次にクリアランス関数
	s3c24xx_i2c_enable_irq(i2c);
オープン割り込み.次に関数を呼び出します
	s3c24xx_i2c_message_start(i2c, msgs);

をクリックして、最初のバイト、すなわちdevice addressを送信します.最初のバイトの送信が完了すると、s 3 c 2440のi 2 cコントローラが中断する.
s 3 c 2440のi 2 c割り込みは1で発生する.1バイトの送信または受信を完了する.ブロードキャストコールまたはアドレスマッチング時3.バス仲裁に失敗しました.
そして、最初のバイトdevice addressの送信が完了すると、関数は
        timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
は現在のプロセスを待機状態にし、待機プロセッサはmsg.buf送信完了(すなわちi 2 c-msg_num=0は送信完了を示す)は、HZ*5(5秒)以内にmsgを送信完了していない場合、送信タイムアウトとなる.
割り込み処理関数はs 3 c 24 x_i2c_probe関数登録、s 3 c 24 xx_i2c_irq().
s3c24xx_i2c_IRqの操作は簡単で、最も重要なステップは関数i 2 sを呼び出すことです.s3c_irq_nextbyte.にある
i2s_s3c_irq_nextbyte関数で
static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
{
	。。。 。。。
	switch (i2c->state) {

	。。。 。。。

	case STATE_START:
		/* last thing we did was send a start condition on the
		 * bus, or started a new i2c message
		 */

		if (iicstat & S3C2410_IICSTAT_LASTBIT &&
		    !(i2c->msg->flags & I2C_M_IGNORE_NAK)) {
			/* ack was not received... */

			dev_dbg(i2c->dev, "ack was not received
"); s3c24xx_i2c_stop(i2c, -ENXIO); goto out_ack; } if (i2c->msg->flags & I2C_M_RD) i2c->state = STATE_READ; else i2c->state = STATE_WRITE; /* terminate the transfer if there is nothing to do * as this is used by the i2c probe to find devices. */ if (is_lastmsg(i2c) && i2c->msg->len == 0) { dev_dbg(i2c->dev, "last msg sended
"); s3c24xx_i2c_stop(i2c, 0); goto out_ack; } if (i2c->state == STATE_READ) goto prepare_read; /* fall through to the write state, as we will need to * send a byte as well */ case STATE_WRITE: /* we are writing data to the device... check for the * end of the message, and if so, work out what to do */ if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { if (iicstat & S3C2410_IICSTAT_LASTBIT) { dev_dbg(i2c->dev, "WRITE: No Ack
"); s3c24xx_i2c_stop(i2c, -ECONNREFUSED); goto out_ack; } } retry_write: if (!is_msgend(i2c)) { byte = i2c->msg->buf[i2c->msg_ptr++]; writeb(byte, i2c->regs + S3C2410_IICDS); /* delay after writing the byte to allow the * data setup time on the bus, as writing the * data to the register causes the first bit * to appear on SDA, and SCL will change as * soon as the interrupt is acknowledged */ ndelay(i2c->tx_setup); } else if (!is_lastmsg(i2c)) { /* we need to go to the next i2c message */ dev_dbg(i2c->dev, "WRITE: Next Message
"); i2c->msg_ptr = 0; i2c->msg_idx++; i2c->msg++; /* check to see if we need to do another message */ if (i2c->msg->flags & I2C_M_NOSTART) { if (i2c->msg->flags & I2C_M_RD) { /* cannot do this, the controller * forces us to send a new START * when we change direction */ s3c24xx_i2c_stop(i2c, -EINVAL); } goto retry_write; } else { /* send the new start */ s3c24xx_i2c_message_start(i2c, i2c->msg); i2c->state = STATE_START; } } else { /* send stop */ s3c24xx_i2c_stop(i2c, 0); } break; 。。。 。。。 }

ここの関数は先にSTATE_に入ることがわかりますSTART、そしてi 2 c状態を読み書き状態に切り替え、関数
必要なバイトをコードに通す
                        byte = i2c->msg->buf[i2c->msg_ptr++];
			writeb(byte, i2c->regs + S3C2410_IICDS);

			/* delay after writing the byte to allow the
			 * data setup time on the bus, as writing the
			 * data to the register causes the first bit
			 * to appear on SDA, and SCL will change as
			 * soon as the interrupt is acknowledged */

			ndelay(i2c->tx_setup);
は、s 3 c 2440のICDSレジスタ送信に書き込まれ、次いで割り込みが発生し、i 2 s_が実行されるs3c_irq_nextbyte->i2s_s3c_irq_nextbyte
msg.までbufのすべてのデータが送信されます.
すべてのデータの送信が完了すると、i 2 s_s3c_irq_nextbyte関数でs 3 c 24 xx_を実行i2c_stop()関数
static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
{
	unsigned long iicstat = readl(i2c->regs + S3C2410_IICSTAT);

	dev_dbg(i2c->dev, "STOP
"); /* stop the transfer */ iicstat &= ~S3C2410_IICSTAT_START; writel(iicstat, i2c->regs + S3C2410_IICSTAT); i2c->state = STATE_STOP; s3c24xx_i2c_master_complete(i2c, ret); s3c24xx_i2c_disable_irq(i2c); }

この関数でいくつかのスイープ作業を実行し、最後に関数s 3 c 24 xx_を呼び出します.i2c_master_complete()
static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret)
{
	dev_dbg(i2c->dev, "master_complete %d
", ret); i2c->msg_ptr = 0; i2c->msg = NULL; i2c->msg_idx++; i2c->msg_num = 0; if (ret) i2c->msg_idx = ret; wake_up(&i2c->wait); }

そしてwake_up関数は、i 2 cキューに待機している他の操作を起動します.
このデータは書き終わりました.読み取りプロセスは似ています.
次はat 24 c 02の読み書きテストコードを添付します