Linux I2C Driver - 使用str8131(5)static int str8131_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num){ struct i2c_msg *i2c; u8 i; if (num != 1 && num != 2) // 我們預期的動作,其數目只會是 1 或 2個 i2c_msg { TRACE("An unexpected situation, num=%d\n", num); return -EIO; } if(clock != current_clock) str8131_i2c_init(); for (i=0; i { if (msgs[i].flags & I2C_M_TEN) // 我們這裡並不支援 10 bit chip address { TRACE("Presently the driver does not handle extended addressing\n"); return -EIO; } if (msgs[i].len == 0) return 0; // 長度為0就不用做了 } i2c = &msgs[0]; // 至少要有一個 i2c_msg if (num == 2) // 通常 2的話,就是指 W_R(Write_Read) { // In general, the num=2 send W_R sequence message if (i2c->flags != 0) // 0:write ,W_R第一個i2c_msg的flag必須要為0來表示為 土地買賣write { TRACE("An unexpected situation, i2c[0]->flags != write\n"); return -EIO; } i2c = &msgs[1]; // ,W_R第二個i2c_msg的flag必須要為I2C_M_RD來表示為 read if ((i2c->flags & I2C_M_RD) == 0) // The msg[1] should be read { TRACE("An unexpected situation, i2c[1]->flags != read\n"); return -EIO; } if (i2c_write_read(msgs) != 0) // 做 write and read的動作 { TRACE("i2c_write_read failed\n"); return -EIO; } } else // 1的話,可能是讀或寫 { if (i2c->flags & I2C_M_RD) // read { if (i2c_read(msgs) != 0) 房地產 { TRACE("i2c_read failed\n"); return -EIO; } } else // write { if (i2c_write(msgs) != 0) { TRACE("i2c_write failed\n"); return -EIO; } } } // Return the number of messages processed, or the error code. return num;接下來我們看i2c_read 、 i2c_write、i2c_write_read三個函式,這裡要先注意的是,儘量不要改變傳進來的 i2c_msg的內容,可能因為它是指標,和kernel實做時會用到,這裡修改它可能會造成一些非預期的結果。把它當作 const,只讀取就好了。當初手賤的去改變傳進來的 msgs的len來當做迴圈的計數,就發現怎麼出現一些奇怪的結果><我們在傳輸時都會呼叫 I2C_Command來做傳輸,這時會把 i2c 的 slave address 左移1位元(i2c->addr << 1),這是因為 i2c的規定,最右邊設計裝潢的那個bit 是用來表示讀或寫。所以當 user-space 傳進來的 slave addr為0x50時,這裡會變成 0xa0static int i2c_read(struct i2c_msg msgs[]){ u32 read_data = 0; u16 i, read_len, read_i2c_len; struct i2c_msg *i2c; i = 0; i2c = &msgs[0]; read_i2c_len = i2c->len; TRACE("read_i2c_len=%d\n", read_i2c_len); while (read_i2c_len) { // To count maximum length of read at a time if (read_i2c_len > I2C_MAX_DATA_LEN) { read_len = I2C_MAX_DATA_LEN; read_i2c_len -= I2C_MAX_DATA_LEN; } else { read_len = read_i2c_len; read_i2c_len = 0; } if (I2C_Command( I2C_READ_ONLY_CMD, (i2c->addr<<1), 0, 0, read_len-1, &read_data) != 0) 禮服{ TRACE("read_only_command failed\n"); return -EIO; } TRACE("i=%d, read_len=%d, read_data=0x%x\n", i, read_len, read_data); memcpy(i2c->buf+i, &read_data, read_len); i += I2C_MAX_DATA_LEN; } return 0;}i2c_read 就是依傳進來的 i2c->len,來判斷要讀取多少位元,這裡的I2C_MAX_DATA_LEN為4,這是cpu暫存器上的限制,所以假設傳進來的 len 為10,那我們就讀 4、4、2, 把資料拷貝到msgs->buf裡。我們呼叫I2C_Command來傳輸資料。static int i2c_write(struct i2c_msg msgs[]){ const u8 addr_len = 2; u8 first_addr, second_addr; u16 i, index, write_len, write_i2c_data_len; u32 write_data=0; struct i2c_msg *i2c; i = 1; i2c = &msgs[0]; index = i2c->buf[0]; write_i2c_data_len = i2c->len - 1; // Subtract legnth of index from i2c->len if (write_i2c_data_len == 0) // only write index { first_addr = (index>>8&0xff); 買屋 second_addr = (index>>0&0xff); write_data |= (first_addr<<0) | (second_addr<<8); if(I2C_Command( I2C_WRITE_ONLY_CMD , (i2c->addr<<1), I2C_DATA_LEN_2_BYTE, write_data, 0 , NULL) != 0) { TRACE("write_only_command failed\n"); return -EIO; } TRACE("Write index only, index=%d\n", index); } else { while (write_i2c_data_len) { write_data = 0; first_addr = (index>>8&0xff); second_addr = (index>>0&0xff); write_data |= (first_addr<<0) | (second_addr<<8); // To count maximum length of write data at a time 21世紀房屋仲介 if (write_i2c_data_len > I2C_MAX_WRITE_DATA_LEN) { write_len = I2C_MAX_WRITE_DATA_LEN; write_i2c_data_len -= I2C_MAX_WRITE_DATA_LEN; } else { write_len = write_i2c_data_len; write_i2c_data_len = 0; } write_data |= ((u32)i2c->buf[i] << 16); if (write_len > 1) write_data |= ((u32)i2c->buf[i+1] << 24); write_len += addr_len; TRACE("write:: i=%d, write_data=0x%x, write_len=%d, index=%d, i2c->addr=0x%x, i2c->len=%d\n" , i, write_data, write_len, index, i2c->addr, 有巢氏房屋i2c->len); if(I2C_Command( I2C_WRITE_ONLY_CMD , (i2c->addr<<1) , write_len-1, write_data , 0, NULL) != 0) { TRACE("write_only_command failed\n"); return -EIO; } i += I2C_MAX_WRITE_DATA_LEN; index += I2C_MAX_WRITE_DATA_LEN; // Move index to next address } } return 0;}i2c_write 和 i2c_read類似,只是 write時要寫入 index和資料,i2c_read時並沒有寫入 index。先判斷傳進來的 len 的大小,如果是 1 的話,那就代表只有傳 index,因為如果沒有含index,是寫不進去的。所以第一個byte都把它認為 index。如果不是1的話,我們就使用 loop來寫入資料,每次寫入都會帶 1 個 byte 的 index,因為要移到新的位置,而最大的寫入為4 東森房屋bytes,但寫入時的index要轉換為 2 bytes(實際上index 的最大可為2 bytes,但那是支援I2C_M_TEN時才會是 2 bytes,我們這裡不支援,只支援 7 bit模式,所以為1 byte),可算出 (4) - (2 bytes的index) = (2 bytes的資料)。一次最大可帶 2 bytes 的資料。自已有試過先寫入一次 index,然後寫入不帶 index(4 bytes)的資料,可惜沒有成功,index不會自已移動。如果可以的話這樣的方法會比較有效率。因為除了第一次要 2 bytes的資料,之後每次可以寫入 4 bytes的資料。static int i2c_write_read(struct i2c_msg msgs[]){ u32 read_data=0, write_data=0; u16 i, index, read_len, read_i2c_len; u8 first_addr, second_addr; struct i2c_msg *i2c; i = 0; index = msgs[0].buf[0]; i2c = &msgs[1]; read_i2c_len = i2c->len; while (read_i2c_len) { first_addr = (index>>8 & 0xff); second_addr = (index>>0 & 0xff); write_data |= (first_addr<<0) | (second_addr<<8); // To count maximum length of read at a time if (read_i2c_len > I2C_MAX_DATA_LEN) { read_len = I2C_MAX_DATA_LEN; 保濕面膜 read_i2c_len -= I2C_MAX_DATA_LEN; } else { read_len = read_i2c_len; read_i2c_len = 0; } if(I2C_Command( I2C_WRITE_READ_CMD , (i2c->addr<<1) , I2C_DATA_LEN_2_BYTE, write_data , read_len-1, &read_data) != 0) { TRACE("write_read_command failed\n"); return -EIO; } memcpy(i2c->buf+i, &read_data, read_len); i += I2C_MAX_DATA_LEN; index += I2C_MAX_DATA_LEN; // Move index to next address } return 0;}前面 wirte 和 read 的合體,先寫入 index ,再做讀取的動作,因為光做讀取,是讀不到資料的。
.msgcontent .wsharing ul li { 信用卡代償text-indent: 0; }
分享
Facebook
Plurk
YAHOO!
.msgcontent .wsharing ul li { 信用卡代償text-indent: 0; }
分享
Plurk
YAHOO!
全站熱搜
留言列表