私のカーネル研究ノート12:linuxi2c-gpioドライバーアプリケーションの例

inuxカーネルのi2c-gpioは、GPIOを使用してI2Cプロトコルをシミュレートするドライバーであり、使用する2つのGPIOを構成するだけで済みます。LinuxのI2Cサブシステムはもっと複雑で、私はまだそれを研究していません。「実用的な」目的で、このドライバーの使用方法といくつかの注意事項を紹介します。

1.概要
Linuxカーネルの多くのドライバーは、I2Cサブシステムを使用します。EEPROM、RTCなど。

GPIOアナログI2Cプロトコルのドライバーは、drivers / i2c / bussesディレクトリにあります。ドライバー名は「i2c-gpio」、ドライバーファイルはdrivers / i2c / busses /i2c-gpio.cです。

2.カーネル構成
この記事では、linux3.17.1バージョンに基づいてカーネルを分析します
カーネル構成(make menuconfig)情報は次のとおりです。
デバイスドライバー->
    I2Cサポート--->
        I2Cハードウェアバスサポート--->
            <*> GPIOベースのビットバンギングI2C 
は、構成から、ドライバーがモジュールではなくカーネルに統合されていることを確認できます。形。これにより、他のI2Cボードレベルの情報が登録される前に、i2cバスがすでに存在していることを確認できます。さらに、GPIOライブラリのサポートも必要です。

[*] GPIOサポート--->  

それ以外の場合、オプション「GPIOベースのビットバンギングI2C」は表示されません。

3.デバイスの登録と使用
3.1I2C関連の構造
この記事ではI2Cサブシステムについては説明しないため、原則の説明は脇に置いておきます。i2cプラットフォームデータ構造i2c_gpio_platform_dataの宣言を見てください。

/ **
 * structi2c_gpio_platform_data-i2c-gpioのプラットフォーム依存データ
 * @ sda_pin:SDAに使用する
 GPIOピンID
 * @scl_pin:SCLに使用するGPIOピンID * @udelay:信号トグル遅延。SCL周波数は(500 / udelay)kHz
 * @timeout:クロックストレッチタイムアウト(jiffies)。スレーブが
 * SCLをこれより長くローに保つと、転送はタイムアウトになります。
 * @sda_is_open_drain:SDAはオープンドレインとして構成されています。つまり
 、出力値をHighに設定すると、ピンは*アクティブにHighに駆動されません。
 * gpio_get_value()は、
 ピンが出力として構成されている場合でも、実際のピン状態を返す必要があります。
 * @scl_is_open_drain:SCLはオープンドレインとして設定されています。同じ要件
 * AS sda_is_open_drainのために適用します。
 * @Scl_is_output_only:SCL出力ドライバをオフにすることはできません。
 * /
構造体i2c_gpio_platform_data {     unsigned int型のsda_pinを、     unsigned int型のscl_pinを、     udelayのint型、     int型のタイムアウトを、     unsigned int型sda_is_open_drain :. 1;     unsigned int型scl_is_open_drain :. 1、     符号なしint scl_is_output_only:1; };重要なものはsda_pinとscl_pinで、それぞれI2CのSDAとSCL信号ピンを表します。UdelayはSCL周波数を制御でき、計算式は500 / udelaykHZです。timeoutは、jiffiesのタイムアウト期間です。sda_is_open_drainとscl_is_open_drainはそれぞれ、SDAとSCLがオープンドレイン回路であるかどうかを示します。この側面は深く研究されていないため、説明しません。例は次のとおりです。









static struct i2c_gpio_platform_data i2c_gpio_data = {     .sda_pin = 68、     .scl_pin = 88、     .timeout = 100、     .udelay = 2、};例で使用されているピンは68と88で、これらはマザーボードのハードウェアによって決定されます。3.2インターネットデバイスi2c-gpioドライバーエントリコードは次のように定義されます(ドライバー/ I2C /バス/I2C-gpio.c):static struct = {platform_driver i2c_gpio_driver     .driver = {         .name = "i2c-         gpio "、。owner = THIS_MODULE 、         。 of_match_table = of_match_ptr(i2c_gpio_dt_ids)、     } 、.     probe = i2c_gpio_probe、     .remove = i2c_gpio_remove、}; static int __init i2c_gpio_init(void){     int ret;

















 



 
    ret = platform_driver_register(&i2c_gpio_driver);
    if(ret)
        printk(KERN_ERR "i2c-gpio:probe failed:%d \ n"、ret);
 
    return ret;
}
subsys_initcall(i2c_gpio_init);
コード分​​析から、GPIOはI2Cをシミュレートしますバスはプラットフォームデバイスとして扱われます。i2c_gpio_driver構造から、ドライバー名がi2c-gpioであることがわかります。したがって、このドライバーを使用するには、別のプラットフォームデバイスを定義し、関数platform_device_registerを呼び出して登録する必要があります。この記事の例は次のとおりです

static struct platform_device i2c_gpio_device = {     .name = "i2c-gpio"、。id     = 0、// "i2c-gpio"の最初のバス、つまり-> 0     .dev = {     .platform_data =&i2c_gpio_data、     .release = platformdev_release、     }、};ここで、nameはデバイスの名前を表します。ここでは、「leds-gpio」である必要があります。platform_dataは、前に定義したi2c_gpio_dataです。idは、i2c-gpioのどのI2Cバスを示します。ドライバが正常に動作すると、/ sys / bus / platform / devices / i2c-gpio.idディレクトリが生成されます。このディレクトリには、このバスにマウントされているデバイスのアドレスが含まれています。最後に、デバイスを登録します。ボードのGPIOが正常に動作した後に登録することをお勧めします。








platform_device_register(&i2c_gpio_device)
。IV I2Cボード・レベルの情報登録のボード・レベルの情報
I2Cデバイスは、以下のように宣言されi2c_board_info構造、によって記述される:
{i2c_board_info構造体     char型[I2C_NAME_SIZE];     unsigned short型フラグ、     符号なしの短いADDR;     ボイド*のplatform_data、     構造体dev_archdata * archdata;     struct device_node * of_node;     struct acpi_dev_node acpi_node;     int irq; };この構造には、I2Cデバイス名、ロゴ、アドレス、およびその他の情報が含まれます。たとえば、マザーボードにはLM7​​5とEEPROMの2つのI2Cデバイスがあり、アドレスはそれぞれ0x48と0x50です。アドレスはデータシートの説明とハードウェアの配線に従って決定されます。ボードレベルの情報は次のように定義されます。staticstructat24_platform_dataat24_eeprom = {     .byte_len = 2 * 1024/8、     .page_size = 16














    .flags = 0、
};
 
static struct i2c_board_info my_i2c_boardinfo [] = {     {         I2C_BOARD_INFO( "lm75"、0x48)、     }、     {         I2C_BOARD_INFO( "24c02"、0x50)、// 24c02 == at24ドライバー         .platform_data =&at24_eeprom、     }、}; 2C_BOARD_INFO宏定义如下:#define I2C_BOARD_INFO(dev_type、dev_addr)\     .type = dev_type、.addr =(dev_addr)










一般的な登録方法は、静的登録i2c_register_board_infoと動的登録i2c_new_deviceに分けられます。ほとんどのARMフレームワークは、次のように非常に簡単に使用できる静的登録を使用します
。i2c_register_board_info(0、i2c_info、ARRAY_SIZE(i2c_info));
ただし、モジュールでコンパイルすると、i2c_register_board_infoが定義されていないことを確認します。

警告:「i2c_register_board_info」[drivers / gpio / gpio-misc.ko]は未定義です!

ここでは、動的登録の2番目の方法を使用します。最初にi2c_get_adapterを呼び出してアダプターを取得し(パラメーターはi2cバスであり、前のi2c_gpio_deviceで定義されたIDに従って決定されます)、次にi2c_new_deviceを呼び出してアダプターに追加します。コードフラグメントは次のとおりです
。structi2c_adapter* adap = NULL;
struct i2c_client * client = NULL;
 
adap = i2c_get_adapter(i2c_gpio_device.id); 
if(adap)
{     for(i = 0; i <ARRAY_SIZE(my_i2c_boardinfo); i ++)     {         client = i2c_new_device(adap、&my_i2c_boardinfo [i]);         pr_info( "%sをアダプタ%s%sに追加します。\ n"、my_i2c_boardinfo [i] .type、adap-                  > name、client? "ok": "failed");     } } else {     pr_info( "i2cバス%dはアダプターが見つかりませんでした... \ n"、i2c_gpio_device.id); }     5。ユーザースペース












ドライバが正常に動作すると、/ sys / bus / platform / devices / i2c-gpio.0ディレクトリが生成されます(この記事を例として取り上げます)。ドライブマッピングに対応するファイルは内部に保存されます。たとえば、/ sys / bus / platform / devices / i2c-gpio.0 / i2c-0 / 0-0050 / eepromはeepromコンテンツです。このファイルの属性は読み取りと書き込みが可能であるため、このファイルの内容を変更することは、EEPROMの内容を変更することを意味します(この方法は危険であり、直接書き込まれません)。
マザーボードの温度を表示するには、次のコマンドを使用できます
。cat
/sys/bus/platform/devices/i2c-gpio.0/i2c-0/0-0048/hwmon/hwmon0/ temp1_input注:ディレクトリ内の0-0050は、これを示しています。 0番目のバス上のI2Cデバイスの0x50アドレス。
6.まとめ
GPIOを使用してI2Cドライバーをシミュレートする前に、システムのGPIOが正常に機能することを確認することをお勧めします。

複数のi2c-gpioバスをドライバーに登録でき、ドライバー名はすべてi2c-gpioですが、同じバスはid値によって区別されます。たとえば、マザーボードには3つのGPIOアナログバスがあり、0、1、および2という名前を付けることができます。

参考資料:

1.カーネルソースコードの公式ウェブサイト:https://www.kernel.org

2、カーネルソースコードクエリ:HTTP://lxr.free-electrons.com/source/ v = 3.17?
--------------------- 
作成者:  LeeChi
ソース:CSDN
原文:https ://blog.csdn.net/subfate/article/details/53524887?utm_source = copy 
著作権表示: この記事はブロガーの原文です。転載する場合はブログ投稿へのリンクを添付してください!

おすすめ

転載: blog.csdn.net/qq_26690505/article/details/83023073