平臺設備驅動模型

    對於字符設備驅動程序,之前都是在驅動程序中定義並設置file_operations結構體,實現各種需要用到的函數,註冊file_operations結構體,框架比較簡單,但是在Linux中,卻很少看見這樣框架的代碼,那是因爲在Linux中設備驅動模型一般都由總線、設備、驅動這個三大部分組成。這是一種分層分離的思想:

分層:核心層和設備相關層分開。

分離:講硬件相關的代碼和驅動分開。

這就是總線設備驅動(bus_drv_dev)模型:

對於dev模塊,當調用device_add函數時:

a.會將device結構體放入bus的device鏈表

b.從bus的drv鏈表中取出每一個結構體,利用match函數進行對比,判斷是否當前的這個dev

c.如支持,則調用驅動額probe函數

對於drv模塊,當調用driver_register時:

a.會將driver結構體放入bus的driver結構體

b.從bus的dev結構體中取出每一個結構體,通過match函數比較,判斷是否支持當前driver

c.若支持,這調用驅動的probe函數

wKioL1aD7kDDTlFTAACC3oPESbU113.png

match函數的比較:

match函數是根據device中的bus_id和driver的name是否一致來匹配的,如果一樣就調用driver中的probe函數


編寫驅動的步驟:

一.在device部分(device.c)

1.定義並設置一個platform_device結構體:包括name(要和driver中的名字對應)、dev結構體下完成一個release函數、一個resource結構體(需要自己定義並填充),這個結構體中有着硬件相關的地址

如:static resource led_dev_resource[]={

[0]={

.start=0x56000050,

.end=0x56000050+4-1,

.flags=IORESOURCE_MEM,

},

[1]={

.start=4,

.end=4,

.flags=IORESOURCE_IRQ,

},

};

static void led_dev_release(struct device * dev)

{

}

static platform_device led_dev={

.name = "myled",

.id = -1,

.resource=led_dev_resource,

.dev={

.release=led_dev_release,

},

};

2.註冊platform_device結構體


int platform_device_register(struct platform_device * pdev)//註冊platform_device結構體

void platform_device_unregister(struct platform_device * pdev)//卸載


二.在driver部分(driver.c)

1.定義並設置一個platform_driver結構體,

如:static platform_driver led_drv={

.probe=led_drv_probe,//匹配後講調用的函數

.remove=led_drv_remove,//與probe相關的清理工作

.driver={

.name="myled",//名字必須與platform_device中的name相同

.owner=THIS_MODULE,

},

};

2.註冊

int platform_device_register(struct platform_device * pdev)

例子:講led點燈拆分成dev和dri兩個部分

在dev.c中(部分核心代碼)

wKiom1aD8L2iKfPrAAJXjTYGMHc358.png

在drv中(部分代碼)

wKiom1aD8hWhr8zSAAIzN00siuQ835.png

wKioL1aD8pbRW1VPAAJ74hS6dmk448.png

wKiom1aD8qTgzP4aAAEjw2z9B9M464.png

整體上實現了一個bus-dev-drv模型的驅動程序,這樣做的好處:當我們需要修改硬件的時候,只需要修改dev中的代碼即可,不需要動dri中的代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章