Linuxデバイスドライバーの移植プロセス

こんにちは、harachtochiteli!



はじめに



Linuxカーネルの新しいバージョンにアップグレードし、それに応じて既存のデバイスドライバーを転送する必要が生じることがあります。







転送プロセスには数分からより長い時間がかかる場合があります。 これは、ドライバーの複雑さだけでなく、どのバージョンのどのカーネルに切り替えるか(APIが変更される傾向があります-すべての問題はここから発生します)、およびコード実装の品質にも依存します。しかし、それについては話しません。



残念ながら、ドライバーのソースコードを添付することはできませんが、転送プロセス中に発生する可能性のあるすべての問題を確認します。 次に、drivers / serial / name_uart.cにあるカーネルバージョン2.6.25から4.12.5に単純なドライバーを移植する例を検討します。 次のリソース2.6.25および4.12.5では、カーネルの構造とソースコードを確認できます。



問題の声明



問題の記述は非常に原始的で単純です-上記のドライバーをカーネルバージョン2.6.25から4.12.5に転送する必要があります。



実装



まず、乗り換える必要があるドライバーに慣れていない場合は、少なくとも表面的な調査をお勧めします。 これにより、タスクを大幅に簡素化できます。 その後、転送に進むことができます。



最初のステップ



ドライバーの2.6.25カーネルには、次のパスがあります: drivers / serial / name_uart.c

次に、適切なディレクトリを見つける必要があります。 そして、ここで最初の問題に直面します-カーネル4.12.5にはそのようなドライバー/シリアル/ディレクトリがありません。



これは非常に簡単に解決されます:ドライバーをdrivers / tty / serial / name_uart.cに取り込んで配置します



第二段階



その後、Linuxがドライバーをアセンブリに含めることができるように、2つのファイルにドライバーを追加する必要があります。



最初のファイル: drivers / tty / serial / Makefile

次の行を追加します。



obj-$(CONFIG_SERIAL_NAME) += name_uart.o
      
      





2番目のファイル: drivers / tty / serial / Kconfig

その中に以下を書きます:



 config SERIAL_NAME tristate "SERIAL_NAME UART driver" help Write description here
      
      





第三段階



最初の2つの手順を完了すると、アセンブリに進むことができます。



ルートディレクトリからmake menuconfigを実行し、ドライバーをアセンブリに含めます。

コマンドを実行すると、グラフィカルインターフェイスが開き、ドライバーを見つけるのに問題はないはずです(検索は次の方法で実行できます:/を押して名前の全部または一部を入力してから入力します)。



別の方法があります-.configファイルを編集し、ドライバーをアセンブリに含めることができます。



次に、ドライバーをオンにしてカーネルの構築を試みることができます。



第4ステップ



カーネルをビルドしようとした後、おそらくカーネルを正常にビルドし、ドライバーの操作性を確認するために解決する必要があるエラーが発生した可能性があります。



私が遭遇したエラーは、procシステムとリモートマクロを操作するための古いインターフェイスでした。



たとえば、2.6.25カーネルのirequest_irq関数の呼び出しは成功しますが、



 irequest_irq(64 + ISC_DMA, dma_interrupt_handler, IRQF_DISABLED, "DMA", NULL);
      
      





カーネル4.12.5では、IRQF_DISABLEDマクロが削除されたため、ドライバーはビルドされませんでした。

解決策-IRQF_DISABLEDの代わりに0を使用して置き換えます。



 irequest_irq(64 + ISC_DMA, dma_interrupt_handler, 0, "DMA", NULL);
      
      





次のエラーは、カーネルバージョン2.6.25で、create_proc_entryを使用してprocシステムとの対話が発生したことでした。この実装は4.12.5にはありません。



したがって、実装を少し書き換える必要があり、その結果、次のオプションが判明しました。



 /****************************************************************************** * /proc interface ******************************************************************************/ static int xr16_get_status(struct seq_file *m, void *v) { struct uart_name_uart *pp; unsigned long f; u64 tmp; int i, xmax = ARRAY_SIZE(pp->in_irq); seq_printf(m, "UART NAME ports stat:\n"); for (i = 0; i < UART_NAME_MAXPORTS; i++) { pp = &uart_name_16_ports[i]; if (!pp->used) continue; local_irq_save(f); tmp = ktime_to_us(ktime_sub(ktime_get(), pp->ktm_last)); do_div(tmp, USEC_PER_SEC); /* *   . */ local_irq_restore(f); } return 0; } static int xr16_proc_open(struct inode *inode, struct file *file) { return single_open(file, uart_name_get_status, NULL); } static const struct file_operations uart_name_proc_fops = { .owner = THIS_MODULE, .open = uart_name_proc_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }
      
      





上記のすべてを要約すると、ドライバー転送は次のステップに分割されます。



1.以前のバージョンのドライバーのソースコードをLinuxカーネルの新しいバージョンにコピーします。

2. KconfigおよびMakefileに説明を追加します。

3.カーネルアセンブリのbusyboxを使用して(または.configファイルを直接編集して)ドライバーを選択します。

4.カーネルがアセンブルされるまで、アセンブル中のすべてのエラーを排除しようとします。



そこで、デバイスドライバーを新しいバージョンのLinuxカーネルに移植するプロセスがどのように発生するかという基本事項と、発生する可能性のある問題を調べました。



次の記事では、Linuxカーネルの新しいバージョンの1つに対する特定の技術タスク用の最初の本格的なネイティブドライバーを作成します。また、標準のLinuxユーティリティを使用してテストするだけでなく、独自のテストを作成します。



不正確な点を見つけた場合、または追加することがある場合は、PMまたはコメントに記入してください。



よろしくお願いします!



All Articles