娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

linux設備驅動(16)platfrom詳解

發布者:yunhui最新更新時間:2025-01-22 來源: cnblogs關鍵字:linux  設備驅動 手機看文章 掃描二維碼
隨時隨地手機看文章

1 platfrom的概括

platform總線是區別于實體總線USB、 I2C、SPI 、PIC總線的虛擬總線,一些usb設備選址的話需要通過USB總線來進行尋址,而有些類似于SoC內部外設如led 看門狗 定時器是直接通過內存的尋址空間來進行尋址的,cpu與這些設備通信是不需要總線的,2.6內核以后要對所有設備進行統一管理,通過kset、kobject來建立層次關系,對這些直接通過內存尋址的設備虛擬了一種總線即platform總線,在硬件上實際是沒有這個總線;platform內核純軟件的總線,所有的直接通過內存尋址的設備都映射到這條總線上。設備用platform_device表示,驅動用platform_driver進行注冊。platform由內核進行統一管理,在驅動中使用資源,提高了代碼的安全性和可移植性。更換硬件時只需要修改硬件部分的代碼,其中還一部分代碼是屬于內核中穩定的部分,通用的接口,不用修改。

相對輸入input子系統,platform是對驅動的模型的分離的思想,而input子系統測試分層的思想。

2 平臺總線優點:

(1)可以通過platform總線,可以遍歷所有的platform總線設備;platform本質其實也是kset、kobject,具有kobject的特性

(2)實現設備與驅動的分離,通過platform總線,設備與驅動是分開注冊的,通過platform總線的probe來隨時檢測與設備匹配的驅動,如匹配上即進行這個設備的驅動注冊;

(3)由于上面這個優勢,一個驅動可以供同類的幾個設備使用;

3 platform總線以及platform總線設備驅動的實現流程

platform總線注冊 -->> platform_device注冊 -->> platform_driver注冊 -->> 設備與驅動的匹配 -->> 驅動的注冊

platform總線的工作流程如下圖:

代碼分析

定義位于:driversbaseplatform.c

platform總線的注冊:platform的注冊是linux內核工程師已經設注冊好的;重點是.match = platform_match函數;platform_driver和platform_device就是通過這個函數來匹配的

4 platform_bus

platform是bus的一種,是一種虛擬總線。


1 struct bus_type platform_bus_type = {

2     .name        = 'platform',

3     .dev_attrs    = platform_dev_attrs,

4     .match        = platform_match,

5     .uevent        = platform_uevent,

6     .pm        = &platform_dev_pm_ops,

7 };


4.1platform_bus_init


 1 int __init platform_bus_init(void)

 2 {

 3     int error;

 4 /*清除早期的platform數據和信息(早期的platform建立時sysfs等都沒建立,不完善,所以要這里清掉之前的建立),重新注冊platform*/

 5     early_platform_cleanup();

 6 

 7     error = device_register(&platform_bus);//設備的注冊,在sysfs的device下注冊一個位platform的空文件夾

 8     if (error)

 9         return error;

10     error =  bus_register(&platform_bus_type);//bus的注冊,在sysfs的bus下注冊一個platform的文件夾 ,同時使用platform總線注冊的設備的bus都會被賦值為platform_bus_type,即將來所有設備會在bus下的platform里出現

11     if (error)

12         device_unregister(&platform_bus);

13     return error;

14 }


platform_bus的device,定義如下:


struct device platform_bus = {

    .init_name    = 'platform',

};

4.2 platform_match


platform總線上設備和驅動的匹配規則


 1 /**

 2  * platform_match - bind platform device to platform driver.

 3  * @dev: device.

 4  * @drv: driver.

 5  *

 6  * Platform device IDs are assumed to be encoded like this:

 7  * '', where is a short description of the type of

 8  * device, like 'pci' or 'floppy', and is the enumerated

 9  * instance of the device, like '0' or '42'.  Driver IDs are simply

10  * ''.  So, extract the from the platform_device structure,

11  * and compare it against the name of the driver. Return whether they match

12  * or not.

13  */

14 static int platform_match(struct device *dev, struct device_driver *drv)

15 {

16     struct platform_device *pdev = to_platform_device(dev);

17     struct platform_driver *pdrv = to_platform_driver(drv);

18 

19     /* Attempt an OF style match first */

20     if (of_driver_match_device(dev, drv))

21         return 1;

22 

23     /* Then try ACPI style match */

24     if (acpi_driver_match_device(dev, drv))

25         return 1;

26 

27     /* Then try to match against the id table */

28     if (pdrv->id_table)//如果driver的id_table存在,則只匹配id_table

29         return platform_match_id(pdrv->id_table, pdev) != NULL;

30 

31     /* fall-back to driver name match */

32     return (strcmp(pdev->name, drv->name) == 0);//如果drv的id_table不存在,則比較name是否相等

33 }


4.3 platform_match_id


 1 static const struct platform_device_id *platform_match_id(

 2             const struct platform_device_id *id,

 3             struct platform_device *pdev)

 4 {/*其實id也是匹配name,只不過可能driver要支持多個device,所以有多個名字,就做成一個id_table比較*/

 5     while (id->name[0]) {

 6         if (strcmp(pdev->name, id->name) == 0) {

 7             pdev->id_entry = id;

 8             return id;

 9         }

10         id++;

11     }

12     return NULL;

13 }


5 platform_device


5.1 platform_device結構體


1 struct platform_device {

 2     const char    *name;

 3     int        id;/*區分使用相同driver的同種設備,從0開始,-1為自動分配*/

 4     bool        id_auto;

 5     struct device    dev;/*具體的設備,無論是何種總線里的設備,都是對dev再次增加信息封裝*/

 6     u32        num_resources;/*多少個資源,為下面準備的*/

 7     struct resource    *resource;/*存放資源的地址*/

 8 

 9     const struct platform_device_id    *id_entry;/*區分統一廠家的不同版本設備*/

10 

11     /* MFD cell pointer */

12     struct mfd_cell *mfd_cell;

13 

14     /* arch specific additions */

15     struct pdev_archdata    archdata;/*特殊架構準備,基本不用*/

16 }


5.2 platform_device_alloc


通常我們自定義一個靜態的platform_device并填充。


當然內核為了絕對的可裁剪性,也提供了通過動態分配的方法。


 1 /**

 2  * platform_device_alloc - create a platform device

 3  * @name: base name of the device we're adding

 4  * @id: instance id

 5  *

 6  * Create a platform device object which can have other objects attached

 7  * to it, and which will have attached objects freed when it is released.

 8  */

 9 struct platform_device *platform_device_alloc(const char *name, int id)

10 {

11     struct platform_object *pa;

12 

13     pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);

14     if (pa) {

15         strcpy(pa->name, name);

16         pa->pdev.name = pa->name;

17         pa->pdev.id = id;

18         device_initialize(&pa->pdev.dev);

19         pa->pdev.dev.release = platform_device_release;/*release放在dev里面unregister的時候只要device_del(dev)就可以*/

20         arch_setup_pdev_archdata(&pa->pdev);

21     }

22 

23     return pa ? &pa->pdev : NULL;

24 }


struct platform_object {

    struct platform_device pdev;

    char name[1];

};


5.2.1 platform_device_release


 1 static void platform_device_release(struct device *dev)

 2 {

 3     struct platform_object *pa = container_of(dev, struct platform_object,

 4                           pdev.dev);

 5 

 6     of_device_node_put(&pa->pdev.dev);

 7     kfree(pa->pdev.dev.platform_data);//這部分由自己具體的設備實現具體的數據結構

 8     kfree(pa->pdev.mfd_cell);

 9     kfree(pa->pdev.resource);//釋放存放resource的內存

10     kfree(pa);//釋放platform_device_alloc中申請的obj

11 }


5.2.2 platform_device_register


無論是靜態還是2.2中的動態定義的platform_device,都需要platform_device添加進platform_bus。


即使用下面platform_device_register函數就可以了。


 1 /**

 2  * platform_device_register - add a platform-level device

 3  * @pdev: platform device we're adding

 4  */

 5 int platform_device_register(struct platform_device *pdev)

 6 {

 7     device_initialize(&pdev->dev);

 8     arch_setup_pdev_archdata(pdev);

 9     return platform_device_add(pdev);

10 }


5.2.3 platform_add_devices


系統也提供了可以同時注冊多個device的API,起始就是多次調用上面的。


 1 /**

 2  * platform_add_devices - add a numbers of platform devices

 3  * @devs: array of platform devices to add

 4  * @num: number of platform devices in array

 5  */

 6 int platform_add_devices(struct platform_device **devs, int num)

 7 {

 8     int i, ret = 0;

 9 

10     for (i = 0; i < num; i++) {

11         ret = platform_device_register(devs[i]);

12         if (ret) {

13             while (--i >= 0)

14                 platform_device_unregister(devs[i]);

15             break;

16         }

17     }

18 

19     return ret;

20 }


5.2.4 platform_device_add


 1 /**

 2  * platform_device_add - add a platform device to device hierarchy

 3  * @pdev: platform device we're adding

 4  *

 5  * This is part 2 of platform_device_register(), though may be called

 6  * separately _iff_ pdev was allocated by platform_device_alloc().

 7  */

 8 int platform_device_add(struct platform_device *pdev)

 9 {

10     int i, ret;

11 

12     if (!pdev)

13         return -EINVAL;

14 

15     if (!pdev->dev.parent)//如果設備沒指定parent的話,默認就是platform(通常都是)

16         pdev->dev.parent = &platform_bus;

17 

18     pdev->dev.bus = &platform_bus_type;//綁定總線類型,sysfs體現

[1] [2] [3] [4]
關鍵字:linux  設備驅動 引用地址:linux設備驅動(16)platfrom詳解

上一篇:Android驅動開發5-8章讀書筆記
下一篇:tiny210移植linux內核(3.0.8)雜項

推薦閱讀最新更新時間:2025-04-15 18:06

CAN能信卡的Linux設備驅動程序設計實現
??? 摘要: 介紹了Linux下設備驅動程序的結構,描述了CAN通信卡設備驅動程序的軟件框架以及如何將CAN設備驅動程序加入到Linux系統內核中。討論了具體實現中為了提高通信效率和通信能力,改進設備驅動程序的緩沖區管理以及利用Linux的特點合理設計中斷處理程序。 ??? 關鍵詞: Linux操作系統 設備驅動程序 CAN通信卡 中斷處理程序 目前,許多工業現場如電力系統、化工系統等大量使用控制器局部網(CAN-Controller Area Network)現場總線網絡,CAN通信卡作為計算機的外設將計算機接入CAN網絡。市場上有不少CAN通信卡,但基本上都不帶Linux驅動程序,當需要在Linu
[應用]
USB設備驅動開發-USB協議相關(3)
? 一、USB設備標準請求 USB設備標準請求是為所有USB設備定義的操作,即使設備還沒有被分配地址或還沒有被配置都必須相應設備標準請求。 標準特性選擇子 特性選擇子用于對特性使能或設置特性,若一個不支持或非法的請求發送給USB設備,設備將在數據或狀態傳輸階段返回STALL作為響應。若設備的默認控制通道由于錯誤不能通信,則設備將被reset來清除錯誤狀態并重啟默認控制通道。 1. Clear Feature wValue中的特性選擇子必須和操作對象匹配,即設備特性對應設備,接口特性對應接口,端點特性對應端點。 若對應的特性不存在或不能被清除,或者操作的接口或端點不存在
[嵌入式]
QNX操作系統及網絡設備驅動模塊
摘要:介紹嵌入式操作系統QNX的微內核結構、基于io-net的網絡子系統、網絡設備驅動程序的組成;給出以以太網網設備驅動程序為例的詳細說明,包括初始化、從網絡設備接收數據,向網絡設備發送數據和網絡設備信息的統計。 關鍵詞:QNX 網絡 驅動程序 QNX是業界公認的X86平臺上最好的嵌入式實時操作系統之一。它具有獨一無二的微內核實時平臺,建立在微內核和完全地址空間保護基礎之上,實時、穩定、可靠,已經完成到PowerPC、MIPS、ARM等內核的移植,成為在國內廣泛應用的嵌入式實時操作系統。本文簡單介紹QNX內核和網絡結構的特點,針對目前熱門的網絡應用環境,討論QNX網絡設備驅動程序的結構和編寫。 1 QNX內核簡介 QNX的
[應用]
Linux移植之auto.conf、autoconf.h、Mach-types.h的生成過程簡析
在Linux移植之make uImage編譯過程分析中分析了uImage文件產生的過程,在uImage產生的過程中,順帶還產生了其它的一些中間文件。這里主要介紹幾個比較關鍵的文件 1、linux-2.6.22.6includeconfigauto.conf、inux-2.6.22.6includelinuxautoconf.h文件的生成過程 2、includeasm-armMach-types.h文件的生成過程 1、inux-2.6.22.6includeconfigauto.conf、inux-2.6.22.6includelinuxautoconf.h文件的生成過程 在頂層Makefile中嘗試尋找auto.c
[單片機]
arm-linux-gcc .s 和 .S 的區別 !
unix/linux 對 大小寫敏感: .s 操作 :匯編 .S 操作 : cpp + 匯編 eg: /* start.s */ #define rTEXT 0x12345678 LDR R0,=rTEXT .... # arm-linux-gcc -g -c -nostdlib start.s -o start.o # nm -u start.o rTEXT # arm-linux-objdump -S -t start.o start.l # cat start.i | grep ''R0 LDR R0,【PC,#0】 經典錯誤: arm-linux-gcc 將.s 文件誤認為cpp處理后
[單片機]
linux 2.6.32 在arm9(s3c2440)平臺的移植 - 標題要長(2)
(1) s3c2440平臺關于nand flash部分的代碼, 在你弄清楚移植代碼的每一個步驟是為什么之前,不要去做所謂的移植,那是毫無意義的 *****/arch/arm/plat-s3c24xx/common-smdk.c***** static struct mtd_partition smdk_default_nand_part = { = { .name = supervivi , .size = 0x00040000, .offset = 0, }, = { .name =
[單片機]
stm32能跑linux
  Linux是一套免費使用和自由傳播的類Unix操作系統,是一個基于POSIX和UNIX的多用戶、多任務、支持多線程和多CPU的操作系統。它能運行主要的UNIX工具軟件、應用程序和網絡協議。它支持32位和64位硬件。Linux繼承了Unix以網絡為核心的設計思想,是一個性能穩定的多用戶網絡操作系統。Linux操作系統誕生于1991 年10 月5 日(這是第一次正式向外公布時間)。Linux存在著許多不同的Linux版本,但它們都使用了Linux內核。Linux可安裝在各種計算機硬件設備中,比如手機、平板電腦、路由器、視頻游戲控制臺、臺式計算機、大型機和超級計算機。嚴格來講,Linux這個詞本身只表示Linux內核,但實際上人們已
[單片機]
OK6410A 開發板 (八) 26 linux-5.11 OK6410A 進程角度 idle進程的建立過程
idle 進程的建立的 過程 idle 進程的建立的 過程 // 其實就是 init_task 結構體初始化的過程 1.sp 的初始化 // __mmap_switched - ARM( ldmia r4!, {r0, r1, sp} ) // __mmap_switched_data: // .long init_thread_union + THREAD_START_SP @ sp // 在鏈接過程中確定了 一個值 (該值與 init_thread_union 相關) // 將該值 寫入 sp 中 // start_kernel 在 sp 對應的棧 中運行 2.TCB(init_task&in
[單片機]
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 苍山县| 理塘县| 隆子县| 淳安县| 梁平县| 石嘴山市| 栖霞市| 铁岭县| 遂川县| 莒南县| 巴马| 白水县| 瑞金市| 秦皇岛市| 临武县| 黄浦区| 峨边| 云浮市| 山西省| 安福县| 高碑店市| 日照市| 宁强县| 横峰县| 沙坪坝区| 邛崃市| 临夏市| 上饶县| 广州市| 杂多县| 东方市| 岫岩| 衡阳市| 马龙县| 晋州市| 安吉县| 蓬安县| 五家渠市| 和田县| 甘德县| 东兴市|