ホームページ > システムチュートリアル > Linux > Linux デバイス ツリー dts 移植: ハードウェア構成情報を記述して転送する方法

Linux デバイス ツリー dts 移植: ハードウェア構成情報を記述して転送する方法

WBOY
リリース: 2024-02-13 11:27:12
転載
1003 人が閲覧しました

Linux システムでは、デバイス ツリーはハードウェア構成を記述するツリー データ構造です。これはオープン ファームウェア標準に由来し、システムを起動して実行するためのオペレーティング システム ソフトウェアとハ​​ードウェア間のインターフェイスを提供するために使用されます。デバイス ツリーは、新しいハードウェアをサポートするためにカーネルに必要な変更を減らし、コードの再利用を改善し、Linux サポート パッケージの開発を加速し、単一のカーネル イメージで複数のシステムをサポートできるようにします。この記事では、デバイス ツリーのデータ ストレージ形式、ソース コード記述構文、U-Boot および Linux カーネルのサポート、デバイス ツリーの解析プロセスなど、Linux デバイス ツリー dts 移植の基本的な手順と方法を紹介します。

Linux デバイス ツリー dts 移植: ハードウェア構成情報を記述して転送する方法

キーワード: フラット デバイス ツリー、DTS、PowerPC、Linux

IBM、Sun、およびその他のメーカーのサーバーは、当初ファームウェア (ハードウェア デバイスに組み込まれたプログラムであり、
を備えたもの) を使用していました。 (ソフトウェアとハ​​ードウェア間のインターフェイスを提供するために使用されます)、システム構成を初期化し、オペレーティング システム ソフトウェアとハ​​ードウェア間のインターフェイスを提供するために使用されます
システムを起動して実行するためのポート。その後、標準化と互換性を目的として、IBM、Sun などが共同でファームウェア インターフェイス IEEE 1275
を発売しました。 IBM PowerPC pSeries、Apple PowerPC、Sun SPARC などのサーバーはすべて Open
を使用します。 ファームウェアは実行時にシステム ハードウェアのデバイス ツリー情報を構築し、それをカーネルに渡してシステムを起動します [1]。それで### 利点としては、カーネルのシステム ハードウェアへの大きな依存の軽減、サポート パッケージの開発の加速、ハードウェアによる変更の削減などがあります。 これにより、需要とコストが削減され、カーネルの設計とコンパイルの要件が軽減されます。

Linux/ppc64 カーネルの開発に伴い、カーネル コードは元の Arch/ppc32 および Arch/ppc64 から

に徐々に移行されました。 Arch/powerpc ディレクトリを統合し、標準ファームウェア インターフェイスを使用するためにカーネル コードに Open Firmware API を導入します [2]。

Linux カーネルの実行時には、ハードウェアに関するいくつかの関連情報を知る必要があります。 ARCH=powerpc パラメータを使用してコンパイルされた
の場合 カーネル イメージ、この情報はオープン ファームウェア仕様に基づいており、デバイス ツリーの形式で存在する必要があります [3]。このようにして、カーネルが起動します
実行時にオープン ファームウェアによって提供されるデバイス ツリーを読み取り、スキャンして、プラットフォームのハードウェア デバイス情報を取得し、一致するデバイスを検索します
デバイスドライバーを選択し、ドライバーをデバイスにバインドします。

組み込み PowerPC では、通常、Open Firmware の代わりに U-Boot などのシステム ブート コードが使用されます。

初期の U-Boot は、include/asm-ppc/u-boot.h の静的データ構造体 struct bd_t を使用して、ボードに関する基本情報を転送しました

それをカーネルに渡し、カーネルが残りを処理します。このようなインターフェイスは十分な柔軟性がありません。ハードウェアが変更された場合は、コンパイルと書き込みを再カスタマイズする必要があります
ブート コードとカーネルを作成すると、それは現在のカーネルには適さなくなります。カーネルと組み込み PowerPC
の開発に適応するため プラットフォームは常に変化しているため、U-Boot では、標準のオープン ファームウェアの利点を吸収してフラット デバイス ツリー FDT を導入しています。 別個の FDT BLOB (バイナリ ラージ オブジェクト、バイナリ ファイルを保存できるコンテナ) を使用した動的インターフェイス
カーネルに渡されるパラメータを保存します [3]。キャッシュ サイズ、割り込みルーティングなどの特定の情報は、デバイス ツリー
によって直接提供されます。 eTSEC の MAC アドレス、周波数、PCI バス番号などのその他の情報は、実行時に U-Boot によって変更されます。
U-Boot は bd_t をフラット デバイス ツリーに置き換え、bd_t との下位互換性は保証されなくなりました。


2 デバイスツリーの概念

簡単に言うと、デバイス ツリーはハードウェア構成を記述するツリー状のデータ構造であり、ルート ノードは 1 つだけです [4]。を含む ### CPU、物理メモリ、バス、シリアル ポート、PHY、およびその他の周辺デバイスに関する情報が含まれます。ツリーは Open を継承します ファームウェア IEEE 1275 デバイス ツリー定義。オペレーティング システムは、起動時にこの構造を構文解析して構成できます。 カーネルをセットアップし、対応するドライバーをロードします。

3 デバイスツリーの保存形式

U-Boot は、メモリ内のデバイス ツリーのストレージ アドレスをカーネルに渡す必要があります。ツリーは主に 3 つの部分で構成されます。 Head

(ヘッダー)、構造ブロック (Structure ブロック)、Strings ブロック (Strings ブロック)。メモリ内のデバイス ツリーの保存

ストレージ レイアウト図 1 は次のとおりです。 図 1 デバイスツリーの保存形式図 図1 DTブロックのレイアウト


3.1 ヘッダー

ヘッダには、デバイスツリーのマジックナンバーフラグ、デバイスツリーのブロックサイズ、ストラクチャブロックのオフセットアドレスなど、主にデバイスツリーの基本情報が記述されます

その具体的な構造 boot_param_header は次のとおりです。この構造体の値はビッグエンディアン モードとオフセット

で表現されます。 アドレスは、デバイス ツリー ヘッドの開始アドレスを基準にして計算されます。
3.2 構造ブロック

フラットデバイスツリー構造ブロックは線形化されたツリー構造であり、文字列ブロックとともにノード

から始まるデバイスツリーの本体を形成します。 ターゲットボードのデバイス情報をフォームに保存します。ストラクチャーブロックでは、ノード開始フラグは定数マクロ OF_DT_BEGIN_NODE,

です。 ノード終了マークはマクロ OF_DT_END_NODE であり、子ノードはノード終了マークの前に定義されます。ノードは要約できます OF_DT_BEGIN_NODE で始まり、ノード パス、属性リスト、子ノード リストが含まれ、 で終わります。 OF_DT_END_NODE でシーケンスが終了し、各子ノード自体も同様の構造になります。

3.3 文字列ブロック
スペースを節約するために、一部の属性名、特に繰り返し重複して出現する属性名は、個別に抽出されて保存されます
文字列ブロックに。このブロックには、終了フラグを持つ多数の属性名の文字列が含まれています。
はデバイスツリーの構造ブロックに格納されます これらの文字列のオフセット アドレス。これにより、属性名の文字列を簡単に見つけることができます。文字列ブロックの導入により埋め込みが節約されます
内蔵システムの保管スペースは限られています。

4 デバイス ツリーのソース コードの DTS 表現
デバイス ツリー ソース コード ファイル (.dts) は、システム ハードウェア構成デバイス ツリーを読み取り可能および編集可能なテキスト形式で記述し、C/C
をサポートします。 メソッドに関するコメント。構造には一意のルート ノード「/」があり、各ノードには独自の名前があり、複数の
を含めることができます。 子ノード。デバイスツリーのデータ形式は、Open Firmware IEEE 標準 1275 に従います。この記事では、デバイス ツリーの
について簡単に説明するだけです。 データのレイアウトと構文については、Linux ボード サポート パッケージの開発者は、IEEE 1275 標準 [5] およびその他のドキュメント [2] [4] を参照してください。
これを説明するために、まず、PowerPC MPC8349E プロセッサーに基づく最小システムのデバイス ツリー ソース コードの例を示します。
ご覧のとおり、このデバイス ツリーには多数のノードがあり、各ノードにはノード ユニット名が指定されています。各属性の後には
が続きます 対応する値を与えてください。二重引用符で囲まれた内容は ASCII 文字列であり、山括弧で囲まれた内容は 32 ビットの 16 進数
です。 価値。このツリー構造は、ルート ノードの基本モードを含む、Linux カーネルの起動に必要なノードと属性の簡略化されたコレクションです。 CPU および物理メモリのレイアウトに関する情報に加え、/chosen ノードを通じてカーネルに渡されるコマンド ライン引数の情報も含まれます。
リーリー

4.1 ルートノード デバイスツリーの始点をルートノード「/」と呼びます。属性モデルは、ターゲット ボード プラットフォームまたはモジュールの名前、属性
を指定します。 互換性の値は、ターゲット ボードと同じシリーズの互換性のある開発ボードの名前を示します。ほとんどの 32 ビット プラットフォームの場合、プロパティ
#address-cells と #size-cells の値は通常 1 です。

4.2 CPU ノード /cpus ノードはルート ノードの子ノードであり、システム内の各 CPU に対応するノードがあります。 /cpu ノード
必須のプロパティはありませんが、
も参照する #address-cells = および #size-cells = を指定することをお勧めします。 各 CPU ノードの reg 属性形式を理解し、物理 CPU の番号付けを容易にします。

このノードには、ボード上の各 CPU のプロパティが含まれている必要があります。 CPU 名は通常、

のように PowerPC と表記されます。 Freescale では、この記事で MPC8349E プロセッサについて説明するために PowerPC,8349 を使用します。 CPU ノードのユニット名は
である必要があります。 cpu@0 の形式では、このノードは通常、device_type (「cpu」に固定) と、第 1 レベルのデータ/命令キャッシュのエントリを指定する必要があります。 サイズ、1次データ/命令キャッシュのサイズ、コア、バスクロック周波数など。上記の例ではシステムを介して起動しています
コードはクロック周波数関連の項目を動的に入力します。

4.3 システムメモリノード

このノードは、ターゲット ボード上の物理メモリ範囲を記述するために使用されます。通常、/memory ノードと呼ばれます。1 つまたは複数のノードが存在します。 複数のノードがある場合は、ノードを区別するためにユニットアドレスを続ける必要がありますが、ユニットアドレスが 1 つだけの場合は、ユニットアドレスを記述する必要はありません (
) デフォルトは 0 です。

このノードにはボード上の物理メモリの属性が含まれており、通常、device_type ("memory" に固定) と reg

を指定する必要があります。 属性。 reg の属性値は、上記の例に示すように、ターゲット ボード メモリの開始点の形式で与えられます

アドレスは0、サイズは256Mバイトです。

4.4 /選択されたノード

このノードは少し特殊です。通常、Open Firmware はパラメータ、 などの変数環境情報を保存します。 デフォルトの入出力デバイス。
通常、bootargs および linux、stdout-path 属性値はこのノードで指定されます。 bootargs 属性はカーネルに渡されるように設定されています
カーネルコマンドラインの引数文字列。 Linux の場合、stdout-path は標準端末デバイスのノード パス名であることが多く、カーネルはこれを
として使用します。 デフォルトの端末として。

U-Boot は、バージョン 1.3.0 以降のフラット デバイス ツリー FDT のサポートを追加しました。U-Boot は Linux カーネルをロードします。

Ramdisk ファイル システム (使用されている場合) とデバイス ツリー バイナリが物理メモリにミラーリングされたら、起動後に Linux

を実行します。 カーネルの前に、デバイス ツリー バイナリが変更されます。デバイス ツリーに MAC アドレス、
などの必要な情報が入力されます。 PCIバス数などU-Boot は、シリアル ポート、ルート
を含むデバイス ツリー ファイルの「/chosen」ノードにも入力します。 デバイス (Ramdisk、ハードディスク、または NFS ブート) およびその他の関連情報。

4.5 システムオンチップ SOC ノード

このノードは、システム オン チップ SOC を記述するために使用されます。プロセッサが SOC の場合、このノードが存在する必要があります。上位の SOC セクション ドットに含まれる情報は、この SOC 上のすべてのデバイスに表示されます。ノード名には、この SOC のユニット アドレス (この SOC
) が含まれている必要があります。 メモリマップドレジスタのベースアドレス。 SOC ノード名は /soc の形式で名前が付けられます (MPC8349 の SOC
など)。 ノードは「soc8349」です。

在属性中应该指定device_type(固定为”soc”)、ranges、bus-frequency 等属性。ranges
属性值以的形式指定。SOC 节点还包含目标板使用的每个
SOC 设备子节点,应该在设备树中尽可能详细地描述此SOC 上的外围设备。如下给出带有
看门狗设备的SOC 节点DTS 示例。

soc8349@e0000000 {
\#address-cells = ;
\#size-cells = ;
device_type = "soc";
compatible = "simple-bus";
ranges = ; /* size 1MB */
reg = ;
bus-frequency = ; /* from bootloader */
{
device_type = "watchdog";
compatible = "mpc83xx_wdt";
reg = ; /* offset: 0x200 */
};
};
ログイン後にコピー

4.6 其他设备节点
分级节点用来描述系统上的总线和设备,类似物理总线拓扑,能很方便的描述设备间的
关系。对于系统上的每个总线和设备,在设备树中都有其节点。对于这些设备属性的描述和
定义请详细参考IEEE 1275 标准及本文参考文献[2]。

设备树的中断系统稍显复杂,设备节点利用interrupt-parent 和interrupts 属性描述到中
断控制器的中断连接。其中interrupt-parent 属性值为中断控制器节点的指针,#interrupts 属
性值描述可触发的中断信号,其值格式与中断控制器的interrupt-cells 属性值有关。一般
#interrupt-cells 属性值为2,interrupts 属性就对应为一对描述硬件中断号和中断触发方式的
十六进制值。

5 扁平设备树编译
根据嵌入式板的设备信息写设备树源码文件(.dts)通常比较简单,但是手写二进制的
扁平设备树(.dtb)就显得比较复杂了。设备树编译器dtc 就是用来根据设备树源码的文本
文件生成设备树二进制镜像的。dtc 编译器会对输入文件进行语法和语义检查,并根据Linux
内核的要求检查各节点及属性,将设备树源码文件(.dts)编译二进制文件(.dtb),以保证
内核能正常启动。dtc 编译器的使用方法如下所示[6]:
dtc [ -I dts ] [ -O dtb ] [ -o opt_file ] [ -V opt_version ] ipt_file
2.6.25 版本之后的内核源码已经包含了dtc 编译器。在配置编译内核时选中
CONFIG_DTC,会自动生成设备树编译器dtc。将编写的目标板设备树文件mpc8349emitx.dts
放到内核源码的arch/powerpc/boot/dts/目录下,利用内核Makefile 生成blob 的简单规则,使
用以下命令亦可完成设备树的dtc 编译:
$ make mpc8349emitx.dtb

6 U-Boot 相关设置说明
为使 U-Boot 支持设备树,需要在板子配置头文件中设置一系列宏变量。如本文在

MPC8349E 处理器目标板中移植的U-Boot 配置如下:
/* pass open firmware flat tree */
\#define CONFIG_OF_LIBFDT 1
\#undef CONFIG_OF_FLAT_TREE
\#define CONFIG_OF_BOARD_SETUP 1
\#define CONFIG_OF_HAS_BD_T 1
\#define CONFIG_OF_HAS_UBOOT_ENV 1
启动引导代码U-Boot 在完成自己的工作之后,会加载Linux 内核,并将扁平设备树的
地址传递给内核,其代码形式如下:
\#if defined(CONFIG_OF_FLAT_TREE) || defined(CONFIG_OF_LIBFDT)
if (of_flat_tree) { /* device tree; boot new style */
/*
\* Linux Kernel Parameters (passing device tree):
\* r3: pointer to the fdt, followed by the board info data
\* r4: physical pointer to the kernel itself
\* r5: NULL
\* r6: NULL
\* r7: NULL
*/
(*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
/* does not return */
}
\#endif
ログイン後にコピー

arch/powerpc 内核的入口有且只有一个,入口点为内核镜像的起始。此入口支持两种调
用方式,一种是支持Open Firmware 启动,另一种对于没有OF 的引导代码,需要使用扁平
设备树块,如上示例代码。寄存器r3 保存指向设备树的物理地址指针,寄存器r4 保存为内
核在物理内存中的地址,r5 为NULL。其中的隐含意思为:假设开启了mmu,那么这个mmu
的映射关系是1:1 的映射,即虚拟地址和物理地址是相同的。

7 Linux 内核对设备树的解析
扁平设备树描述了目标板平台中的设备树信息。每个设备都有一个节点来描述其信息,
每个节点又可以有子节点及其相应的属性。内核源码中include/linux/of.h 及drivers/of/base.c
等文件中提供了一些Open Firmware API,通过这些API,内核及设备驱动可以查找到相应
的设备节点,读取其属性值,利用这些信息正确地初始化和驱动硬件。

图2 内核及驱动对扁平设备树的解析
Fig2 Interaction from kernel and drivers with the FDT blob

8 结论
通过本文,你应该对Linux设备树dts移植有了一个基本的了解,它是一种描述和传递硬件配置信息的有效方式,可以适应嵌入式Linux系统的多样化需求。当然,设备树也不是一成不变的,它需要根据具体的硬件平台和内核版本进行定制和修改。总之,设备树是Linux系统中不可或缺的一个组件,值得你深入学习和掌握。

以上がLinux デバイス ツリー dts 移植: ハードウェア構成情報を記述して転送する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:lxlinux.net
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート