国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
RTC實(shí)時(shí)時(shí)鐘驅(qū)動(dòng)

RTC 實(shí)時(shí)時(shí)鐘驅(qū)動(dòng)收藏

 RTC 實(shí)時(shí)時(shí)鐘驅(qū)動(dòng)

-------I2C軟件模擬通信

 

 

內(nèi)核版本: linux-2.4.21

文檔設(shè)計(jì): 侯輝華

    : 1.01

時(shí)    : 2007/06/10

 

 

 

 

 

 

內(nèi)容簡(jiǎn)介: 介紹接在I2C總線上RTC實(shí)時(shí)時(shí)鐘設(shè)備的驅(qū)動(dòng), 使用軟件模擬的方法完成I2C的通信; 介紹了Linux下的時(shí)鐘系統(tǒng), 以及I2C的層次結(jié)構(gòu).

 

 

目錄索引:

 

一.       Linux下的時(shí)鐘系統(tǒng)簡(jiǎn)介.

二.       Linux對(duì)時(shí)間的表示.

三.       Linux時(shí)鐘中斷的初始化及處理.

四.       RTC設(shè)備驅(qū)動(dòng)程序.

五.       I2C總線讀寫.

.  Linux下的I2C驅(qū)動(dòng)層次結(jié)構(gòu)..
.  Linux下的時(shí)鐘系統(tǒng)簡(jiǎn)介

 

實(shí)際上,linux系統(tǒng)有兩個(gè)時(shí)鐘:一個(gè)是由主板電池驅(qū)動(dòng)的“Real Time Clock”也叫做RTC或者叫CMOS時(shí)鐘,硬件時(shí)鐘。當(dāng)操作系統(tǒng)關(guān)機(jī)的時(shí)候,用這個(gè)來記錄時(shí)間,但是對(duì)于運(yùn)行的系統(tǒng)是不用這個(gè)時(shí)間的。另一個(gè)時(shí)間是 “System clock”也叫內(nèi)核時(shí)鐘或者軟件時(shí)鐘,是由軟件根據(jù)時(shí)間中斷來進(jìn)行計(jì)數(shù)的,內(nèi)核時(shí)鐘在系統(tǒng)關(guān)機(jī)的情況下是不存在的,所以,當(dāng)操作系統(tǒng)啟動(dòng)的時(shí)候,內(nèi)核時(shí)鐘是要讀取RTC時(shí)間來進(jìn)行時(shí)間同步.

 
linux
的內(nèi)核時(shí)間實(shí)際上是記錄從197011日距離現(xiàn)在的秒數(shù),并且以GMT(格林尼治時(shí)間)(或者叫UTC- Coordinated Universal Time)為標(biāo)準(zhǔn), UTC是不隨著DST(夏令時(shí))變換,需要有變化的是由應(yīng)用程序自身來完成時(shí)間的轉(zhuǎn)換。

 

.  Linux對(duì)時(shí)間的表示

通常,操作系統(tǒng)可以使用三種方法來表示系統(tǒng)的當(dāng)前時(shí)間與日期:①最簡(jiǎn)單的一種方法就是直接用一個(gè)64位的計(jì)數(shù)器來對(duì)時(shí)鐘滴答進(jìn)行計(jì)數(shù)。②第二種方法就是用一個(gè)32位計(jì)數(shù)器來對(duì)秒進(jìn)行計(jì)數(shù),同時(shí)還用一個(gè)32位的輔助計(jì)數(shù)器對(duì)時(shí)鐘滴答計(jì)數(shù),之子累積到一秒為止。因?yàn)?/span>232次方超過136年,因此這種方法直至22世紀(jì)都可以讓系統(tǒng)工作得很好。③第三種方法也是按時(shí)鐘滴答進(jìn)行計(jì)數(shù),但是是相對(duì)于系統(tǒng)啟動(dòng)以來的滴答次數(shù),而不是相對(duì)于相對(duì)于某個(gè)確定的外部時(shí)刻;當(dāng)讀外部后備時(shí)鐘(如RTC)或用戶輸入實(shí)際時(shí)間時(shí),根據(jù)當(dāng)前的滴答次數(shù)計(jì)算系統(tǒng)當(dāng)前時(shí)間。

Linux通常都采用第三種方法來維護(hù)系統(tǒng)的時(shí)間與日期, 通過時(shí)鐘點(diǎn)滴進(jìn)行計(jì)時(shí)的基礎(chǔ)原理, 可以參看下面介紹的參考文檔, 主要原理是通過硬件的中斷累積來計(jì)時(shí), 但必要要設(shè)置硬件中斷一次所須的時(shí)間, 一般具體的不同的芯片都不同, EP9302系統(tǒng)具體設(shè)置如下:

1.        EP93xx系列芯片有四個(gè)Timer計(jì)時(shí)器, 使用的是Timer1, 與具體芯片相關(guān)的內(nèi)容在如下兩個(gè)文件:

linux-2.4.21\arch\arm\mach-ep93xx\time.c,

linux-2.4.21\arch\arm\mach-ep93xx\time.h

2.        針對(duì)整個(gè)Arm體系的時(shí)鐘相關(guān)文件為:

linux-2.4.21\arch\arm\kernel\time.c

時(shí)鐘中斷計(jì)時(shí)的主要相關(guān)函數(shù)為如下兩個(gè):

1.        ep93xx_gettimeoffset()的作用就是返回距最近一次時(shí)鐘中斷發(fā)生后, Timer已經(jīng)累積的時(shí)間(但還未滿足引發(fā)一次時(shí)鐘中斷), 這個(gè)時(shí)間值單位為微秒, 獲取當(dāng)前時(shí)間時(shí), 就是累計(jì)已經(jīng)發(fā)生的Timer中斷次數(shù)所經(jīng)歷的時(shí)間, 然后加上這個(gè)即將要發(fā)生中斷所過去的時(shí)間, 這樣取得當(dāng)前時(shí)間的精度是相當(dāng)高的.

2.        LATCH的含義是指一次時(shí)鐘中斷要經(jīng)過多少個(gè)Timer時(shí)鐘周期, TIMER1LOAD寄存器設(shè)置的就是這個(gè)值,ep93xx的計(jì)時(shí)器Timer1會(huì)將這個(gè)值一直遞減直至0, 如此就引發(fā)一次時(shí)鐘中斷, 然后又重LATCH重頭開始遞減.

3.        xtime記載的即為系統(tǒng)自開機(jī)以來的當(dāng)前時(shí)間, 單位為秒, 精確度為微秒. 因此在開機(jī)時(shí)必須從RTC當(dāng)中取得真實(shí)的時(shí)間來賦此初值, EP93xx系列直接初始此值為其自身所帶RTC模塊的時(shí)間值, RTCDR寄存器是EP93xx所自帶的RTC模塊的寄存器, 其值單位為秒,基準(zhǔn)為相對(duì)1970, 此處即為我們要改動(dòng)的地方.將其值從i2cRTC實(shí)時(shí)芯片中取回賦給它.

static unsigned longep93xx_gettimeoffset(void)

{

         unsigned longhwticks;

         hwticks = LATCH -(inl(TIMER1VALUE) & 0xffff);

         return ((hwticks *tick) / LATCH);

}

void __init ep93xx_setup_timer(void)      //初始化Timer,設(shè)定時(shí)鐘中斷周期

{

         gettimeoffset =ep93xx_gettimeoffset;

         outl(0,TIMER1CONTROL);

         outl(LATCH - 1,TIMER1LOAD);          //設(shè)定Timer經(jīng)多少個(gè)Timer時(shí)鐘周期后產(chǎn)生中斷

         outl(0xc8,TIMER1CONTROL);

         xtime.tv_sec =inl(RTCDR);           //ep93xx內(nèi)部RTC模塊讀取時(shí)間,后將重新從cmos.

}

以下詳細(xì)介紹一下時(shí)鐘點(diǎn)滴計(jì)時(shí)的幾個(gè)基本參數(shù), 以下定義的出處, 除非特別指出, 一般是位于各自不同的平臺(tái)的文件夾下定義:

linux-2.4.21\include\asm-arm\arch-ep93xx

linux-2.4.21\arch\arm\mach-ep93xx\

 

1.        時(shí)鐘周期(clock cycle)的頻率:計(jì)時(shí)器Timer晶體振蕩器在1秒時(shí)間內(nèi)產(chǎn)生的時(shí)鐘脈沖個(gè)數(shù)就是時(shí)鐘周期的頻率, 要注意這個(gè)Timer的時(shí)鐘周期頻率要與時(shí)鐘中斷的頻率區(qū)別開來,  Linux用宏CLOCK_TICK_RATE來表示計(jì)時(shí)器的輸入時(shí)鐘脈沖的頻率(此值在EP93xx上是508KHZ),該宏定義在timex.h頭文件中:

#defineCLOCK_TICK_RATE 508000 /* Underlying HZ */

2.        時(shí)鐘中斷(clock tick):我們知道當(dāng)計(jì)數(shù)器減到0值時(shí),它就在IRQ0上產(chǎn)生一次時(shí)鐘中斷,也即一次時(shí)鐘中斷, 計(jì)數(shù)器的初始值決定了要過多少時(shí)鐘周期才產(chǎn)生一次時(shí)鐘中斷,因此也就決定了一次時(shí)鐘滴答的時(shí)間間隔長(zhǎng)度. EP93xx系統(tǒng)中, Timer1TIMER1LOAD 的值決定過多少時(shí)鐘周期后產(chǎn)生一次時(shí)鐘中斷.

3.        時(shí)鐘中斷的頻率(HZ):也即1秒時(shí)間內(nèi)Timer所產(chǎn)生的時(shí)鐘中斷次數(shù)。確定了時(shí)鐘中斷的頻率值后也就可以確定Timer的計(jì)數(shù)器初值。Linux內(nèi)核用宏HZ來表示時(shí)鐘中斷的頻率,而且在不同的平臺(tái)上HZ有不同的定義值。對(duì)于SPARC、MIPS、ARMi386等平臺(tái)HZ的值都是100。該宏在ARM平臺(tái)上的定義如下(param.h):

#ifndef HZ

#define HZ 100

#endif

據(jù)HZ值,可知每隔(1000msHZ)=10ms發(fā)生一次時(shí)鐘中斷.

 

4.        時(shí)鐘中斷的時(shí)間間隔:Linux用全局變量tick來表示時(shí)鐘中斷的時(shí)間間隔長(zhǎng)度,其實(shí)定義了HZ之后, 即決定了此間隔值, tick變量的單位是微妙(μs), 該變量定義在kernel/timer.c文件中,如下:

long tick =(1000000 + HZ/2) / HZ; /* timer interrupt period */.

5.        LATCHLinux用宏LATCH來定義要設(shè)置到Timer中的值,它表示TImer將沒隔多少個(gè)時(shí)鐘周期產(chǎn)生一次時(shí)鐘中斷。顯然LATCH應(yīng)該由下列公式計(jì)算: LATCH=(1秒之內(nèi)的Timer時(shí)鐘周期個(gè)數(shù))÷(1秒之內(nèi)的時(shí)鐘中斷次數(shù))=CLOCK_TICK_RATE)÷(HZ.

 

. Linux時(shí)鐘中斷的初始化及處理

 

以下著重描述一下時(shí)鐘中斷時(shí)與RTC相關(guān)的修改:

 

文件:linux-2.4.21\arch\arm\kernel\time.c

描述:時(shí)鐘初始化化, start_kernel()當(dāng)中調(diào)用.

void __init time_init(void)

{

         xtime.tv_usec= 0;

         xtime.tv_sec  = 0;

         setup_timer();

}

 

文件:linux-2.4.21\arch\arm\mach-ep93xx\time.h

描述:安裝時(shí)鐘中斷服務(wù)程序,從RTC更新初始化系統(tǒng)時(shí)鐘, time_init()當(dāng)中調(diào)用.

/*

 * Set up timer interrupt, and return thecurrent time in seconds.

*/

static inline void setup_timer(void)

{

         ep93xx_setup_timer(); 

//houhh 20070713...

/////////

         xtime.tv_sec= get_cmos_time();     //RTC設(shè)備中讀取當(dāng)前時(shí)間

         set_rtc= set_cmos_time;                 //初始化更新系統(tǒng)時(shí)間到RTC的函數(shù), do_set_rtc()中調(diào)用

/////////

         timer_irq.handler= ep93xx_timer_interrupt;     //時(shí)鐘中斷服務(wù)程序

         setup_arm_irq(IRQ_TIMER1,&timer_irq);      //安裝時(shí)鐘中斷處理

}

 

文件:linux-2.4.21\arch\arm\mach-ep93xx\time.h

描述:讀寫I2CRTC設(shè)備,軟件模擬方式, 引自i2c-ep93xx.c, 將在下面詳細(xì)介紹.

extern uchar pcf8563_readdata(ucharaddress);

extern int pcf8563_writedata(ucharaddress, uchar mdata);

#define CMOS_READ(addr)                  pcf8563_readdata(addr)

#define CMOS_WRITE(data, addr)         pcf8563_writedata(addr, data)

 

 

 

 

文件:linux-2.4.21\arch\arm\mach-ep93xx\time.h

描述:設(shè)置及讀寫RTC, 主要通過宏CMOS_READ/ CMOS_WRITE完成功能.

unsigned long get_cmos_time(void)

static int set_cmos_time(unsigned longnowtime)

 

文件: linux-2.4.21\arch\arm\mach-ep93xx\time.h

描述:時(shí)鐘中斷服務(wù)程序,并檢測(cè)更新系統(tǒng)時(shí)鐘到RTC, setup_timer()當(dāng)中調(diào)用.

/*

 * IRQ handler for the timer

*/

static void ep93xx_timer_interrupt(intirq, void *dev_id, struct pt_regs *regs)

{

         outl(1, TIMER1CLEAR );

         do_leds();

         do_set_rtc();        //houhh 20070713, 檢測(cè)是否要更新系統(tǒng)當(dāng)前時(shí)間到cmos rtc設(shè)備...

         do_timer(regs);

         do_profile(regs);

}

 

一般認(rèn)為時(shí)鐘中斷計(jì)時(shí)的精度較高,所以在時(shí)鐘中斷服務(wù)程序中會(huì)每隔11分鐘(660)就檢測(cè)一次是否須要將此時(shí)的系統(tǒng)時(shí)間寫回到RTC當(dāng)中, 所以在ep93xx的時(shí)鐘中斷服務(wù)程序中,須要加上do_set_rtc(),關(guān)于這個(gè)函數(shù)具體的功能請(qǐng)具體參見源碼.

 


.  RTC設(shè)備驅(qū)動(dòng)程序

 

主要指出RTC設(shè)備及相關(guān)操作,這一塊相當(dāng)簡(jiǎn)單,RTC時(shí)鐘處理成一簡(jiǎn)單字符設(shè)備.

 

基礎(chǔ)文件結(jié)構(gòu):

static struct file_operationspcf8563_fops = {

         owner:THIS_MODULE,

         ioctl:pcf8563_ioctl,

         open:pcf8563_open,

         release:pcf8563_release,

};

文件:linux-2.4.21\drivers\char\pcf8563_rtc.c

描述: RTC設(shè)備的文件結(jié)構(gòu),指文件打開及釋放操作,其實(shí)最核心的還是ioctl,這里可以進(jìn)行時(shí)間讀取以及時(shí)間設(shè)置操作, 具體使用示例可以參考rtctest.c示例文件.

 

文件:linux-2.4.21\drivers\char\pcf8563_rtc.c

描述:時(shí)間設(shè)置與讀取.

get_rtc_time(struct rtc_time *tm);

Set_rtc_time(struct rtc_time *tm);

 

文件: linux-2.4.21\drivers\charpcf8563_rtc.c

描述: I2C讀寫, 這兩個(gè)函數(shù)是從文件i2c-ep93xx.c中引用的,定義成宏.

extern intpcf8563_writedata(uchar address, uchar mdata);

extern ucharpcf8563_readdata(uchar address);

#definertc_reg_read(x)                   pcf8563_readdata(x)

#definertc_reg_write(x,y)               pcf8563_writedata(x,y)

 

文件: linux-2.4.21\drivers\charpcf8563_rtc.c

描述: 模塊初始化,負(fù)責(zé)注冊(cè)/注消RTC字符設(shè)備.

int __init pcf8563_init(void)

void __exit pcf8563_exit(void)


.  I2C總線讀寫

 

i2c總線讀寫方式為軟件模擬方式,因?yàn)?/span>ep93xx沒有相關(guān)的i2c總線控制器,因此只能通過軟件方式來模擬I2C總線的讀寫, 在調(diào)試過程中遇到如下問題,注意如下即可:

 

1.       注意延時(shí)的時(shí)間,I2C的開始條件與讀寫時(shí)都須要一定的延時(shí),根據(jù)主設(shè)備(ep93xx cpu)的運(yùn)行速度,此延時(shí)必須是一個(gè)穩(wěn)定的時(shí)間,通常采取讀取特定外設(shè)i/o以達(dá)此目的.

2.       注意在改變I2CSDA數(shù)據(jù)線狀態(tài)時(shí),必須是在SCL時(shí)鐘線為低的時(shí)候,因?yàn)楦鶕?jù)開始與結(jié)束條件的要求,開始與結(jié)束條件是在SCL時(shí)鐘線高的時(shí)候SDA拉高或者拉低,所以如果在傳送數(shù)據(jù)時(shí),SCL為高,則會(huì)被當(dāng)成開始或結(jié)束條件,通信失敗.

3.       在讀寫I2C總線時(shí),每傳送或接收一BYTE數(shù)據(jù),必須要進(jìn)行回應(yīng).

Ø        寫回應(yīng):主設(shè)備寫完八位數(shù)據(jù)后,在第九個(gè)周期等待從設(shè)備來拉低SDA作為回應(yīng),因此須先將SDA在第八周期SCL低時(shí)拉高,之后拉高SCL等從設(shè)備回應(yīng),等到從設(shè)備回應(yīng)后拉低SCL,第九周期結(jié)束,一個(gè)BYTE傳送完成.

Ø        讀回應(yīng):主設(shè)備讀從設(shè)備八位數(shù)據(jù)后,也應(yīng)該在第九周期進(jìn)行回應(yīng),分如下兩種情況: 連續(xù)讀n個(gè)字節(jié)時(shí),前n-1個(gè)字節(jié)以拉低作回應(yīng),第n個(gè)字節(jié)則為拉高SDA回應(yīng),因此如若是每次只讀一個(gè)字節(jié),則回應(yīng)為拉高.

4.       操作SDA/SCL PIN時(shí),注意在讀SDA時(shí),將其設(shè)置成輸入狀態(tài).

 

文件: linux-2.4.21\drivers\i2ci2c-ep93xx.c

描述: SDA/SCL PIN腳定義, EP93xxGPIOG口的第0, 1.

#define I2C_SDA_PORT      GPIO_PGDR

#define I2C_SDA_DIR         GPIO_PGDDR

#define I2C_SDA_MASK    0x2            //EEDAT...

#define I2C_SCL_PORT       GPIO_PGDR

#define I2C_SCL_DIR         GPIO_PGDDR

#define I2C_SCL_MASK     0x1            //EECLK...

 

文件: linux-2.4.21\drivers\i2c\ i2c-ep93xx.c

描述: SDA/SCL輸入輸出.

static void bit_ep93xx_setscl(void* data, int state)

{

         unsignedlong flags;

         save_flags(flags);

         outl(inl(I2C_SCL_DIR)| I2C_SCL_MASK, I2C_SCL_DIR);  //tristate pin

         if (state){

                   cli();

                   outl(inl(I2C_SCL_PORT)| I2C_SCL_MASK, I2C_SCL_PORT); // drive pin

         }

         else{

                   cli();

                   outl(inl(I2C_SCL_PORT)& ~I2C_SCL_MASK, I2C_SCL_PORT); // drive pin

         }

         restore_flags(flags);

}

//===========================================================================

///  write SCL pin

//===========================================================================

static void bit_ep93xx_setsda(void* data, int state)

{

         unsignedlong flags;

         save_flags(flags);

         outl(inl(I2C_SDA_DIR)| I2C_SDA_MASK, I2C_SDA_DIR);    //output...

         if (state){

                   cli(); 

                   outl(inl(I2C_SDA_PORT)| I2C_SDA_MASK, I2C_SDA_PORT); // drive pin

         }

         else{

                   cli();

                   outl(inl(I2C_SDA_PORT)& ~I2C_SDA_MASK, I2C_SDA_PORT); // drive pin

         }                

         restore_flags(flags);

}

 

具體有關(guān)I2C總線軟件模擬通信部分,參考源碼.


.  Linux下的I2C驅(qū)動(dòng)層次結(jié)構(gòu).

 

Linux最大的特點(diǎn),就是將一系列的驅(qū)動(dòng)中共有的東西抽象出來,大大提高代碼的共享與利用率,這樣使具體硬件設(shè)備的驅(qū)動(dòng)作者無須關(guān)注驅(qū)動(dòng)中共性的部分,I2C驅(qū)動(dòng)同樣如此,這里我不打算詳細(xì)的分析I2C的層次結(jié)構(gòu),只是簡(jiǎn)單的陪析一下其大略的層次, 并指出幾個(gè)不易理解的地方。

 

1.      適配器層(adapters)

描述: 這一層簡(jiǎn)單的理解,可以理解成是I2C總線的抽象,它提供訪問I2C總線的方法規(guī)則,并包含在物理總線上適用此規(guī)則進(jìn)行I2C通信的I2C設(shè)備, 而且I2C設(shè)備并不須是在同一條總線上,只須滿足相同的訪問I2C總線方法規(guī)則,且設(shè)備地址不重重疊.

2.      I2C設(shè)備驅(qū)動(dòng)層(i2c client driver)

描述:具體到每個(gè)掛在I2C上的設(shè)備, 針對(duì)特定的設(shè)備可以有不同的驅(qū)動(dòng), 諸如設(shè)備標(biāo)志ID, 設(shè)備名稱, 設(shè)備屬性志Flag, 還有就是設(shè)備連接及拔除的相應(yīng)處理.

3.      I2C數(shù)據(jù)傳送規(guī)則層(algorithms)

描述: 針對(duì)具體的I2C總線, 可以有不同的數(shù)據(jù)傳輸規(guī)則, 分為三種:

ü        大體來說如果本身就有I2C控制器的, I2C使用起來就比較簡(jiǎn)單, 傳輸入數(shù)據(jù)時(shí)就是讀寫一些寄存器即可.

ü        通地軟件模擬方式進(jìn)行數(shù)據(jù)傳輸, I2C中這個(gè)規(guī)則被稱為algorithmsfor bit-shift, 這種編程起來稍微麻煩一些, 要用軟件模擬I2C的通信協(xié)議規(guī)則.

ü        通過每三方總線間接的連接I2C總線的, ISA總線, 此時(shí)I2C是間接連接在系統(tǒng)上, 這種方式通常與具體的所連接上的總線相關(guān).

另外, 還有一種規(guī)則是針對(duì)SMBus總線, 這個(gè)總線是Intel推出的兼容I2C協(xié)議的, 可能一次傳送一個(gè)字,兩個(gè)字節(jié),多個(gè)字節(jié)等等, 這里沒有用到,并不詳述, 由此我們可以理會(huì)I2C設(shè)計(jì)者設(shè)計(jì)的結(jié)構(gòu)的靈活程度.

 

以上簡(jiǎn)述了I2C驅(qū)動(dòng)層次結(jié)構(gòu), 現(xiàn)在具體的就PCF8563 RTC來描述每一層具體由哪些文件組成, 結(jié)合實(shí)際的驅(qū)動(dòng)文件說明:

 

1.      適配器層----------------- i2c-core.c, i2c-dev.c

2.      I2C設(shè)備驅(qū)動(dòng)層---------pcf8563-rtc.c

3.      I2C數(shù)據(jù)傳送規(guī)則層--- i2c-algo-bit.c,i2c-ep93xx

 

大體對(duì)照I2C驅(qū)動(dòng)的層次結(jié)構(gòu), 結(jié)合以上文件來看, 可以理解I2C的驅(qū)動(dòng).

 

I2C驅(qū)動(dòng)代碼中不易理解的幾點(diǎn):

 

結(jié)合在代碼閱讀時(shí)我所經(jīng)歷的過程, 說明以下幾點(diǎn)不易明白的地方:

 

1.      i2c設(shè)備的識(shí)別

描述:每個(gè)I2C設(shè)備有自己特定的設(shè)備地址,通常為讀地址及寫地址; 2.4版當(dāng)中是采取遍歷的方式來查找I2C設(shè)備應(yīng)該, 每個(gè)i2c設(shè)備都會(huì)標(biāo)明自己所處的地址,描述i2c設(shè)備所處地址范圍的結(jié)構(gòu)比較復(fù)雜, 它包括描述i2c設(shè)備所處地址范圍, 要忽略的地址范圍, 應(yīng)當(dāng)強(qiáng)制檢測(cè)的范圍等, 個(gè)人感覺些結(jié)構(gòu)設(shè)計(jì)過于重復(fù), 2.6版中已經(jīng)簡(jiǎn)化.

具體的I2C設(shè)備檢測(cè)時(shí), 即根據(jù)這些地址, 0~0x7f開始檢測(cè), 檢測(cè)時(shí)會(huì)跳出過無須檢測(cè)的范圍. 比如一i2c設(shè)備寫地址為0xa0, 則在此描述時(shí)給出的地址值是0x50, 因此在真實(shí)寫此設(shè)備時(shí), 必須將地址左移兩位得真實(shí)地址.

 

2.4i2c地址描述結(jié)構(gòu):

structi2c_client_address_data {

      unsigned short *normal_i2c;

      unsigned short *normal_i2c_range;

      unsigned short *probe;

      unsigned short *probe_range;

      unsigned short *ignore;

      unsigned short *ignore_range;

      unsigned short *force;

};

2.6i2c地址描述結(jié)構(gòu):

structi2c_client_address_data {

      unsigned short *normal_i2c;

      unsigned short *probe;

      unsigned short *ignore;

      unsigned short **forces;

};

 

2.      i2c設(shè)備設(shè)備的讀與寫

描述:設(shè)備地址一般為7, 此地址是字節(jié)的高七位, 最低的一位用于描述是讀設(shè)備還是寫設(shè)備, 因此可知I2C設(shè)備讀寫地址必然相連, 因此讀寫地址轉(zhuǎn)換通常為最低位或上1, 或者清除1, 另外還記得這里描述的地址必須左移兩位, 因?yàn)榻o出的設(shè)備地址是以低七位形式給出.

寫地址一般是小于讀地址, 所以通常讀地址都是寫地址或上1即得, 因此在設(shè)備驅(qū)動(dòng)結(jié)構(gòu)i2c_client, 僅用一addr成員來描述設(shè)備地址.

具體來說, i2c-algo-bit.c文件下的bit_doAddress()函數(shù), 如果是七位地址的I2C總線, 其處理如下, 將設(shè)備地址左移兩位得寫地址,然后或上1, 即得讀地址.

addr= ( msg->addr << 1 );

if(flags & I2C_M_RD )

addr|= 1;

3.      i2c adapters algorithms的管理.

描述: 每一個(gè)adapters 都會(huì)有一個(gè)唯一的標(biāo)志, 如我們的EP93xx則定義為I2C_HW_B_EP93XX, 每一種algorithms都也有一個(gè)ID標(biāo)志, bit-shift algorithms的標(biāo)志即為: I2C_ALGO_BIT.,  關(guān)于這些標(biāo)志的定義, 可以查看i2c-id.h文件.

        具體的, 添加一個(gè)bit-shift algorithmsadapters , 可以調(diào)用i2c_bit_add_bus()函數(shù), 這個(gè)調(diào)用由用戶發(fā)出, 一般在模塊加載的init函數(shù)中調(diào)用, 每當(dāng)加入一個(gè)adapters, 都會(huì)檢測(cè)已經(jīng)注冊(cè)的i2c driver設(shè)備是否適用此adapters, 如果適用則調(diào)用該i2c設(shè)備driver下的attach_adapter, 通知設(shè)備發(fā)現(xiàn)其相應(yīng)適配器, 只有找到相應(yīng)適配器, 該設(shè)備才能使用i2c總線.

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
嵌入式Linux系統(tǒng)中I2C總線設(shè)備的驅(qū)動(dòng)設(shè)計(jì):ee365
linux驅(qū)動(dòng)概述和常用串行總線
深入學(xué)習(xí) RTC時(shí)鐘庫(kù) DS3231
單片機(jī)與高精度時(shí)鐘芯片DS3231的接口應(yīng)用
Arduino UNO DS3231高精度RTC芯片 制作時(shí)鐘
淺析 Linux 中的時(shí)間編程和實(shí)現(xiàn)原理,第 3 部分: Linux 內(nèi)核的工作
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服