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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

platform_get_resource

發布時間:2023/12/16 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 platform_get_resource 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

platform_get_resource函數

在后續Linux設備驅動開發中會用到此函數,且在后續文章中會跳轉過來,提前埋下種子。
文中提到的《設備樹如何轉換成platform_device》和《Linux設備樹解析》,后續會更新。

platform_get_resource函數原型

功能:從設備中獲取相關資源。
參數@dev:平臺設備。描述設備信息的,有設備樹描述。
參數@type: 資源類型。下文詳細講解。
參數@num: 資源索引。同類型資源進行重新編號后的下標編號,注意和資源數組中的元素數量即num_resources區別。(要注意這一點),最后總結時會講到。

/*** platform_get_resource - get a resource for a device* @dev: platform device* @type: resource type* @num: resource index*/ struct resource *platform_get_resource(struct platform_device *dev,unsigned int type, unsigned int num) {u32 i;for (i = 0; i < dev->num_resources; i++) {struct resource *r = &dev->resource[i];if (type == resource_type(r) && num-- == 0)return r;}return NULL; }

補充Linux下設備資源相關知識

IIC、SPI、GPIO 等這些外設都有對應的寄存器,這些寄存器其實就是一組內存空間,Linux內核使用resource結構體來描述一段內存空間,“resource”翻譯出來就是“資源”,因此用resource結構體描述的都是設備資源信息,resource 結構體定義在include/linux/ioport.h 中,定義如下:

/** Resources are tree-like, allowing* nesting etc..*/struct resource {resource_size_t start;resource_size_t end;const char *name;unsigned long flags;unsigned long desc;struct resource *parent, *sibling, *child;};對于 32 位的 SOC 來說,resource_size_t 是 u32 類型的。 其中 start 表示開始地址,end 表示結束地址, name 是這個資源的名字,flags 是資源標志位,一般表示資源類型, 可選的資源標志定義在文件 include/linux/ioport.h 中,如下所示:/** IO resources have these defined flags.** PCI devices expose these flags to userspace in the "resource" sysfs file,* so don't move them.*/ #define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */ #define IORESOURCE_IO 0x00000100 /* PCI/ISA I/O ports */ #define IORESOURCE_MEM 0x00000200 #define IORESOURCE_REG 0x00000300 /* Register offsets */ #define IORESOURCE_IRQ 0x00000400 #define IORESOURCE_DMA 0x00000800 #define IORESOURCE_BUS 0x00001000#define IORESOURCE_PREFETCH 0x00002000 /* No side effects */ #define IORESOURCE_READONLY 0x00004000 #define IORESOURCE_CACHEABLE 0x00008000 #define IORESOURCE_RANGELENGTH 0x00010000 #define IORESOURCE_SHADOWABLE 0x00020000#define IORESOURCE_SIZEALIGN 0x00040000 /* size indicates alignment */ #define IORESOURCE_STARTALIGN 0x00080000 /* start field is alignment */#define IORESOURCE_MEM_64 0x00100000 #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ #define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */#define IORESOURCE_EXT_TYPE_BITS 0x01000000 /* Resource extended types */ #define IORESOURCE_SYSRAM 0x01000000 /* System RAM (modifier) */#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */#define IORESOURCE_DISABLED 0x10000000 #define IORESOURCE_UNSET 0x20000000 /* No address assigned yet */ #define IORESOURCE_AUTO 0x40000000 #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */

大家一般最常見的資源標志就是IORESOURCE_MEM ,IORESOURCE_REG 和 IORESOURCE_IRQ 等。比如后續更新的Linux下CAN驅動開發中也使用了platform_get_resource(pdev,IORESOURCE_MEM, 0),IORESOURCE_MEM代表內存地址。

回到正題,繼續分析上面函數

描述設備信息,傳統的用 platform_device 來描述設備信息。當 Linux 內核支持了設備樹以后就不需要用戶手動去注冊platform 設備了。因為設備信息都放到了設備樹中去描述,Linux 內核啟動的時候會從設備樹中讀取設備信息,然后將其組織成 platform_device 形式,至于設備樹到 platform_device 的具體過程參考《設備樹如何轉換成platform_device》

下面列舉platform_device這種“古老”方式來編寫設備信息,用來分析platform_get_resource如何拿到設備信息的。設備樹方式來編寫設備信息的框架就不寫了,現在很常用,后續更新設備樹的詳細介紹,包括語法等,參考《Linux設備樹解析》。

/******************** 采用自定義platform_device這種“古老”方式來編寫設備信息 **********************/ // 簡要描述xxxdevice.c 即platform_device框架如下所示#include <linux/xxx.h> ....../* 寄存器地址定義*/ #define PERIPH1_REGISTER_BASE (0X20000000) /* 外設 1 寄存器首地址 */ #define PERIPH2_REGISTER_BASE (0X020E0068) /* 外設 2 寄存器首地址 */ #define REGISTER_LENGTH 4/* 設備資源信息 */ static struct resource xxx_resources[] = {[0] = {.start = PERIPH1_REGISTER_BASE,.end = (PERIPH1_REGISTER_BASE + REGISTER_LENGTH - 1),.flags = IORESOURCE_MEM,},[1] = {.start = PERIPH2_REGISTER_BASE,.end = (PERIPH2_REGISTER_BASE + REGISTER_LENGTH - 1),.flags = IORESOURCE_MEM,}, };/* platform 設備結構體 */ static struct platform_device xxxdevice = {.name = "xxx-peripheral",.id = -1,.num_resources = ARRAY_SIZE(xxx_resources),.resource = xxx_resources, };/* 設備模塊加載 */ static int __init xxxdevice_init(void) {return platform_device_register(&xxxdevice); }/* 設備模塊注銷 */ static void __exit xxx_resourcesdevice_exit(void) {platform_device_unregister(&xxxdevice); }module_init(xxxdevice_init); module_exit(xxxdevice_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("TieTouXiaoGe");/*********************************************** 結束 *********************************************/

所以上述for循環的次數即資源數組xxx_resources[]的元素數量。
struct resource *r = &dev->resource[i]; 表示從第一份資源開始逐個搜索,
然后if (type == resource_type( r ) && num-- == 0),這行代碼首先通過
type == resource_type( r )判斷當前這份資源的類型是否匹配,如果匹配則再通過num-- == 0判斷是否是你要的(這里先判斷是否等于0再自減1),如果不匹配重新提取下一份資源而不會執行num-- == 0這一句代碼。通過以上兩步就能定位到你要找的資源了,接著把資源返回即可。如果都不匹配則return NULL。

總結

// 設備驅動開發中常用 struct resource *res res = platform_get_resource(pdev, IORESOURCE_MEM, 0); // 獲取設備內存地址資源。struct resource *platform_get_resource(struct platform_device *dev,unsigned int type, unsigned int num)

unsigned int type決定資源的類型,unsigned int num決定type類型的第幾份資源(從0開始)。即使同類型資源在資源數組中不是連續排放也可以定位得到該資源。比如第一份IORESOURCE_IRQ類型資源在resource[2],而第二份在resource[5],那platform_get_resource(pdev,IORESOURCE_IRQ,0);可以定位第一份IORESOURCE_IRQ資源;
platform_get_resource(pdev,IORESOURCE_IRQ,1);可以定位第二份IORESOURCE_IRQ資源。
之所以能定位到資源,在于函數實現中的這一行代碼:
if (type == resource_type( r ) && num-- == 0)該行代碼,如果沒有匹配資源類型,
num-- == 0不會執行而重新提取下一份資源,只有資源匹配了才會尋找該類型的第幾份資源,即使這些資源排放不連續。(解釋了上面的參數@num)

總結

以上是生活随笔為你收集整理的platform_get_resource的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。