免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

Zynqlinux的I2C驅動學習筆記(一)

最近在用米爾的Z-TURN BOARD單板做小項目。順便也加強學習I2C驅動,記一篇做記錄。
I2C總線知識非常簡單,SDA,SCL,他們的時序規則是:I2C總線是由數據線SDA和時鐘SCL構成的串行總線,可發送和接收數據。在CPU與被控IC之間、IC與IC之間進行雙向傳送,最高傳送速率100kbps。各種被控制電路均并聯在這條總線上,但就像電話機一樣只有撥通各自的號碼才能工作,所以每個電路和模塊都有唯一的地址,在信息的傳輸過程中,I2C總線上并接的每一模塊電路既是主控器(或被控器),又是發送器(或接收器),這取決于它所要完成的功能。CPU發出的控制信號分為地址碼和控制量兩部分,地址碼用來選址,即接通需要控制的電路,確定控制的種類;控制量決定該調整的類別(如對比度、亮度等)及需要調整的量。這樣,各控制電路雖然掛在同一條總線上,卻彼此獨立,互不相關。

創新互聯公司是一家專業的成都網站建設公司,我們專注網站設計制作、成都網站建設、網絡營銷、企業網站建設,買友情鏈接廣告投放為企業客戶提供一站式建站解決方案,能帶給客戶新的互聯網理念。從網站結構的規劃UI設計到用戶體驗提高,創新互聯力求做到盡善盡美。

I2C總線在傳送數據過程中共有三種類型信號, 它們分別是:開始信號、結束信號和應答信號。

開始信號:SCL為高電平時,SDA由高電平向低電平跳變,開始傳送數據。
結束信號:SCL為高電平時,SDA由低電平向高電平跳變,結束傳送數據。
應答信號:接收數據的IC在接收到8bit數據后,向發送數據的IC發出特定的低電平脈沖,表示已收到數據。CPU向受控單元發出一個信號后,等待受控單元發出一個應答信號,CPU接收到應答信號后,根據實際情況作出是否繼續傳遞信號的判斷。若未收到應答信號,由判斷為受控單元出現故障。

在LINUX系統初始化的過程中,通過 i2c_register_board_info,將所需要的I2C從設備加入一個名為_i2c_board_list雙向循環鏈表,系統在成功加載I2C主設備adapt后,就會對這張鏈表里所有I2C從設備逐一地完成 i2c_client的注冊。

也就是說,i2c_client和i2c_adapter都是由i2c_core來維護的。

在xilinx-linux中,i2c從設備是通過dts文件傳遞給內核的,內核通過zynq_init_machine函數注冊所有的i2c從設備,i2c_client.

I2C的linux必須知道4個結構體:i2c_adapter,i2c_algorithm,i2c_client,i2c_driver
struct i2c_adapter {
struct module owner;
unsigned int class; / classes to allow probing for /
const struct i2c_algorithm algo; / the algorithm to access the bus
/
void *algo_data;

/ data fields that are valid for all devices /
struct rt_mutex bus_lock;

int timeout; / in jIFfies /
int retries;
struct device dev; / the adapter device
/

int nr;
char name[48];
struct completion dev_released;

struct mutex userspace_clients_lock;
struct list_head userspace_clients;

struct i2c_bus_recovery_info *bus_recovery_info;
};

i2c總線控制器數據依附于algo_data,比如xi2cps,s3c24xx_i2c。

struct device dev;成員表明i2c_adapter是一個硬件,對應SoC上的I2C控制器。而i2c_algorithm則是這個I2C控制器的底層驅動程序。

同理:
struct i2c_client {
unsigned short flags; / div., see below /
unsigned short addr; / chip address - NOTE: 7bit /
/ addresses are stored in the /
/ LOWER 7 bits
/
char name[I2C_NAME_SIZE];
struct i2c_adapter adapter; / the adapter we sit on /
struct i2c_driver driver; / and our access routines /
struct device dev; / the device structure /
int irq; / irq issued by device
/
struct list_head detected;
};

struct i2c_client代表一個掛載到i2c總線上的i2c從設備,該設備所需要的數據結構,其中包括
該i2c從設備所依附的i2c主設備 struct i2c_adapter adapter
該i2c從設備的驅動程序struct i2c_driver
driver
作為i2c從設備所通用的成員變量,比如addr, name等
該i2c從設備驅動所特有的數據,依附于dev->driver_data下,在i2c_driver中的probe函數中設置這個結構體成員。比如eeprom的eeprom_data。
所有i2c從設備組成的雙向鏈表:detected

struct device dev表明struct i2c_client代表的是一個硬件,比如eeprom芯片,或則rtc芯片,通過i2c總線連接到i2c_adapter硬件上。
而i2c_driver則是這個i2c_client芯片硬件的驅動程序。

我們一般會對每個I2C字符設備定義一個私有信息結構體,而i2c_client一般被包含在這個私有信息結構體中。看過LDR3源代碼的hacker應該比較清楚。

i2c_client依附于i2c_adapter,也就是I2C設備和I2C總線控制器的對應關系,一個i2c_adapter可以掛接多個i2c_client,i2c_adapter的struct list_head userspace_clients;結構成員就是所有client的鏈表。

linux的最新版本基本上支持目前所有的I2C適配器硬件和I2C從設備,但是對于工程師來說,可能要面臨各種情況:為i2c_adapter和i2c_client編寫驅動程序。

二、I2C核心
I2C核心是源碼位于drivers/i2c/i2c-core.c,它并不依賴于硬件平臺的接口函數,是I2C總線驅動和設備驅動的紐帶。

增加/刪除i2c_adapter
int i2c_add_adapter(struct i2c_adapter adapter) //調用i2c_register_adapter()
int i2c_del_adapter(struct i2c_adapter
adapter)

增加/刪除i2c_driver
int i2c_register_driver(struct module owner, struct i2c_driver driver)
int i2c_add_driver(struct i2c_driver driver) //調用i2c_register_driver
void i2c_del_driver(struct i2c_driver
driver)

增加/刪除i2c_client
struct i2c_client i2c_new_device(struct i2c_adapter adap, struct i2c_board_info const info)
void i2c_unregister_device(struct i2c_client
client)

注:在2.6.30版本之前使用的是i2c_attach_client()和i2c_detach_client()函數。之后attach被merge到了i2c_new_device中,而detach直接被unregister取代。實際上這兩個函數內部都是調用了device_register()和device_unregister()

I2C傳輸、發送接收
int i2c_transfer(struct i2c_adapter adap, struct i2c_msg msgs, int num)
int i2c_master_send(struct i2c_client client,const char buf ,int count)
int i2c_master_recv(struct i2c_client client, char buf ,int count)
i2c_transfer()函數用于進行I2C 適配器和I2C 設備之間的一組消息交互,i2c_master_send()函數和i2c_master_recv()函數內部會調用i2c_transfer()函數分別完成一條寫消息和一條讀消息。
i2c_transfer()本身不能和硬件完成消息交互,它尋找i2c_adapter對應的i2c_algorithm,要實現數據傳送就要實現i2c_algorithm的master_xfer(),這個函數與具體的硬件有關,大部分時間由廠商完成。
i2c_transfer()通過調用__i2c_transfer()完成I2C通訊:
int __i2c_transfer(struct i2c_adapter adap, struct i2c_msg msgs, int num)
{
unsigned long orig_jiffies;
int ret, try;

/ Retry automatically on arbitration loss /
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;
}

return ret;

}

可見retries為重傳嘗試次數,timeout為超時時間。

三、Linux I2C總線驅動
1、I2C適配器的加載和卸除
加載:申請硬件資源,比如IO地址,中斷號,調用i2c_add_adapter加載適配器
i2c_add_adapter中會調用i2c_register_adapter函數
static int i2c_register_adapter(struct i2c_adapter *adap)
{
device_register(&adap->dev); //完成I2C主設備adapter的注冊,即注冊object和發送uevent等
i2c_scan_static_board_info(adap); //注冊i2c_clienlt
}

static void i2c_scan_static_board_info(struct i2c_adapter adapter)
{
struct i2c_devinfo
devinfo;

down_read(&__i2c_board_lock);
list_for_each_entry(devinfo, &i2c_board_list, list) {
if (devinfo->busnum == adapter->nr
&& !i2c_new_device(adapter,
&devinfo->board_info))
dev_err(&adapter->dev,
“Can’t create device at 0x%02x\n”,
devinfo->board_info.addr);
}
up_read(&
i2c_board_lock);
}

i2c_new_device調用device_register注冊i2c從設備。
那么,這個I2C從設備組成的雙向循環鏈表,是什么時候通過什么方式建立起來的呢?
以 /arch/ARM/mach-pxa/saar.c 為例
static void __init saar_init(void)
{
saar_init_i2c();
}

static void __init saar_init_i2c(void)
{
pxa_set_i2c_info(NULL);
i2c_register_board_info(0, ARRAY_AND_SIZE(saar_i2c_info));
}

static struct i2c_board_info saar_i2c_info[] = {
[0] = {
.type = “da9034”,
.addr = 0x34,
.platform_data = &saar_da9034_info,
.irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO83)),
},
};

/ drivers/i2c/i2c-boardinfo.c /
int __init i2c_register_board_info(int busnum, structi2c_board_info const info, unsigned len)
{
struct i2c_devinfo
devinfo;
devinfo->board_info = *info;
list_add_tail(&devinfo->list, &__i2c_board_list); //將I2C從設備加入該鏈表中
}

標題名稱:Zynqlinux的I2C驅動學習筆記(一)
當前路徑:http://m.newbst.com/article16/ihpcgg.html

成都網站建設公司_創新互聯,為您提供品牌網站設計網站策劃網站排名品牌網站制作網站營銷建站公司

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

成都做網站