日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux驱动程序的数据封装

發(fā)布時間:2023/12/20 linux 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux驱动程序的数据封装 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

引言

0

基于ARM內(nèi)核的SoC在引入設(shè)備樹技術(shù)之后,通過設(shè)備樹文件來描述不同的設(shè)備并匹配不同的驅(qū)動代碼,使得一個kernel鏡像文件可以支持多種設(shè)備。這種代碼可重用的思想不僅體現(xiàn)在設(shè)備樹文件中,在驅(qū)動代碼中同樣也有所體現(xiàn)。其中之一就是驅(qū)動代碼中設(shè)備描述表-of_device_id。同一個IP集成到不同SoC或者根據(jù)應(yīng)用場景激活不同功能,可以通過of_device_id這個數(shù)據(jù)結(jié)構(gòu)來實現(xiàn)。

對于同一個IP集成到不同SoC的應(yīng)用場景而言,其寄存器基地址以及時鐘等參數(shù)可能不同,但是IP功能基本一樣。那么可以通過of_device_id里的不同data條目獲取對應(yīng)的參數(shù)信息。例如exynos的dsi IP,在不同版本的SoC中基地址不同,定義了5種SoC類型。在dsi probe時獲取其在SoC中的基地址。


下面驅(qū)動代碼表示該模塊需要支持多種不同時鐘頻率的初始化,可以定義一個of_device_id表,根據(jù)匹配到的設(shè)備信息為每一種時鐘提供獨立的初始化函數(shù)。由of_device_id_match_data獲取到不同的init_fn,按照不同的dev.of_node,執(zhí)行return init_fn(np);

以上應(yīng)用場景核心的數(shù)據(jù)結(jié)構(gòu)是of_device_id,關(guān)鍵的處理函數(shù)是of_device_get_match_data(),當(dāng)然,關(guān)于of_device_id的應(yīng)用場景不僅僅限于上面說的這兩種。

數(shù)據(jù)結(jié)構(gòu)of_device_id

1

of_device_id數(shù)據(jù)結(jié)構(gòu)如下,定義在mod_devicetable.h中,組成也并不復(fù)雜。

1struct?of_device_id?{ 2????char????name[32]; 3????char????type[32]; 4????char????compatible[128]; 5????const?void?*data; 6};

mod_devicetable.h這個文件最初并沒有of_device_id這個數(shù)據(jù)結(jié)構(gòu),該文件的歷史暫時也只能查到2005年的Linux-2.6.12-rc2

它的功能從最初的文件中也可以看到,主要是為PCI以及USB設(shè)備使用的,將設(shè)備的vendor ID、subsystem ID、class等信息提供給scripts/table2alias.c,當(dāng)系統(tǒng)新插入一個PCI或USB設(shè)備時,用戶空間程序根據(jù)對應(yīng)的vendor ID等信息來加載對應(yīng)的驅(qū)動程序。

2005年7月Linux-2.6.13-rc2中提交了of_match_id這個數(shù)據(jù)結(jié)構(gòu)的代碼。

???????? of_device_get_match_data()

2

函數(shù)原型位于drivers/of/device.c

1const?void?*of_device_get_match_data(2????const?struct?device?*dev)3{4????const?struct?of_device_id?*match;56????match?=?of_match_device(xxx);7????if?(!match)8????????return?NULL;9 10????return?match->data; 11} 12EXPORT_SYMBOL(of_device_get_match_data);

這個函數(shù)的返回值類型可強制轉(zhuǎn)換成任何類型,取決于驅(qū)動程序中例化數(shù)據(jù)結(jié)構(gòu)of_device_id data。當(dāng)然,由于of_device_get_match_data的函數(shù)返回值類型決定了不做強制類型轉(zhuǎn)換,也不會有問題。


代碼中增加下面的內(nèi)容,來追蹤of_device_get_match_data執(zhí)行流程。

#定義of_device_id并完成例化

#在probe函數(shù)中增加獲取數(shù)據(jù)的代碼

執(zhí)行結(jié)果顯示正確的獲取到了of_device_id各個成員例化的value值

#of_device_get_match_data()代碼流程

有幾種情況是無法獲取到數(shù)據(jù)的

##解析dtb之后未創(chuàng)建設(shè)備結(jié)點

##驅(qū)動代碼未實現(xiàn)of_device_id設(shè)備表

##of_device_id成員compatible、name、type的值和設(shè)備樹中定義的同

基于模塊加載的并且可以熱插拔的驅(qū)動程序,可以在系統(tǒng)啟動后查看設(shè)備表信息。以定位出未獲取到設(shè)備表信息的故障原因。

查看設(shè)備表信息

3

能夠查看到設(shè)備表信息的一個前置條件是在定義of_device_id的時候,要將該設(shè)備表通過MODULE_DEVICE_TABLE來進行聲明注冊,否則在用戶空間是看不到的。其定義在/include/linux/module.h中。type可以是of、usb、pci等,name為設(shè)備表的名字。

內(nèi)核中scripts/mod/file2alias.c,用于將設(shè)備表導(dǎo)出到用戶空間modules.alias中,所以可以直接查看modules.alias文件。


也可以通過modinfo來查看ko文件符號信息


設(shè)備表的定義如下,代碼定義了name、type,那么設(shè)備樹里同樣也要定義:

刪除MODULE_DEVICE_TABLE,modules.alias里是沒有設(shè)備表信息的。

對于of_device_id而言,name、type、compatible添加的方法:

#USB設(shè)備表

1struct?usb_device_id?{2????/*?which?fields?to?match?against??*/3????__u16???????match_flags;45????/*?Used?for?product?specific?matches;?range?is?inclusive?*/6????__u16???????idVendor;7????__u16???????idProduct;8????__u16???????bcdDevice_lo;9????__u16???????bcdDevice_hi; 10 11????/*?Used?for?device?class?matches?*/ 12????__u8????????bDeviceClass; 13????__u8????????bDeviceSubClass; 14????__u8????????bDeviceProtocol; 15 16????/*?Used?for?interface?class?matches?*/ 17????__u8????????bInterfaceClass; 18????__u8????????bInterfaceSubClass; 19????__u8????????bInterfaceProtocol; 20 21????/*?Used?for?vendor-specific?interface?matches?*/ 22????__u8????????bInterfaceNumber; 23 24????/*?not?matched?against?*/ 25????kernel_ulong_t??driver_info 26????????__attribute__((aligned(sizeof(kernel_ulong_t)))); 27};

#PCI設(shè)備表

1struct?pci_device_id?{ 2????__u32?vendor,?device;???????/*?Vendor?and?device?ID?or?PCI_ANY_ID*/ 3????__u32?subvendor,?subdevice;?/*?Subsystem?ID's?or?PCI_ANY_ID?*/ 4????__u32?class,?class_mask;????/*?(class,subclass,prog-if)?triplet?*/ 5????kernel_ulong_t?driver_data;?/*?Data?private?to?the?driver?*/ 6};

對于這兩種類型的設(shè)備,導(dǎo)出的符號信息和普通設(shè)備也不一樣。

PCI設(shè)備導(dǎo)出到用戶空間的設(shè)備信息:

導(dǎo)出PCI設(shè)備信息的代碼

USB設(shè)備導(dǎo)出到用戶空間的設(shè)備信息:


導(dǎo)出USB設(shè)備信息的代碼

除了上面三種設(shè)備描述table之外,kernel還提供了很多種其他的設(shè)備描述表,定義在include/linux/mod_devicetable.h



mod_devicetable.h的commit log:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/log/include/linux/mod_devicetable.h


推薦閱讀:

專輯|Linux文章匯總

專輯|程序人生

專輯|C語言

我的知識小密圈

關(guān)注公眾號,后臺回復(fù)「1024」獲取學(xué)習(xí)資料網(wǎng)盤鏈接。

歡迎點贊,關(guān)注,轉(zhuǎn)發(fā),在看,您的每一次鼓勵,我都將銘記于心~

總結(jié)

以上是生活随笔為你收集整理的Linux驱动程序的数据封装的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。