Linux设备驱动-platform虚拟总线dya01
參考連接:https://www.cnblogs.com/deng-tao/p/6026373.html
參考書:<Linux設備驅動開發詳解>宋寶華
根據參考資料和同事討論總結.
摘要: platform的原理及相關結構體
1、什么是platform(平臺)總線?
相對于USB、PCI、I2C、SPI等物理總線來說,platform總線是一種虛擬、抽象出來的總線,實際中并不存在這樣的總線。
那為什么需要platform總線呢?
其實是Linux設備驅動模型為了保持設備驅動的統一性而虛擬出來的總線。因為對于usb設備、i2c設備、pci設備、spi設備等等,他們與cpu的通信都是直接掛在相應的總線下面與我們的cpu進行數據交互的,但是在我們的嵌入式系統當中,并不是所有的設備都能夠歸屬于這些常見的總線,在嵌入式系統里面,SoC系統中集成的獨立的外設控制器、掛接在SoC內存空間的外設卻不依附與此類總線。所以Linux驅動模型為了保持完整性,將這些設備掛在一條虛擬的總線上(platform總線),而不至于使得有些設備掛在總線上,另一些設備沒有掛在總線上。
platform總線相關代碼:driver\base\platform.c 文件
相關結構體定義:include\linux\platform_device.h 文件中
2.通俗理解
Platform虛擬總線
總線兩邊分別掛接設備和驅動,設備和驅動互相探測,一旦探測成功(基于設備樹風格的匹配,基于ID表,基于設備名和驅動名)就可以對設備進行操作了.
設備驅動的開發,我們可以總結為以下順序:
定義platform_device
注冊platform_device
定義platform_driver
注冊platform_driver
單片機是直接拿寄存器控制硬件.
而嵌入式設備因為有操作系統,必須通過驅動來控制硬件設備.
3.platform平臺總線工作原理
平臺總線體系的工作流程
(1)第一步:系統啟動時在bus系統中注冊platform
(2)第二步:內核移植的人負責提供platform_device
(3)第三步:寫驅動的人負責提供platform_driver
(4)第四步:platform的match函數發現driver和device匹配后,調用driver的probe函數來完成驅動的初始化和安裝,然后設備就工作起來了
4.platform總線管理下的2員大將
兩個結構體platform_device和platform_driver
對于任何一種Linux設備驅動模型下的總線都由兩個部分組成:
描述設備相關的結構體和描述驅動相關的結構體
在platform總線下就是platform_device和platform_driver
(1)platform_device結構體:(include\linux\platform_device.h)
struct platform_device { // platform總線設備const char * name; // 平臺設備的名字int id; // ID 是用來區分如果設備名字相同的時候(通過在后面添加一個數字來代表不同的設備,因為有時候有這種需求)struct device dev; // 內置的device結構體u32 num_resources; // 資源結構體數量struct resource * resource; // 指向一個資源結構體數組const struct platform_device_id *id_entry; // 用來進行與設備驅動匹配用的id_table表/* arch specific additions */struct pdev_archdata archdata; // 自留地 添加自己的東西};platform_device結構體中的struct resource結構體分析:
struct resource { // 資源結構體resource_size_t start; // 資源的起始值,如果是地址,那么是物理地址,不是虛擬地址resource_size_t end; // 資源的結束值,如果是地址,那么是物理地址,不是虛擬地址const char *name; // 資源名unsigned long flags; // 資源的標示,用來識別不同的資源struct resource *parent, *sibling, *child; // 資源指針,可以構成鏈表};(2)platform_driver結構體
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 (*resume) (struct platform_device *); struct device_driver driver; const struct platform_device_id *id_table; bool prevent_deferred_probe; };其中,device_driver結構體定義如下:
struct device_driver {const char *name;struct bus_type *bus;struct module *owner;const char *mod_name; /*used for built-in modules*/bool suppress_bind_attrs; /*disables bind/unbind via sysfs*/const struct of_device_id *of_match_table;const struct acpi_device_id *acpi_match_table;int (*probe) (struct device *dev);int (*remove) (struct device *dev);void (*shutdown) (struct device *dev);int (*suspend) (struct device *dev,pm_message_t state);int (*resume) (struct device *dev);const struct attribute_group **groups;const struct dev_pm_ops *pm;struct driver_private *p; };與platform_driver地位對等的i2c_driver,spi_driver,usb_driver等都包含device_driver結構體實例成員,他其實描述了xxx_driver(xxx是總線名)在驅動意義上的一些共性.
在Linux4.0以后,內核直接使用設備樹來管理設備信息.設備樹中包含寄存器地址,中斷號等信息,直接寫成一個文本文檔,bootloader會將"這棵樹"傳給內核,內核解析其中的內容,進而展開內核中的platform_device,i2c_client,spi_device等設備. 驅動程序直接從設備樹的name進行匹配, 匹配到就可以通過platform_get_resource函數得到設備信息和寄存器信息等,進而控制硬件設備.
總結
以上是生活随笔為你收集整理的Linux设备驱动-platform虚拟总线dya01的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 完美解决EclipseTab占位符问题
- 下一篇: 《人世间》影评