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

【IMX6ULL學習筆記】十七、總線驅動框架-Platform、IIC、SPI等

發布者:Xingfu6666最新更新時間:2025-02-28 來源: cnblogs關鍵字:IIC  SPI 手機看文章 掃描二維碼
隨時隨地手機看文章

一、總線

Linux 總線驅動模型主要可以分為三個部分:總線、設備、驅動。Linux 中的總線(bus)、驅動(driver)和設備(device)模型,也就是常說的驅動分離。Linux內核在啟動時會向系統注冊總線,比如 IIC總線、SPI總線、SDIO總線、Platform總線等。總線是與硬件平臺無關的,由Linux系統提供并進行注冊,無需用戶關心。總線的職責就是將驅動與設備進行匹配,Linux系統內核使用 bus_type 結構體表示總線,此結構體定義在文件include/linux/device.h,bus_type 結構體內容如下:


struct bus_type {

    const char *name; /* 總線名字 */

    const char *dev_name;

    struct device *dev_root;

    struct device_attribute *dev_attrs;

    const struct attribute_group **bus_groups; /* 總線屬性 */

    const struct attribute_group **dev_groups; /* 設備屬性 */

    const struct attribute_group **drv_groups; /* 驅動屬性 */

    int (*match)(struct device *dev, struct device_driver *drv);

    int (*uevent)(struct device *dev, struct kobj_uevent_env *env);

    int (*probe)(struct device *dev);

    int (*remove)(struct device *dev);

    void (*shutdown)(struct device *dev);

    int (*online)(struct device *dev);

    int (*offline)(struct device *dev);

    int (*suspend)(struct device *dev, pm_message_t state);

    int (*resume)(struct device *dev);

    const struct dev_pm_ops *pm;

    const struct iommu_ops *iommu_ops;

    struct subsys_private *p;

    struct lock_class_key lock_key;

};

第 10 行:match 函數,此函數很重要,此函數就是完成設備和驅動之間匹配的,總線就是使用 match 函數來根據注冊的設備來查找對應的驅動,或者根據注冊的驅動來查找相應的設備,因此每一條總線都必須實現此函數。match 函數有兩個參數:dev 和 drv,這兩個參數分別為 device 和 device_driver 類型,也就是設備和驅動。

Linux 還提供了兩個 API 用于總線的注冊與注銷(由Linux完成,用戶無需關心),定義在 Drive/base/bus.c中,如下:


bus_register(struct bus_type *bus);

bus_unregister(struct bus_type *bus);

參數:對應總線結構體變量


各種總線如IIC、SPI、SDIO總線等都是 bus_type 的一個實例。


內核初始化會先調用 platform_bus_init() 初始化 platform_bus 總線,之后由 _initcall 的優先級順序可知先初始化各種實際總線例如 spi、i2c。之后注冊 platform_device 到 platform_bus 上,然后注冊 platform_driver 到platform_bus。


在 linux 引進設備樹之前設備信息都存放在內核 arch 目錄下,引進設備樹以后設備信息由設備樹描述(此舉為了刪除linux內核大量和平臺設備相關的代碼)內核初始化會掃描設備樹文件將設備信息保存到設備鏈表,提供鏈表的頭指針,在注冊設備時調用of_xxx(操作設備樹鏈表的api)來獲得設備信息。


注冊 platform_device 會將設備綁定到 platform_bus,之后會遍歷 platform_bus 上是否有與之匹配的驅動程序(調用 platform_bus_type 的 match 函數進行匹配),如果存在,匹配成功調用驅動的probe對設備進行初始化的配置。

注冊 platform_driver 到 platform_bus 會遍歷 platform_bus 上是否有與之匹配的設備(調用 platform_bus_type 的 match 函數進行匹配),如果存在,匹配成功調用驅動的 probe 對設備進行初始化的配置。如果平臺設備本身是實際的總線例如spi、i2c等,此時在驅動程序中會注冊總線設備到到相應的總線上,之后會遍歷xxx_bus上是否與之匹配的驅動程序,如果有會執行驅動的 probe 進行初始化相關配置。


下面以 SPI 總線驅動為例子做一個詳細講解:

①、SPI 驅動分為 SPI 控制器驅動、SPI 設備驅動。SPI 控制器掛在 Linux 的虛擬總線 Platform Bus 上,包括 SPI 控制器設備和 SPI 控制器設備的驅動,在內核代碼里分別由結構體 platform_device 和 platform_driver 表示,內核初始化時先注冊 platform_device(SPI 控制器設備,定義在設備樹 DTS 中的 SPI 控制器設備節點)到 platform bus,此時會遍歷總線上是否存在匹配的 SPI 控制器驅動程序(根據兼容性、設備id、設備名),匹配成功會調用控制器驅動的 probe 對控制器進行相關的配置。


②、之后會注冊 SPI 控制器的驅動程序(定義在內核源碼中,由 SOC 產商編寫)到 platform bus 上,此時會遍歷總線上是否存在匹配的 SPI 控制器設備(根據兼容性、設備id、設備名),匹配成功會調用控制器驅動的 probe 對控制器進行相關的配置。在 SPI 控制器驅動的 probe 函數中會注冊 spi device(設備樹 DTS 中定義在 SPI 控制器設備節點下的 SPI 設備)到 spi bus(spi bus此時已經初始化),此時會遍歷 spi 總線上是否有與之匹配的設備驅動程序,如果有,調用 spi 設備驅動的 probe 函數對 spi device 進行配置。spi 設備驅動(由用戶編寫,如IIC OLED、Sensor IIC等驅動)注冊到 spi bus 時也會同樣去匹配是否有匹配的設備。


擴展:

Linux 內核的 sysfs 子系統用來管理 Linux 設備驅動模型,參考下圖:

image

1、I2C 總線

I2C 總線結構體變量為 i2c_bus_type,該結構體變量是 bus_type 結構體的一個實例,IIC 設備和驅動的匹配以及注冊都是由 I2C 總線完成的,IIC總線結構體和IIC驅動設備注冊 API 都定義在 drivers/i2c/i2c-core.c 文件中,i2c_bus_type 內容如下:


struct bus_type i2c_bus_type = {

    .name = 'i2c',

    .match = i2c_device_match,

    .probe = i2c_device_probe,

    .remove = i2c_device_remove,

    .shutdown = i2c_device_shutdown,

};

.match 就是 I2C 總線的設備和驅動匹配函數,也就是 i2c_device_match 這個函數,此函數內容如下:


static int i2c_device_match(struct device *dev, struct device_driver *drv)

{

    struct i2c_client *client = i2c_verify_client(dev);

    struct i2c_driver *driver;


    if (!client)

        return 0;


    /* Attempt an OF style match */

    if (of_driver_match_device(dev, drv))

        return 1;


    /* Then ACPI style match */

    if (acpi_driver_match_device(dev, drv))

        return 1;


    driver = to_i2c_driver(drv);

    /* match on an id table if there is one */

    if (driver->id_table)

        return i2c_match_id(driver->id_table, client) != NULL;


    return 0;

}

第 11 行:of_driver_match_device 函數用于完成設備樹設備和驅動匹配。比較 I2C 設備節點的 compatible 屬性和 of_device_id 中的 compatible 屬性是否相等,如果相當的話就表示 I2C 設備和驅動匹配。

第 15 行:acpi_driver_match_device 函數用于 ACPI 形式的匹配。

第 21 行:i2c_match_id 函數用于傳統的、無設備樹的 I2C 設備和驅動匹配過程。比較 I2C 設備名字和 i2c_device_id 的 name 字段是否相等,相等的話就說明 I2C 設備和驅動匹配。

IIC設備驅動的注冊與注銷 API 也定義在 drivers/i2c/i2c-core.c 文件中,API 函數如下:

1、i2c_adapter 注冊/注銷函數(主機驅動API)


int i2c_add_adapter(struct i2c_adapter *adapter)

int i2c_add_numbered_adapter(struct i2c_adapter *adap)

void i2c_del_adapter(struct i2c_adapter * adap)

2、i2c_driver 注冊/注銷函數(設備驅動API)


int i2c_register_driver(struct module *owner, struct i2c_driver *driver)

int i2c_add_driver (struct i2c_driver *driver)

void i2c_del_driver(struct i2c_driver *driver)

結論:

i2c-core.c 定義了 IIC 總線結構體變量,并調用 bus.c 提供的總線注冊與注銷API,將 IIC 總線注冊到系統中。同時,向下提供了 IIC 主機驅動和設備驅動的注冊、注銷相關 API。


2、SPI 總線

再如 SPI 設備和驅動的匹配過程是由 SPI 總線來完成的,這點和 I2C 等驅動一樣,SPI 總線為 spi_bus_type,定義在 drivers/spi/spi.c 中,內容如下:


struct bus_type spi_bus_type = {

    .name = 'spi',

    .dev_groups = spi_dev_groups,

    .match = spi_match_device,

    .uevent = spi_uevent,

};

可以看出,SPI 設備和驅動的匹配函數為 spi_match_device,函數內容如下:


static int spi_match_device(struct device *dev, struct device_driver *drv)

{

    const struct spi_device *spi = to_spi_device(dev);

    const struct spi_driver *sdrv = to_spi_driver(drv);


    /* Attempt an OF style match */

    if (of_driver_match_device(dev, drv))

        return 1;


    /* Then try ACPI */

    if (acpi_driver_match_device(dev, drv))

        return 1;


    if (sdrv->id_table)

        return !!spi_match_id(sdrv->id_table, spi);


    return strcmp(spi->modalias, drv->name) == 0;

}

spi_match_device 函數和 i2c_match_device 函數的對于設備和驅動的匹配過程基本一樣。

第 7 行:of_driver_match_device 函數用于完成設備樹設備和驅動匹配。比較 SPI 設備節點的 compatible 屬性和 of_device_id 中的 compatible 屬性是否相等,如果相當的話就表示 SPI 設備和驅動匹配。

第 11 行:acpi_driver_match_device 函數用于 ACPI 形式的匹配。

第 15 行:spi_match_id 函數用于傳統的、無設備樹的 SPI 設備和驅動匹配過程。比較 SPI 設備名字和 spi_device_id 的 name 字段是否相等,相等的話就說明 SPI 設備和驅動匹配。

第 17 行:比較 spi_device 中 modalias 成員變量和 device_driver 中的 name 成員變量是否相等。


SPI總線提供SPI驅動的注冊與注銷相關API,也定義在 drivers/spi/spi.c 中。


1、主機驅動API

SPI 主機驅動的核心是申請 spi_master,然后初始化 spi_master,最后向 Linux 內核注冊 spi_master,主機驅動注冊與注銷相關 API 如下:

①、spi_master 申請與釋放

spi_alloc_master 函數用于申請 spi_master,函數原型如下:


struct spi_master *spi_alloc_master(struct device *dev, unsigned size)

函數參數和返回值含義如下:


dev:設備,一般是 platform_device 中的 dev 成員變量。

size:私有數據大小,可通過 spi_master_get_devdata 函數獲取這些私有數據。

返回值:申請到的 spi_master。

spi_master 的釋放通過 spi_master_put 函數來完成,當刪除一個 SPI 主機驅動的時候就需要釋放掉前面申請的 spi_master,spi_master_put 函數如下:


void spi_master_put(struct spi_master *master)

函數參數和返回值含義如下:


master:要釋放的 spi_master。

返回值:無。

②、spi_master 的注冊與注銷

當 spi_master 初始化完成以后就需要將其注冊到 Linux 內核,spi_master 注冊函數為 spi_register_master,函數原型如下:


int spi_register_master(struct spi_master *master)

函數參數和返回值含義如下:


master:要注冊的 spi_master。

返回值:0,成功;負值,失敗。

I.MX6U 的 SPI 主機驅動會采用 spi_bitbang_start 這個 API 函數來完成 spi_master 的注冊,spi_bitbang_start 函數內部其實也是通過調用 spi_register_master 函數來完成 spi_master 的注冊。


如果要注銷 spi_master 的話可以使用 spi_unregister_master 函數,此函數原型為:


void spi_unregister_master(struct spi_master *master)

函數參數和返回值含義如下:


master:要注銷的 spi_master。

返回值:無。

如果使用 spi_bitbang_start 注冊 spi_master 的話就要使用 spi_bitbang_stop 來注銷掉 spi_master。


2、設備驅動API

spi_driver 初始化完成以后需要向 Linux 內核注冊,spi_driver 注冊函數為 spi_register_driver,函數原型如下:


int spi_register_driver(struct spi_driver *sdrv)

函數參數和返回值含義如下:


sdrv:要注冊的 spi_driver。

返回值:0,注冊成功;賦值,注冊失敗。

注銷掉前面注冊的 spi_driver,使用 spi_unregister_driver 函

數完成 spi_driver 的注銷,函數原型如下:


void spi_unregister_driver(struct spi_driver *sdrv)

函數參數和返回值含義如下:


sdrv:要注銷的 spi_driver。

返回值:無。

結論:

spi.c 定義了 spi 總線結構體變量,并調用 bus.c 提供的總線注冊與注銷API,將 spi 總線注冊到系統中。同時,向下提供了 spi 主機驅動和設備驅動的注冊、注銷相關 API。


3、platform 總線

在 SOC 中有些外設是沒有總線這個概念的,但是又要使用總線、驅動和設備模型,因此 Linux 提出了 platform 這個虛擬總線。platform 總線也是 bus_type 的一個具體實例,定義在文件 drivers/base/platform.c 文件中,如下:


struct bus_type platform_bus_type = {

    .name = 'platform',

    .dev_groups = platform_dev_groups,

    .match = platform_match,

    .uevent = platform_uevent,

    .pm = &platform_dev_pm_ops,

};

platform_bus_type 就是 platform 平臺總線,其中 platform_match 就是匹配函數。=platform_match 函數定義在文件 drivers/base/platform.c 中,函

數內容如下所示:


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

{

    struct platform_device *pdev = to_platform_device(dev);

    struct platform_driver *pdrv = to_platform_driver(drv);


    /*When driver_override is set,only bind to the matching driver*/

    if (pdev->driver_override)

        return !strcmp(pdev->driver_override, drv->name);


    /* Attempt an OF style match first */

    if (of_driver_match_device(dev, drv))

        return 1;


    /* Then try ACPI style match */

    if (acpi_driver_match_device(dev, drv))

        return 1;


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

    if (pdrv->id_table)

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


    /* fall-back to driver name match */

    return (strcmp(pdev->name, drv->name) == 0);

}

驅動和設備的匹配有四種方法,我們依次來看一下:

第 11~12 行:第一種匹配方式,OF 類型的匹配,也就是設備樹采用的匹配方式,

of_driver_match_device 函數定義在文件 include/linux/of_device.h 中。device_driver 結構體(表示設備驅動)中有個名為of_match_table的成員變量,此成員變量保存著驅動的compatible匹配表,設備樹中的每個設備節點的 compatible 屬性會和 of_match_table 表中的所有成員比較,查看是否有相同的條目,如果有的話就表示設備和此驅動匹配,設備和驅動匹配成功以后 probe 函數

就會執行。

第 15~16 行:第二種匹配方式,ACPI 匹配方式。

第 19~20 行:第三種匹配方式,id_table 匹配,每個 platform_driver 結構體有一個 id_table 成員變量,顧名思義,保存了很多 id 信息。這些 id 信息存放著這個 platformd 驅動所支持的驅動類型。

[1] [2]
關鍵字:IIC  SPI 引用地址:【IMX6ULL學習筆記】十七、總線驅動框架-Platform、IIC、SPI等

上一篇:【IMX6ULL學習筆記】十八、Platform 驅動框架
下一篇:【IMX6ULL學習筆記】十六、設備樹下LED驅動

推薦閱讀最新更新時間:2025-06-10 17:54

STM32——簡述USART與SPIIIC之間的區別與聯系
簡述USART與SPI、IIC之間的區別與聯系 第一個區別當然是名字: SPI(Serial Peripheral Interface) 串行外設接口 I2C(INTER IC BUS) 集成電路總線 USART(Universal Asynchronous Receiver Transmitter) 通用異步收發器 第二個區別在電氣信號線上: SPI總線由三條信號線組成:串行時鐘(SCLK)、串行數據輸出(SDO)、串行數據輸入(SDI)。 SPI總線可以實現多個SPI設備互相連接。提供SPI串行時鐘的SPI設備為SPI主機或主設備(Master),其他設備為SPI從機或從設備(Slave)。主從設備間可以實現全雙工通信
[單片機]
STM8硬件IIC從機
一.平臺 芯片:STM8S103F3P6 環境:IAR + STVP 系統:WIN7 二. 目的 STM8S103F3P6:使用STM8標準庫開發 角色------從機 方式----------硬件IIC STM32H7: 角色------主機 方式----------IO口模擬IIC主機 主機發送命令包,從機接收后進行判斷 主機發送讀取命令,從機返回上次命令包判斷后要返回的數據包 三.STM8硬件IIC STM8S103時鐘 由于該芯片實際應用是放到控制板作為一個附屬芯片,不考慮功耗、盡可能采用高的頻率,且需要滿足硬件I2C對時鐘的需求(后續講到),由STM8S103參考手冊時鐘章節可看出,接外
[單片機]
STM8硬件<font color='red'>IIC</font>從機
處理器IP供應商特色方案亮相IIC-China
HDTV、IPTV、802.11n等新興應用市場的出現以及多功能融合產品對處理器性能提出更高要求。目前中國市場上活躍著多家處理器IP供應商,其產品策略各異。作為標準處理器市場上最具代表性的廠商,ARM處理器IP應用于眾多手機或其它便攜式產品中。而MIPS科技的處理器IP起初被廣泛用于路由器等領域,近年來,該公司又拓展了嵌入式及便攜式應用。Tensilica公司以可配置處理器IP起家,其后續開發的Diamond系列標準處理器與原有的Xtensa產品線形成互補,加速實現差異化 SoC 設計。在IIC- China 2008展會上這幾家主流IP供應商帶來各類特色方案,為高性能、低功耗應用設計提供多種選擇。 MIPS:高性能處理
[焦點新聞]
Tensilica攜手新岸線參展IIC-China
  Tensilica和手機電視系統及芯片供應商北京新岸線(Nufront)日前聯合宣布,將共同參展2008年3月3-4日深圳(展位號:2K41)、3月10-11日上海(展位號:4S41)的IIC-China 2008展會。   Tensilica幫助國內客戶通過創新性的Xtensa可配置處理器及Diamond標準處理器產品快速開發并差異化其SOC設計。在本屆IIC-China展會,Tensilica公司將展出多款RISC CPU,音頻DSP,視頻DSP等IP產品。   新岸線(Nufront)是Tensilica國內首家Xtensa可配置處理器客戶。基于可配置技術,新岸線公司成功實現了高性能和超低功耗(第三方手機電視國標功耗測試結
[焦點新聞]
s3c2440裸機-spi編程-2-OLED顯示面板
1.OLED顯示面板介紹 以QG-2864TMBEG01這款OLED為例,可見它支持Parallel/i2c/SPI這3種方式對它進行控制,這里僅對它進行SPI控制。它的product Specification見附件。 并行接口時序: SPI串行接口時序 Tr/Tf: 表示spi clk上升/下降延不能超過40ns Tclkl/Tclkh: 表示spi clk低/高電平持續至少20ns Tcycle: 表示spi clk一個時鐘周期至少100ns Tdsw/Tdhw: 表示spi data的建立/持續時間至少15ms Tcss:片選建立時間至少20ns Tcsh:片選持續時間至少10ns Tas/Tah:
[單片機]
更小、更薄、更輕!兆易創新業界超小尺寸FO-USON8封裝128Mb SPI NOR Flash面世!
更小、更薄、更輕!兆易創新業界超小尺寸3mm×3mm×0.4mm FO-USON8封裝128Mb SPI NOR Flash面世! 中國北京(2023年5月16日) —— 業界領先的半導體器件供應商兆易創新GigaDevice(股票代碼 603986)今日宣布,率先推出采用3mm×3mm×0.4mm FO-USON8封裝的SPI NOR Flash——GD25LE128EXH ,其最大厚度僅為0.4mm,容量高達128Mb,是目前業界在此容量上能實現的最小塑封封裝產品,可在應對大容量代碼存儲需求的同時,提供極大限度的緊湊型設計自由。 近年來,隨著物聯網、可穿戴、健康監護、網通等應用的快速發展,市場需求變化多樣,不僅要
[嵌入式]
更小、更薄、更輕!兆易創新業界超小尺寸FO-USON8封裝128Mb <font color='red'>SPI</font> NOR Flash面世!
玩轉STM32CubeMX | SPI總線
1.SPI總線及W25QXX芯片 1.1 SPI總線簡介 SPI全稱Serial Peripheral Interface,即串行外圍設備接口。是Motorola首先在其MC68HCXX系列處理器上定義的。SPI接口主要應用在EEPROM、FLASH、實時時鐘、AD轉換器,還有數字信號處理器和數字信號解碼器之間。SPI是一種高速的、全雙工、同步通訊總線,在芯片的管腳上只占用四根線,節約了芯片的管腳,同時為PCB的布局節省空間提供了方便,正是這種簡單易用的特性,如今越來越多的芯片集成了這種通訊協議。下圖是SPI內部結構簡易圖 從上圖可以看出,主設備和從設備都有一個串行移位寄存器,主設備通過向它的SPI串行寄存器寫入一個字節來發起
[單片機]
玩轉STM32CubeMX | <font color='red'>SPI</font><font color='red'>總線</font>
小廣播
設計資源 培訓 開發板 精華推薦

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

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

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 丰都县| 化德县| 桂东县| 壤塘县| 察隅县| 孟州市| 资源县| 英德市| 徐闻县| 吉水县| 鄂托克旗| 论坛| 土默特右旗| 香河县| 寻乌县| 兴安盟| 柳州市| 交口县| 永福县| 卓尼县| 苗栗市| 万载县| 揭东县| 井研县| 峨边| 越西县| 武宁县| 西乡县| 富阳市| 吴川市| 海口市| 赤壁市| 武功县| 青冈县| 北安市| 临漳县| 辽源市| 大田县| 九龙坡区| 澎湖县| 卓尼县|