国产成人精品三级麻豆,色综合天天综合高清网,亚洲精品夜夜夜,国产成人综合在线女婷五月99播放,色婷婷色综合激情国产日韩

當(dāng)前位置:首頁(yè) > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 >
Linux下的platform機(jī)制
時(shí)間:2018-08-16作者:華清遠(yuǎn)見(jiàn)

作者:楊老師,華清遠(yuǎn)見(jiàn)教育科技集團(tuán)講師。

從Linux2.6起,內(nèi)核引入了一套新的驅(qū)動(dòng)管理和注冊(cè)機(jī)制:Platform_device和Platform_driver,F(xiàn)在Linux中大部分的設(shè)備驅(qū)動(dòng)都可以使用這套機(jī)制,總線為platform_bus,設(shè)備用platform_device表示,驅(qū)動(dòng)用platform_driver進(jìn)行注冊(cè)。

Linux的這種platform driver機(jī)制和傳統(tǒng)的device_driver機(jī)制相比,一個(gè)十分明顯的優(yōu)勢(shì)在于platform機(jī)制將本身的資源注冊(cè)進(jìn)內(nèi)核,由內(nèi)核統(tǒng)一管理,在驅(qū)動(dòng)程序中使用這些資源時(shí)通過(guò)platform_device提供的標(biāo)準(zhǔn)接口進(jìn)行申請(qǐng)并使用。這樣提高了驅(qū)動(dòng)和資源管理的獨(dú)立性,并且擁有較好的可移植性和安全性。下面是SPI驅(qū)動(dòng)層次示意圖,Linux中的SPI總線可理解為SPI控制器引出的總線:

 

 

和傳統(tǒng)的驅(qū)動(dòng)一樣,platform機(jī)制也分為三個(gè)步驟:

1、總線注冊(cè)階段:

內(nèi)核啟動(dòng)初始化時(shí)的main.c文件中的start_kernel() →rest_init() →kernel_init()→do_basic_setup()→driver_init()→platform_bus_init()→ bus_register(&platform_bus_type),注冊(cè)了一條platform總線(虛擬總線,platform_bus)。

2、添加設(shè)備階段:

int platform_device_register(struct platform_device *pdev); //注冊(cè)一個(gè)設(shè)備

int platform_add_devices(struct platform_device **pdevs, int ndev); //注冊(cè)多個(gè)設(shè)備

設(shè)備注冊(cè)的時(shí)候Platform_device_register()/platform_device_add()→(pdev→dev.bus = &platform_bus_type)→device_add(),就這樣把設(shè)備給掛到虛擬的總線上。

由分析可以知道: 使用逆向的分析可以知道:Platform_device_register() 這個(gè)函數(shù)在arch/arm/mach-s5pv210/mach-smdkv210.c 文件中使用了,

文件位置346行: platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));

然后在349行處 定義了一個(gè)宏 :MACHINE_START(SMDKV210, "SMDKV210") ,跟蹤這個(gè)宏可以知道這個(gè)宏的詳細(xì)定義,

#define MACHINE_START(_type,_name) \

static const struct machine_desc __mach_desc_##_type \

__used \

__attribute__((__section__(".arch.info.init"))) = { \

.nr = MACH_TYPE_##_type, \

.name = _name,

#define MACHINE_END \

};

可以知道段代碼被定義在了.arch.info.init段 由系統(tǒng)的連接腳本指定,具體可以查看 arch/arm/kernel/vmlinux.lds 腳本可以知道

3、驅(qū)動(dòng)注冊(cè)階段:

Platform_driver_register()→driver_register()→bus_add_driver()→driver_attach()→bus_for_each_dev(), 對(duì)在每個(gè)掛在虛擬的platform bus的設(shè)備作__driver_attach()→driver_probe_device(),判斷drv→bus→match()是否執(zhí)行成功,此時(shí)通過(guò)指針執(zhí)行platform_match→strncmp(pdev→name , drv→name , BUS_ID_SIZE),如果相符就調(diào)用really_probe(實(shí)際就是執(zhí)行相應(yīng)設(shè)備的platform_driver→probe(platform_device)。)開(kāi)始真正的探測(cè),如果probe成功,則綁定設(shè)備到該驅(qū)動(dòng)。

從上面可以看出,platform機(jī)制后還是調(diào)用了bus_register() ,

device_add() , driver_register()這三個(gè)關(guān)鍵的函數(shù)。

下面看幾個(gè)結(jié)構(gòu)體

struct platform_device (/include/linux/Platform_device.h)

{

constchar * name;

int id;

struct device dev;

u32 num_resources;

struct resource * resource;

};

Platform_device結(jié)構(gòu)體描述了一個(gè)platform結(jié)構(gòu)的設(shè)備,在其中包含了一般設(shè)備的結(jié)構(gòu)體struct device dev;設(shè)備的資源結(jié)構(gòu)體struct resource * resource;還有設(shè)備的名字const char * name。(注意,這個(gè)名字一定要和后面platform_driver.driver àname相同,原因會(huì)在后面說(shuō)明。)

該結(jié)構(gòu)體中重要的就是resource結(jié)構(gòu),這也是之所以引入platform機(jī)制的原因。

struct resource ( /include/linux/ioport.h)

{

resource_size_t start;

resource_size_t end;

constchar *name;

unsigned long flags;

struct resource *parent, *sibling, *child;

};

其中 flags位表示該資源的類(lèi)型,start和end分別表示該資源的起始地址和結(jié)束地址(/include/linux/Platform_device.h):

struct platform_driver

{

int (*probe)(struct platform_device *);

int (*remove)(struct platform_device *);

void (*shutdown)(struct platform_device *);

int (*suspend)(struct platform_device *, pm_message_t state);

int (*suspend_late)(struct platform_device *, pm_message_t state);

int (*resume_early)(struct platform_device *);

int (*resume)(struct platform_device *);

struct device_driver driver;

};

Platform_driver結(jié)構(gòu)體描述了一個(gè)platform結(jié)構(gòu)的驅(qū)動(dòng)。其中除了一些函數(shù)指針外,還有一個(gè)一般驅(qū)動(dòng)的device_driver結(jié)構(gòu)。

名字要一致的原因:

上面說(shuō)的驅(qū)動(dòng)在注冊(cè)的時(shí)候會(huì)調(diào)用函數(shù)bus_for_each_dev(), 對(duì)在每個(gè)掛在虛擬的platform bus的設(shè)備作__driver_attach()→driver_probe_device(),在此函數(shù)中會(huì)對(duì)dev和drv做初步的匹配,調(diào)用的是drv-

staticint platform_match(struct device * dev, struct device_driver * drv)

{

struct platform_device *pdev = container_of(dev, struct platform_device, dev);

return (strncmp(pdev-

}

是比較dev和drv的name,相同則會(huì)進(jìn)入really_probe()函數(shù),從而進(jìn)入自己寫(xiě)的probe函數(shù)做進(jìn)一步的匹配。所以dev→name和driver→drv→name在初始化時(shí)一定要填一樣的。

不同類(lèi)型的驅(qū)動(dòng),其match函數(shù)是不一樣的,這個(gè)platform的驅(qū)動(dòng),比較的是dev和drv的名字,還記得usb類(lèi)驅(qū)動(dòng)里的match嗎?它比較的是Product ID和Vendor ID。

個(gè)人總結(jié)Platform機(jī)制的好處:

1、提供platform_bus_type類(lèi)型的總線,把那些不是總線型的soc設(shè)備都添加到這條虛擬總線上。使得,總線——設(shè)備——驅(qū)動(dòng)的模式可以得到普及。

2、提供platform_device和platform_driver類(lèi)型的數(shù)據(jù)結(jié)構(gòu),將傳統(tǒng)的device和driver數(shù)據(jù)結(jié)構(gòu)嵌入其中,并且加入resource成員,以便于和Open Firmware這種動(dòng)態(tài)傳遞設(shè)備資源的新型bootloader和kernel 接軌。


發(fā)表評(píng)論

全國(guó)咨詢(xún)電話:400-611-6270,雙休日及節(jié)假日請(qǐng)致電值班手機(jī):15010390966

在線咨詢(xún): 曹老師QQ(3337544669), 徐老師QQ(1462495461), 劉老師 QQ(3108687497)

企業(yè)培訓(xùn)洽談專(zhuān)線:010-82600901,院校合作洽談專(zhuān)線:010-82600350,在線咨詢(xún):QQ(248856300)

Copyright 2004-2018 華清遠(yuǎn)見(jiàn)教育科技集團(tuán) 版權(quán)所有 ,京ICP備16055225號(hào),京公海網(wǎng)安備11010802025203號(hào)