驅動載入到I2C匯流排,如何執行到probe
為了簡短文章長度,一些檢查和除錯資訊被刪除
1. 在xxx_init()中會呼叫i2c_add_driver()函式
static int __init ltr559_init(void) { return i2c_add_driver(<r_ps_driver);//ltr_ps_driver是一個struct i2c_driver } static void __exit ltr559_exit(void) { i2c_del_driver(<r_ps_driver); } module_init(ltr559_init); module_exit(ltr559_exit);
2. i2c_add_driver
是一個巨集命令,呼叫 i2c_register_driver
/************************* include/linux/i2c.h *******************************/
#define i2c_add_driver(driver) \
i2c_register_driver(THIS_MODULE, driver)
3. i2c_register_driver
在一些 i2c_adapter 相關匯流排例項, 一個 i2c_driver 可以被一個或多個 i2c_client 裝置節點使用去訪問 i2c_slave_chip
該函式
/********************** kernel/drivers/i2c/i2c_core.c ************************/ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) { int res; /*在驅動模組初始化完成後才可以註冊 */ if (unlikely(WARN_ON(!i2c_bus_type.p))) return -EAGAIN; /* 新增該驅動到i2c驅動連結串列上 */ driver->driver.owner = owner; driver->driver.bus = &i2c_bus_type; /* 當註冊完成,驅動程式碼將呼叫probe()去匹配裝置 */ res = driver_register(&driver->driver); INIT_LIST_HEAD(&driver->clients); i2c_for_each_dev(driver, __process_new_driver); return 0; }
4. driver_register
主要的工作還是由 bus_add_driver 來操作
/*************************** kernel/driver/base/driver.c **************************/
int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;
BUG_ON(!drv->bus->p);
other = driver_find(drv->name, drv->bus);//通過driver_name在bus上查詢該driver,正常返回0
ret = bus_add_driver(drv); //主要
ret = driver_add_groups(drv, drv->groups);
if (ret) {
bus_remove_driver(drv);
return ret;
}
kobject_uevent(&drv->p->kobj, KOBJ_ADD);
return ret;
}
5. bus_add_driver
/**************** kernel/driver/base/bus.c **********************************/
int bus_add_driver(struct device_driver *drv)
{
struct bus_type *bus;
struct driver_private *priv;
int error = 0;
bus = bus_get(drv->bus);
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset;
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name);
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv); //嘗試繫結
}
module_add_driver(drv->owner, drv);
error = driver_create_file(drv, &driver_attr_uevent); //為驅動建立檔案,繼續呼叫sysfs_create_file()
error = driver_add_attrs(bus, drv);
if (!drv->suppress_bind_attrs) {
error = add_bind_files(drv);
}
return 0;
}
6. driver_attach
/**
* driver_attach - try to bind driver to devices.
* @drv: driver.
*
* Walk the list of devices that the bus has on it and try to
* match the driver with each one. If driver_probe_device()
* returns 0 and the @dev->driver is set, we've found a
* compatible pair.
*/
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
7. bus_for_each_dev
引數 fn 就是__driver_attach()函式
/**
* bus_for_each_dev - device iterator.
* @bus: bus type.
* @start: device to start iterating from.
* @data: data for the callback.
* @fn: function to be called for each device.
*/
int bus_for_each_dev(struct bus_type *bus, struct device *start,
void *data, int (*fn)(struct device *, void *))
{
struct klist_iter i;
struct device *dev;
int error = 0;
if (!bus || !bus->p)
return -EINVAL;
klist_iter_init_node(&bus->p->klist_devices, &i,
(start ? &start->p->knode_bus : NULL));
while ((dev = next_device(&i)) && !error)
error = fn(dev, data);
klist_iter_exit(&i);
return error;
}
8. __driver_attach
static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data;
if (!driver_match_device(drv, dev))
return 0;
if (dev->parent) /* 如果是被usb介面呼叫,父裝置也要上鎖*/
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev); //
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent);
return 0;
}
9. driver_probe_device
如果裝置沒有註冊,則該函式返回 -ENODEV , probe 成功 返回 1 ,失敗 返回 0 。該函式被呼叫時,裝置一定要上鎖
/********************** kernel/drivers/base/dd.c *********************************
* driver_probe_device - attempt to bind device & driver together
* @drv: driver to bind a device to
* @dev: device to try to bind to the driver
*/
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = 0;
if (!device_is_registered(dev)) //判斷裝置是否註冊
return -ENODEV;
pm_runtime_barrier(dev);
ret = really_probe(dev, drv);
pm_request_idle(dev);
return ret;
}
10. really_probe
/********************** kernel/drivers/base/dd.c *********************************/
static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = 0;
atomic_inc(&probe_count);
WARN_ON(!list_empty(&dev->devres_head));
dev->driver = drv;
ret = pinctrl_bind_pins(dev);
if (ret)
goto probe_failed;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
}
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {
ret = drv->probe(dev); //這裡才是正在呼叫驅動中實現的probe函式
if (ret)
goto probe_failed;
}
driver_bound(dev);
ret = 1;
goto done;
probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
if (ret == -EPROBE_DEFER) {
/* Driver requested deferred probing */
dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
driver_deferred_probe_add(dev);
} else if (ret != -ENODEV && ret != -ENXIO) {
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret);
} else {
pr_debug("%s: probe of %s rejects match %d\n",
drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret = 0;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
}
相關推薦
驅動載入到I2C匯流排,如何執行到probe
為了簡短文章長度,一些檢查和除錯資訊被刪除 1. 在xxx_init()中會呼叫i2c_add_driver()函式 static int __init ltr559_init(void) { return i2c_add_driver(<r_p
linux驅動開發:匯流排,裝置,驅動三要素
平臺匯流排和IIC,SPI,IIS都是匯流排型別,一般的,匯流排下,掛載對應的裝置。但實際上,裝置要正常運轉,是需要驅動程式來未知提供驅動的。所以linux核心也把驅動掛載在對應的匯流排下。匯流排,驅動,裝置三者缺一不可. 相應的,核心衍生出來的平臺匯流排,那
Linux驅動之I2C匯流排裝置以及驅動
[ 導讀] 本文通過閱讀核心程式碼,來梳理一下I2C子系統的整體檢視。在開發I2C裝置驅動程式時,往往缺乏對於系統整體的認識,導致沒有一個清晰的思路。所以從高層級來分析一下I2C系統的設計思路,將有助於設計除錯具體的驅動程式。 ## I2C/SMBUS基礎 I2C是一種晶片間通訊匯流排技術,最早由Ph
spring boot 匯出jar 包,執行報錯無法載入 orcl驅動的問題。
原因是因為orcl資料庫是收費的,所以在pom檔案中無法匯入所以需要手動新增jar包,但是打包的時候無法將手動的jar包打包,只打包maven中的jar。 解決的辦法: 需要自己本地建立一個maven本地倉庫,然後需要配置環境 。 將執行 mvn
(已解決)拷貝dll檔案到另一個專案,編譯不報錯,執行報錯“未能載入檔案或程式集...”
未能載入檔案或程式集“JUtility, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”或它的某一個依賴項。試圖載入格式不正確的程式。 需要注意該dll生成的目標平臺:右擊專案-生成-目標平臺, 引用這個dll的專案
java動態編譯class,動態載入類,執行載入類的方法,直接可執行測試
直接上圖上程式碼 public static void main(String[] args) { TestClass testClass=new TestClass(); try { //動態編譯程式碼 Java
開發必備知識點--django專案啟動時,url載入之前,執行某個.py檔案
django專案啟動時,自定義執行某個py檔案 在任意的app下的apps.py中的Config類下自定義ready()方法,並且呼叫autodiscover_modules。 app01/apps.py 1 from django.apps import AppConfig 2 from dj
記困擾很久的pytorch載入模型OOM,python import執行流程,python“懶執行”,whindows控制ubuntu遠端桌面
前言 半路接手專案,閱讀程式碼,解決bug,優化速度。 part one 1050 Ti載入模型時OOM model.load_state_dict(torch.load(path)) Copie
I2C匯流排驅動框架詳解
一、I2C子系統總體架構 1、三大組成部分 (1)I2C核心(i2c-core):I2C核心提供了I2C匯流排驅動(介面卡)和裝置驅動的註冊、登出方法,I2C通訊方法(”algorithm”)上層的,與具體硬體無關的程式碼以及探測裝置 檢測裝置地址的上層程式
vs程式執行時報錯"未能載入 SqlServerSpatialxxx.dll,找不到指定的模組,(異常來自......)"的解決方法
報錯原因: 因為程式中引用了Microsoft.SqlServer.Types程式集,正常情況下程式會去c:\windows\system32或者c:\windows\syswow64目錄中尋找,所以找不到。 其實你引用時已經在bin\debug\SqlServerTypes資料夾下生成了報
在c#中引用Microsoft.SqlServer.Types後,系統執行報"未能載入 SqlServerSpatial140.dll,找不到指定的模組,(異常來自......)的解決方法
1.在資源管理器中檢視C:\Windows\System32或者C:\Windows\SysWOW64下有沒有SqlServerSpatialXXX.dll的檔案,如果沒有,在網上下載後,把檔案重新命名為報錯的dll檔名,將其放入此目錄下 2.如果有,如下圖,我將原本的130改為140,程式便不
Linux--核心---I2C匯流排驅動分析 以linux3.10.0 RK3288為例
Linux 3.10.0 iic匯流排註冊過程 I2C匯流排驅動包括I2C介面卡驅動載入與解除安裝以及I2C匯流排通訊方法 I2C核心提供了i2c_adapter的增加和刪除函式、i2c_driver的增加和刪除函式、i2c_client的依附和脫離函式 以及i2c傳輸、傳送
第七章——Windows核心基礎-核心理論基礎(0環通訊,核心函式,驅動載入流程)
windowsR3與R0通訊 當我們呼叫某個API的時候,這個API是被封裝在某個DLL庫中,而DLL庫中的函式則是在更底層的ntdll.dll檔案中,而相對應的則是呼叫ntdll中的Native API函式ntdll中的
A31S android 手動載入攝像頭命令,驅動編譯進核心
insmod /system/vendor/modules/videobuf2-core.ko insmod /system/vendor/modules/videobuf2-memops.ko ins
gendisk,request與bio結構體,以及塊裝置驅動註冊與登出,以及載入與解除安裝
struct bio *bio; bio是這個請求中包含的bio結構體的連結串列,驅動中不宜直接存取這個成員,而應該使用後文將介紹的rq_for_each_bio()。 char *buffer; 指向緩衝區的指標,資料應當被傳送到或者來自這個緩衝區,這個指標是一個核心虛擬地址,可被驅動直接引用。 uns
Java虛擬機器結構(記憶體,類載入器,執行引擎)
1. JVM背景知識 1995年,Java誕生於Sun公司。目標:Write Once, Run Anywhere。 2006年,Sun宣佈Java開源,並在隨後1年,陸續將JDK的各部分在GPL v2協議下公開原始碼,並建立OpenJDK組織,對原始
Linux+I2C匯流排分析(主要是probe的方式)
Linux I2C 匯流排淺析 ㈠ Overview Linux的I2C體系結構分為3個組成部分: ·I2C核心: I2C核心提供了I2C匯流排驅動和裝置驅動的註冊、登出方法,I2C通訊方法(即“algorithm”)上層的、與具體介面卡無關的程式碼以及探測裝置、檢測裝置地址的上層程式碼等。這部分是與平臺無
js中如何控制所有頁面載入完成後,再執行某些方法
做頁面時經常會遇到當前頁面載入完成後,執行某些初始化工作。這時候就要知道如何判斷頁面(包括IFRAME)已經載入完成,程式碼如下: <script language="javascript"> document.onreadystatechange
i2c驅動程式(2) i2c_driver probe被呼叫的流程分析
(本文為個人的筆記 難免有錯 望各位高人賜教指正 謝謝!) i2c驅動程式i2c_driver probe被呼叫的流程分析 step1 i2c_add_driver(&at24_driver); step2 i2c_register_driver(T
java動態載入jar包,並執行其中的類和方法
動態載入jar包,在實際開發中經常會需要用到,尤其涉及平臺和業務的關係的時候,業務邏輯部分可以獨立出去交給業務方管理,業務方只需要提供jar包,就能在平臺上執行。 下面通過一個例項來直觀演示: 第一:定義一個抽象類 AbstractAction (稍後換成介面的例項) pa