struct machine_desc以及i2c的學(xué)習(xí)
struct machine_desc {
? ?unsigned int ? ? ? ?nr; ? ? /* architecture number ?*/
? ?const char ? ? ?*name; ? ? ?/* architecture name ? ?*/
? ?unsigned long ? ? ? atag_offset; ? ?/* tagged list (relative) */
? ?const char *const ? *dt_compat; /* array of device tree
? ? ? ? ? ? ? ? ? ? ? ? * 'compatible' strings */
? ?unsigned int ? ? ? ?nr_irqs; ? ?/* number of IRQs */
#ifdef CONFIG_ZONE_DMA
? ?unsigned long ? ? ? dma_zone_size; ?/* size of DMA-able area */
#endif
? ?unsigned int ? ? ? ?video_start; ? ?/* start of video RAM ? */
? ?unsigned int ? ? ? ?video_end; ?/* end of video RAM */
? ?unsigned char ? ? ? reserve_lp0 :1; /* never has lp0 ? ?*/
? ?unsigned char ? ? ? reserve_lp1 :1; /* never has lp1 ? ?*/
? ?unsigned char ? ? ? reserve_lp2 :1; /* never has lp2 ? ?*/
? ?char ? ? ? ? ? ?restart_mode; ? /* default restart mode */
? ?struct smp_operations ? *smp; ? ? ? /* SMP operations ? */
? ?bool ? ? ? ? ? ?(*smp_init)(void);
? ?void ? ? ? ? ? ?(*fixup)(struct tag *, char **,
? ? ? ? ? ? ? ? ? ? struct meminfo *);
? ?void ? ? ? ? ? ?(*reserve)(void);/* reserve mem blocks ?*/
? ?void ? ? ? ? ? ?(*map_io)(void);/* IO mapping function ?*/
? ?void ? ? ? ? ? ?(*init_early)(void);
? ?void ? ? ? ? ? ?(*init_irq)(void);
? ?void ? ? ? ? ? ?(*init_time)(void);
? ?void ? ? ? ? ? ?(*init_machine)(void);
? ?void ? ? ? ? ? ?(*init_late)(void);
#ifdef CONFIG_MULTI_IRQ_HANDLER
? ?void ? ? ? ? ? ?(*handle_irq)(struct pt_regs *);
#endif
? ?void ? ? ? ? ? ?(*restart)(char, const char *);
};
這個結(jié)構(gòu)體定義在mach/arch.h,在內(nèi)核移植中起著相當(dāng)重要的作用,內(nèi)核通過struct machine_desc來控制系統(tǒng)體系架構(gòu)相關(guān)部分的初始化,這個結(jié)構(gòu)體內(nèi)包含了體系相關(guān)的初始化函數(shù):
map_io(),init_irq(),init_machine()等。
用戶可以在具體的板卡設(shè)備文件中初始化該結(jié)構(gòu)體,一般初始化形式為:
MACHINE_START(GSIA18S, "GS_IA18_S")
? ?.init_time ?= at91sam926x_pit_init,
? ?.map_io ? ? = at91_map_io,
? ?.handle_irq = at91_aic_handle_irq,
? ?.init_early = gsia18s_init_early,
? ?.init_irq ? = at91_init_irq_default,
? ?.init_machine ? = gsia18s_board_init,
MACHINE_END
MACHINE_START是一個宏,作用是定義一個struct machine_desc的實例并初始化,放在section(.arch.info.init),是初始化數(shù)據(jù),內(nèi)核啟動完成后其所占用的內(nèi)存會被釋放。
struct machine_desc的各個成員會在內(nèi)核啟動的不同時期被調(diào)用。
map_io:用于對I/O端口的靜態(tài)映射,會在系統(tǒng)初始化過程中被調(diào)用,流程為:start_kernel()->setup_arch()->paging_init()
inti_machine:會在arch/arm/kernel/setup.c中調(diào)用,放在arch_init段里面,會自動按照順序被調(diào)用。
init_irq:調(diào)用順序:start_kernel()->init_IRQ()->init_arch_irq()中被調(diào)用
I2C:
I2c通信是適用于小數(shù)據(jù)量的一種片間低速同步通信協(xié)議,速率一般在幾百kb,標(biāo)準(zhǔn)模式為100kb/s,快速模式為400kb/s,同時也是一種帶有沖突檢測和仲裁機制的多主機總線,但是同一時刻只會有一個主機。
連接在總線上的每個器件都會有唯一地址。在嵌入式領(lǐng)域,一般都是以soc上的i2c控制器作為主機,連接在總線上的i2c外設(shè)做從機。常見的設(shè)備由:e2prom、傳感器等。
在主機與從機的通信中,“start”信號是必須的,結(jié)束信號和應(yīng)答信號可以沒有。起始信號后面必須發(fā)送一個8bit的數(shù)據(jù),其中7bit從機地址+1bit標(biāo)志位。
標(biāo)志位分為:“write”表示數(shù)據(jù)的流向是從主機到從機,“read”表示數(shù)據(jù)流向是從機到主機。
應(yīng)答信號:ACK表示收到數(shù)據(jù)。NACK表示未收到數(shù)據(jù)(發(fā)送放接收到這個數(shù)據(jù)后會停止發(fā)數(shù)據(jù))
i2c的通信方式為:
一、主機向從機寫數(shù)據(jù):
1、主機獲取SDA的控制權(quán),將其在SCL處于高電平的狀態(tài)下拉低,發(fā)出“start”信號,
2、主機通過廣播的方式發(fā)出自己想要與之通信的從機地址(8bit數(shù)據(jù),最低為為write,表示數(shù)據(jù)的傳輸方向是:主機---->從機)
3、從機發(fā)出“ack”,告知主機收到
4、主機接收到響應(yīng)后,發(fā)出自己要操作的從機內(nèi)部寄存器的地址(8bit數(shù)據(jù))
5、從機接收到寄存器地址后發(fā)出“ack”信號
6、主機發(fā)出8bit數(shù)據(jù)
7、從機接收到數(shù)據(jù)后向主機發(fā)出應(yīng)答信號。
8、主機發(fā)出“stop”
二、主機從主機讀數(shù)據(jù):
1、主機獲取SDA的控制權(quán),在SCL高電平狀態(tài)下將其拉低,發(fā)出“start”信號
2、主機發(fā)出8bit數(shù)據(jù)(7bit是從機地址,1bit表示數(shù)據(jù)的傳輸方向:主機---->從機)
3、主機發(fā)出8bit數(shù)據(jù)(從機中的寄存器地址)
主機會再次發(fā)送start信號
4、主機發(fā)出8bit數(shù)據(jù)(7bit是從機地址,1bit表示數(shù)據(jù)的傳輸方向:從機---->主機)
5、從機向主機發(fā)出應(yīng)答后,主機釋放SDA,從機獲得控制權(quán),并向主機發(fā)出8bit數(shù)據(jù)
6、主機接收數(shù)據(jù)后,向從機發(fā)出應(yīng)答信號
7、主機重新獲得SDA控制權(quán),發(fā)出“stop”
總結(jié):i2c通信是一種半雙工通信,同一時刻總線上的數(shù)據(jù)傳輸方向是單一的。讀寫操作的步驟雖然分為好記步,但可以這樣理解:
1、不管是寫還是讀,都需要先將從機地址和從機中需要進行操作的寄存器地址發(fā)送給從機,讓其做好準(zhǔn)備,所以這里的操作標(biāo)志位應(yīng)當(dāng)是write。
2、如果是寫操作,那么不需要修改數(shù)據(jù)的傳輸方向,執(zhí)行完步驟1后,從機向主機發(fā)出應(yīng)答,主機便進行寫數(shù)據(jù)。
3、如果是讀操作,那么執(zhí)行完步驟1以后,需要主機再次發(fā)出start信號,并且發(fā)出從機地址和操作標(biāo)志位組成的8bit數(shù)據(jù),將數(shù)據(jù)傳輸方向變更為從機--->主機。
主機在收到從機的應(yīng)答信號后,就會釋放掉SDA,從機獲取SDA控制權(quán),向主機發(fā)出數(shù)據(jù),直到主機發(fā)出非應(yīng)答信號,傳輸結(jié)束。
如何使用示波器測量i2c信號:
1、使用雙通道示波器,將SDA與SCL信號接入示波器。成功接入的標(biāo)志是兩個表筆的電平都是高電平。
2、設(shè)置示波器:trigger menu中,將觸發(fā)方式設(shè)置為邊沿觸發(fā)(下降沿),信源選擇SDA所接的通道。觸發(fā)模式選擇auto,如果需要單次則將觸發(fā)模式設(shè)置為signal。
建議先整體看一下,再單次觸發(fā)。
波形分析關(guān)鍵點:
如果在第九個時鐘周期SDA信號出現(xiàn)異常的尖峰,應(yīng)該是因為從機將SDA控制權(quán)交還給主機造成的。