Firefly-RK3399開發(fā)板上有 9 個(gè)片上 I2C 控制器,各個(gè) I2C 的使用情況如下表:
本文主要描述如何在該開發(fā)板上配置 I2C。
配置 I2C 可分為兩大步驟:
-
定義和注冊 I2C 設(shè)備
-
定義和注冊 I2C 驅(qū)動
下面以配置 GSL3680 為例。
在注冊I2C設(shè)備時(shí),需要結(jié)構(gòu)體 i2c_client 來描述 I2C 設(shè)備。然而在標(biāo)準(zhǔn)Linux中,用戶只需要提供相應(yīng)的 I2C 設(shè)備信息,Linux就會根據(jù)所提供的信息構(gòu)造 i2c_client 結(jié)構(gòu)體。
用戶所提供的 I2C 設(shè)備信息以節(jié)點(diǎn)的形式寫到 dts 文件中,如下所示:
在定義 I2C 驅(qū)動之前,用戶首先要定義變量 of_device_id 和 i2c_device_id 。
of_device_id 用于在驅(qū)動中調(diào)用dts文件中定義的設(shè)備信息,其定義如下所示:
static struct of_device_id gsl_ts_ids[] = { {.compatible = "gslX680"}, {} };
定義變量 i2c_device_id:
static const struct i2c_device_id gsl_ts_id[] = { {GSLX680_I2C_NAME, 0}, {} }; MODULE_DEVICE_TABLE(i2c, gsl_ts_id);
i2c_driver 如下所示:
static struct i2c_driver gsl_ts_driver = { .driver = { .name = GSLX680_I2C_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(gsl_ts_ids), }, #ifndef CONFIG_HAS_EARLYSUSPEND //.suspend = gsl_ts_suspend, //.resume = gsl_ts_resume, #endif .probe = gsl_ts_probe, .remove = gsl_ts_remove, .id_table = gsl_ts_id, };
注:變量id_table指示該驅(qū)動所支持的設(shè)備。
使用i2c_add_driver函數(shù)注冊 I2C 驅(qū)動。
i2c_add_driver(&gsl_ts_driver);
在調(diào)用 i2c_add_driver 注冊 I2C 驅(qū)動時(shí),會遍歷 I2C 設(shè)備,如果該驅(qū)動支持所遍歷到的設(shè)備,則會調(diào)用該驅(qū)動的 probe 函數(shù)。
在注冊好 I2C 驅(qū)動后,即可進(jìn)行 I2C 通訊。
-
向從機(jī)發(fā)送信息:
int i2c_master_send(const struct i2c_client *client, const char *buf, int count) { int ret; struct i2c_adapter *adap = client->adapter; struct i2c_msg msg; msg.addr = client->addr; msg.flags = client->flags & I2C_M_TEN; msg.len = count; msg.buf = (char *)buf; ret = i2c_transfer(adap, &msg, 1); /* * If everything went ok (i.e. 1 msg transmitted), return #bytes * transmitted, else error code. */ return (ret == 1) ? count : ret; }
-
向從機(jī)讀取信息:
int i2c_master_recv(const struct i2c_client *client, char *buf, int count) { struct i2c_adapter *adap = client->adapter; struct i2c_msg msg; int ret; msg.addr = client->addr; msg.flags = client->flags & I2C_M_TEN; msg.flags |= I2C_M_RD; msg.len = count; msg.buf = buf; ret = i2c_transfer(adap, &msg, 1); /* * If everything went ok (i.e. 1 msg received), return #bytes received, * else error code. */ return (ret == 1) ? count : ret; } EXPORT_SYMBOL(i2c_master_recv);
A1: 請檢查硬件上拉是否給電。
A2: 返回值為-6表示為NACK錯(cuò)誤,即對方設(shè)備無應(yīng)答響應(yīng),這種情況一般為外設(shè)的問題,常見的有以下幾種情況:
-
I2C地址錯(cuò)誤,解決方法是測量I2C波形,確認(rèn)是否I2C 設(shè)備地址錯(cuò)誤;
-
I2C slave 設(shè)備不處于正常工作狀態(tài),比如未給電,錯(cuò)誤的上電時(shí)序等;
-
時(shí)序不符合 I2C slave設(shè)備所要求也會產(chǎn)生Nack信號。
A3: 這時(shí)需要調(diào)用兩次i2c_transfer, I2C read 拆分成兩次,修改如下:
static int i2c_read_bytes(struct i2c_client *client, u8 cmd, u8 *data, u8 data_len) { struct i2c_msg msgs[2]; int ret; u8 *buffer; buffer = kzalloc(data_len, GFP_KERNEL); if (!buffer) return -ENOMEM;; msgs[0].addr = client->addr; msgs[0].flags = client->flags; msgs[0].len = 1; msgs[0].buf = &cmd; ret = i2c_transfer(client->adapter, msgs, 1); if (ret < 0) { dev_err(&client->adapter->dev, "i2c read failed\n"); kfree(buffer); return ret; } msgs[1].addr = client->addr; msgs[1].flags = client->flags | I2C_M_RD; msgs[1].len = data_len; msgs[1].buf = buffer; ret = i2c_transfer(client->adapter, &msgs[1], 1); if (ret < 0) dev_err(&client->adapter->dev, "i2c read failed\n"); else memcpy(data, buffer, data_len); kfree(buffer); return ret; }
-
Linux
+關(guān)注
關(guān)注
87文章
11326瀏覽量
209961 -
嵌入式主板
+關(guān)注
關(guān)注
7文章
6086瀏覽量
35476 -
Firefly
+關(guān)注
關(guān)注
2文章
538瀏覽量
7073
發(fā)布評論請先 登錄
相關(guān)推薦
使用Firefly RK3399開發(fā)板燒錄鏡像為什么會失敗呢
FireFly RK3399開發(fā)板與NanoPC T4開發(fā)板有何不同呢
Firefly -RK3399電源適配器介紹
![<b class='flag-5'>Firefly</b> -<b class='flag-5'>RK3399</b>電源適配器<b class='flag-5'>介紹</b>](https://file.elecfans.com/web1/M00/AB/49/o4YBAF22zsCACha_AAESYwVcVZw399.jpg)
Firefly-RK3399--PWM介紹
![<b class='flag-5'>Firefly-RK3399</b>--PWM<b class='flag-5'>介紹</b>](https://file.elecfans.com/web1/M00/AE/41/o4YBAF3XQ3mAEZT1AAFhCM0tNzE156.png)
Firefly-RK3399開發(fā)板
![<b class='flag-5'>Firefly-RK3399</b><b class='flag-5'>開發(fā)板</b>](https://file.elecfans.com/web1/M00/AB/49/o4YBAF22zueAeF6SAAFr3dJ-JTc908.jpg)
Firefly-RK3399--LED 介紹
![<b class='flag-5'>Firefly-RK3399</b>--LED <b class='flag-5'>介紹</b>](https://file.elecfans.com/web1/M00/AB/A1/pIYBAF22zxOARAmgAAAYL4yA0lw306.png)
Firefly-RK3399--ADC開發(fā)板介紹
![<b class='flag-5'>Firefly-RK3399</b>--ADC<b class='flag-5'>開發(fā)板</b><b class='flag-5'>介紹</b>](https://file.elecfans.com/web1/M00/AE/9A/pIYBAF3XSW2AGzt6AAIRdlroTGQ426.png)
簡單介紹RK3399開發(fā)板、RK3399主板的相關(guān)參數(shù)
RK3399開發(fā)板屏幕切換控制的方式介紹
![<b class='flag-5'>RK3399</b><b class='flag-5'>開發(fā)板</b>屏幕切換控制的方式<b class='flag-5'>介紹</b>](https://file.elecfans.com//web1/M00/E7/30/o4YBAGBhKkaAaQeCAAC3DLdULLE450.jpg)
評論