當前位置:編程學習大全網 - 編程語言 - linux下怎麽直接使用iic接口

linux下怎麽直接使用iic接口

利用Linux中IIC設備子系統移植IIC設備驅動

背景描述

IIC總線在嵌入式系統中應用十分廣泛,常見的有eeprom,rtc。壹般的處理器會包含IIC的控制器,用來完成IIC時序的控制;另外壹方面,由於IIC的時序簡單,使用GPIO口來模擬時序也是常見的做法。面對不同的IIC控制器,各種各樣的芯片以及linux源碼,如何更快做好IIC設備驅動。

問題描述

在我們的方案中,我們會用到eeprom,rtc以及tw2865。由於Hi3520的IIC控制器設計有問題,無法正常使用。而IIC控制器的SDA和SCL管腳正好是和兩個GPIO管腳復用的。Hisi將控制gpio來實現IIC的時序,從而對IIC設備進行操作。這種設計方式簡單明了,但使用IIC子系統,可以更方便的移植和維護其他的設備驅動。

問題分析

Hisi對於gpio口,rtc芯片以及tw2865的處理方式如下:將gpio口做成壹個模塊化的驅動,該驅動模擬IIC時序,並向外提供壹些函數接口,比如:EXPORT_SYMBOL(gpio_i2c_read_tw2815);等。對於具體的rtc芯片,將其註冊為壹個misc設備,並利用gpio模塊導出的函數進行rtc芯片的配置操作。

其實對於linux-2.6.24\drivers\i2c目錄下代碼,我們可以加以利用。

Linux的IIC字結構分為三個組成部分:

IIC核心

IIC核心提供了IIC總線驅動和設備驅動的註冊、註銷方法,IICalgorithm上層的、與具體適配器無關的代碼以及探測設備、檢測設備地址的上層代碼。

IIC總線驅動

IIC總線驅動是對IIC硬件體系結構中適配器端的實現。

IIC設備驅動

IIC設備驅動是對IIC硬件體系總設備端的實現。

我們查看下該目錄下的makefile和kconfig:

obj-$(CONFIG_I2C_BOARDINFO) +=i2c-boardinfo.o

obj-$(CONFIG_I2C) += i2c-core.o

obj-$(CONFIG_I2C_CHARDEV) +=i2c-dev.o

obj-y +=busses/ chips/ algos/

i2c-core.c就是IIC核心,buses中的文件是主流處理器中IIC總線的總線驅動,而chips中的文件就是常用芯片的驅動,algos中的文件實現了壹些總線適配器的algorithm,其中就包括我們要用到的i2c-algo-bit.c文件。

我們首先利用i2c-gpio.c和i2c-algo-bit.c做好總線驅動。

在i2c-gpio.c中,module_init?i2c_gpio_init?platform_driver_probe(&i2c_gpio_driver,i2c_gpio_probe);

將其註冊為platform虛擬總線的驅動。

在staticint __init i2c_gpio_probe(struct platform_device *pdev)中,

定義了如下三個結構體:

structi2c_gpio_platform_data *pdata;//平臺相關的gpio的設置

structi2c_algo_bit_data *bit_data;//包含algorithm的具體函數,setor

get SDA和SCL

structi2c_adapter *adap;//適配器

i2c_gpio_probe主要做了下面幾件事:

填充bit_data結構的各個函數指針,關聯到具體的操作SDA和SCl函數。

填充adap結構,adap->algo_data= bit_data;

pdata= pdev->dev.platform_data;

bit_data->data= pdata;

pdev->dev->driver_data= adap;

在i2c-core中註冊適配器類型。

inti2c_bit_add_numbered_bus(struct i2c_adapter *adap)

在staticint i2c_bit_prepare_bus(struct i2c_adapter *adap)中

adap->algo= &i2c_bit_algo;

將i2c_bit_algo與adap關聯上。

static const structi2c_algorithm i2c_bit_algo = {

.master_xfer = bit_xfer,

.functionality = bit_func,

};

其中,master_xfer函數指針就是IIC傳輸函數指針。

I2c-algo-bit.c還實現了IIC開始條件,結束條件的模擬,發送字節,接收字節以及應答位的處理。

i2c-gpio.c中的i2c_gpio_setsda_val等函數是與具體平臺gpio相關的。

修改對應arch-hi3520v100目錄下的gpio.h中的各個函數,這些函數是通過操作寄存器來控制gpio的方向和值。

在對應mach-hi3520v100中的platform-devices.c中添加如下:

static structi2c_gpio_platform_data pdata = {

.sda_pin = 1<<0,

.sda_is_open_drain = 1,

.scl_pin = 1<<1,

.scl_is_open_drain = 1,

.udelay = 4, /* ~100 kHz */

};

static struct platform_devicehisilicon_i2c_gpio_device = {

.name = "i2c-gpio",

.id = -1,

.dev.platform_data = &pdata,

};

static struct platform_device*hisilicon_plat_devs[] __initdata = {

&hisilicon_i2c_gpio_device,

};

int __inithisilicon_register_platform_devices(void)

{

platform_add_devices(hisilicon_plat_devs,ARRAY_SIZE (hisilicon_plat_devs));

return 0;

}

通過platform添加devices和driver,使得pdev->dev.platform_data=pdata

綜合上面的過程,我們完成了adapter的註冊,並將用gpio口模擬的algorithm與adapter完成了關聯。

這樣,在rtc-x1205.c中,x1205_attach函數利用i2c核心完成client和adap的關聯。

在x1205_probe函數中填充i2c_client結構體,並調用i2c_attach_client通知iic核心。

接著註冊rtc驅動。

最後我們要讀取時間,就需要構造i2c_msg結構體,如下所示:

struct i2c_msg msgs[] = {

{ client->addr, 0, 2,dt_addr }, /* setup read ptr */

{ client->addr, I2C_M_RD,8, buf }, /* read date */

};

/* read date registers */

if((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {

dev_err(&client->dev,"%s: read error\n", __FUNCTION__);

return -EIO;

}

dt_addr是寄存器的地址,I2C_M_RD表示iicread。

  • 上一篇:小白該如何學習單片機?
  • 下一篇:VS2010開發Qt,怎麽顯示qDebug信息
  • copyright 2024編程學習大全網