Windows system >> Windowsの知識 >  >> Linuxシステムチュートリアル >> Linuxチュートリアル >> I2Cデバイスとドライバの関連付け

I2Cデバイスとドライバの関連付け

  

Linux オペレーティングシステム
には、カーネル起動時の自動ロードとユーザーによる手動ロードの2種類があります。ハードウェアデバイスも2つの方法で追加できます。システムへ:システム起動前およびシステム実行中のホットプラグ以下では、ハードウェアデバイスと関連ドライバがどのようにバインドされ、緩められるかを紹介するために、アームアーキテクチャの下のat91プロセッサのI2Cコントローラを例として取り上げます。

1.プラットフォームドライバの登録プロセス

1.1 at91_i2c_init()関数

ファイルdrivers /i2c /bus /i2c-at91.cには、構造体platform_driverが定義されています。モジュールがカーネルにロードされたときにat91_i2c_init()関数を呼び出すmodule_init()マクロを使用して初期化および宣言されます。この関数では、登録を完了するためにplatform_driver_register()関数が呼び出されます。


static struct platform_driver at91_i2c_driver = {

.probe = at91_i2c_probe、

.remove = __devexit_p(at91_i2c_remove)、

。中断= at91_i2c_suspend、

.resume = at91_i2c_resume、

.driver = {

.name =" at91_i2c"、

.owner = THIS_MODULE、

}、

};


static int __init at91_i2c_init(void)

{
return platform_driver_register (& at91_i2c_driver);

}

1.2 platform_driver_register()関数

ファイルdrivers /base /platform.cでは、platform_driver_register()関数が実装およびエクスポートされています。他のモジュールの関数がこの関数を呼び出せるようにするためです。単純なラッパーが完成したら、driver_register()関数を呼び出して、プラットフォーム実装からLinuxカーネル実装への移行を完了します。

ここでは、platform_match()およびplatform_drv_probe()関数に注意を払う必要があります。 platform_match()関数は、ドライバとデバイスの関連付けを決定し、platform_drv_probe()関数は後述の関数で呼び出されます。

//ドライバ情報の名前とデバイス情報の名前を比較する

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

{

struct platform_device * pdev = container_of(dev、struct platform_device、dev);


return(strncmp(pdev-> name、drv-> name、 BUS_ID_SIZE)== 0);

}


struct bus_type platform_bus_type = {

.name =" platform"、

.dev_attrs = platform_dev_attrs、

.match = platform_match、

.uevent = platform_uevent、

.suspend = platform_suspend、

.suspend_late = platform_suspend_late、

.resume_early = platform_resume_early、

.resume = platform_resume、

};

EXPORT_SYMBOL_GPL(platform_bus_type);


/**

* platform_driver_register

* @drv:プラットフォームドライバ構造体

* /

int platform_driver_register(struct platform_driver * drv)< Br>

{

drv-> driver.bus =& platform_bus_type;

//really_probe関数内platform_drv_probe関数へのコールバック

if(drv-> probe)

drv-> driver.probe = platform_drv_probe;

if(drv-> remove)

drv-> driver.remove = platform_drv_remove;

if(drv-> shutdown)

drv-> driver.shutdown = platform_drv_shutdown;

if(drv-> suspend)

drv-> driver.suspend = platform_drv_suspend;

if(drv-> resume)

drv-> driver。再開= platform_drv_resume;

return driver_register(& drv-> driver);

}

EXPORT_SYMBOL_GPL(platform_driver_register);


1.3 driver_register()関数

ファイルdrivers /base /driver.cには、driver_register()関数が実装されています。この関数では、構造体struct device_driver内のklist_deviceおよびアンロードされたフィールドが初期化され、klist_deviceフィールドを介して、ドライバによってサポートされているデバイスリンクリストを保存し、' complete'インターフェイスメカニズムを介してスレッド間の同期を完了する。リンクリストと“ Complete”インターフェースに関する詳細な情報は[1]にあります。 bus_add_driver()関数を実行した結果を返します。


/**

* driver_register - ドライバをバスに登録する

* @drv:登録するドライバ

*

*ほとんどの作業はbus_add_driver()呼び出しに渡されます。

*ほとんどの作業はバスに関するものです。

*構造体>

*

*興味深い点の1つは、@ drv-> unloaded

*をドライバの参照時に完了するように設定することです。

*カウントが0になります。

* /

int driver_register(struct device_driver * drv)

{

if((drv-> bus->プローブ&& drv->プローブ)| |

(drv->バス>削除&&& drv->削除)| |

(drv-> bus-> shutdown&&< drv-> shutdown)){

printk(KERN_WARNING"ドライバ '%s'は更新が必要です - bus_typeを使用してくださいメソッド\\ n"、drv-> name);

}

klist_init(& drv-> klist_devices、NULL、NULL);

init_completion(& name) Drv->アンロード済み);

return bus_add_driver(drv);

}


1.4 bus_add_driver()関数

bus_add_driver()関数はファイルdrivers /base /bus.cに実装されています。これはドライバ情報をバス構造体に保存し、ステートメントklist_add_tail(& drv-> knode_bus、& bus-> klist_drivers)を介してデバイスに登録します。その過程で、私たちはこの声明の役割を理解することができます。このステートメントの前にdriver_attach()関数が呼び出されました。

/**

* bus_add_driver - バスにドライバを追加する。

* @drv:driver。

*

* /

int bus_add_driver(struct device_driver * drv)

{

intエラー= 0;


if(!bus)

戻り値0;


pr_debug(" bus%s:ドライバ%sを追加してください。\\ n"、バス - > name、drv-> name);

Copyright © Windowsの知識 All Rights Reserved