AN-2608:パワー・システム・マネージメント用Linux
要約
オープン・ソースのautoconfig Linux C/C++アプリケーションが、デジタル・パワー・システム・マネージメント(PSM)デバイス向けにGitHub で公開されています。これは、I2C 通信用の /dev/i2cを利用してユーザ空間で動作します。このアプリケーション・ノートでは、コードのフレームワーク、デバッグ、ウェブベースのツール・サポートを紹介し、更に2 つのマスター・ソリューションについて説明します。
本アプリケーション・ノート読了後の目標は、アプリケーションを正常にダウンロード、コンパイル、実行し、個別のソフトウェア設計、デバイス・プログラミング、あるいはパワー・システムのデバッグに活用できるようにすることです。
Linux のユーザ・モードの実行ファイル用にC アプリケーションを書いた経験があると役に立ちます。
はじめに
ほとんどのパワー・システム・マネージメント(PSM)設計は、セット&フォーゲット・モデルに従っています。LTpowerPlay™ と組み合わせることで、PSM デバイスのセットアップやデバッグを簡単に行えます。また、更に便利なことに、大規模なプログラミング・ソリューションと組み合わせる場合には、ソフトウェア/ファームウェアは不要です。しかし、多くの大規模システムでは、ボード・マネージメント・コントローラ(BMC)が必要です。ここで、「ソフトウェアやファームウェアは、PSM に対し何ができるのか?」という疑問が生じます。
PSM ソフトウェア/ファームウェアの基盤となるのはPMBus です。これは、SMBus を基盤としており、更にSMBus の土台はI2C です。PSM ソフトウェア/ファームウェアで価値を高めるBMC を構築するには、各プロトコルに対するある程度の知識、またはプログラマを細部の作業から解放する既存のクラス/コードが必要です。
このLinux アプリケーション例は、各プロトコル・レイヤを処理し、ユーザ空間でPSM ソフトウェア/ファームウェアを作成しやすくするアプリケーション・プログラミング・インターフェース(API)を提供します。Linux PSM はBMC の代替ではなく、一組のクラスであり、代表的なBMC ソフトウェア/ファームウェアに対応するアプリケーション例です。
また、Linux は学習ツールとして、アナログ・デバイセズの評価用ボードでも使用できます。エンジニアがLinux コードのスニペットを既存のアプリケーションにコピー・アンド・ペーストして利用するのは、ごく一般的な方法です。ただし、以下に示すクラス階層全体を再利用することもできます。
- デバイスおよびレールの検出
- コマンドAPI
- フォルト・ログのデコード
- システム内プログラミング
このアプリケーション・ノートでは、Linux コード・ベース、PSM プログラミング、セットアップ、Linux PSM と評価用ボードの併用、PSM デバッグ手法について説明します。プロトコルの詳細や一般的なプログラミングに関する詳細については、アプリケーション・ノート135:Implementing Robust PMBus Software for the LTC3880 およびI2C/SMBus/PMBus に関する業界標準1 を参照してください。
LINUX PSM
評価および開発用ハードウェア
Linux PSM ハードウェアには、Devantech® USB/I2C アダプタ(小型の3 線接続デバイス)があり、評価用ボード(ミドル・ボード)や最終製品ボードのPMBus、SMBus、またはI2C バスに接続します。
最適な学習のためには、DC1613A、DC1962C2、Devantech アダプタ3、Total Phase® BeagleTM4(I2C スニファ)を用いて始めることを推奨します。これらのデバイスを使用することで、コントローラ(LTC388X/μModule)およびマネージャ(LTC297X)のプログラミング、デバッグ、学習を行えます。
図1 にグラバ・クリップで接続された推奨ハードウェアを示します。このハードウェアをLinux PSM ソフトウェアで使用するには、タイプA/タイプB 変換USB ケーブル2 本(タイプA を小型ボードに、タイプB をコンピュータに接続)を用いて、Devantech アダプタおよびBeagle をLinux コンピュータに接続します。Beagle のUSB を接続しない場合は、Beagle のリボン・ケーブルをグラバ・クリップから取り外し、PMBus トラフィックとDC1962C との干渉を防止してください5。
Linux との互換性
Linux PSM コードはautoconfigプロジェクトをベースにしており、VMWare 仮想マシン(VM)およびI/O ピンにI2C を用いたRaspberry Pi上で動作するUbuntu 24 を用いてテストされています。このアプリケーション・ノートでは、VMWare で動作するUbuntu 24 プラットフォームを前提としており、コードはUbuntu 24 上で単純なmakeコマンドによってコンパイルできます。
Devantech アダプタをUSB ケーブルでPC に接続すると、VM Linux インスタンス(場合によっては、メニューからUSB デバイスをVM に接続する必要があります)が /dev/i2c-0 ファイルを作成します。Linux コードは、このファイルを通じてI2C を操作します。RaspberryPi プラットフォームでは、I2C はマイクロプロセッサ・チップに組み込まれており、 /dev/i2c-Nが作成されます。これは、BMC の組み込みLinux が /dev/i2c-Nを作成するのと同様で、N はLinux によって割り当てられる番号です。N が判明したら、コードを修正して一致させるか、コマンド・ラインでN を渡すことができます。
注:Devantech Linux ドライバは、Ubuntu 24 には含まれていないため、手動でコンパイルしてインストールする必要があります。
また、/dev/i2c-Nが作成されても、ユーザ・ログインでは書き込みできません。Linux アプリケーションをスーパーユーザとして実行するのではなく、以下のようにアクセス権を変更します。
sudo chmod 666 /dev/i2c-N
ここで、N は実際の番号です。USB を接続すると自動でファイルのアクセス権が変更されるような措置を講じていない限り、USB を接続するたびにこのコマンドを繰り返す必要があります。
Devantech ドライバのインストール
ドライバはソース・コードの形で提供されており、以下から取得できます。
groeck/devantech: Devantech USB-ISS Linux kernel driver (github.com)
通常、ユーザは各自のLinux ボックスにgit をインストールし、上記リンクからコードをクローンします。ドライバ・コードに同梱されているREADME ファイルには、以下の手順に従うインストール情報が記載されています。
$ sudo make install- 以下を追加してUSB-ISS ドライバをブロックリスト登録します:
i2c-devantech-iss to /etc/modules - Linux をリブートします。
- README ファイルに記載されたすべての手順を実行します。注:Ubuntu 24 を使用していない場合、適切なLinux ヘッダをインストールする必要がある場合があります。
- Devantech アダプタをUSB で接続し、
ls -l /dev/i2c*が生成されていることを確認します。 - コードがファイルに書込みを行えるように、アクセス権を調整します。
- 多数のI2C デバイスがある場合、
sudo i2cget 0 0x30 0を実行して、それらのデバイスをテストし、正しいN を特定します。
この操作は、コマンド0x00(PAGE)を使って、アドレス0x30 のデバイス(N == 0)からバイト読出しを実行します。DC1962C には、そのアドレスにPMBus デバイスがあります。このコマンドを各N に対して実行し、いずれか1 つが応答するまで繰り返します。その後、アドレス0x32 または0x33 でも試行し、これらも応答することを確認します。
ひとたびN が判明すると、その値は常に同じです。VM では、N は通常0 です。NUNC ボックスやその他の組み込みシステムでは、任意の数となる場合があります。
Linux PSM アプリケーション
Linux コードは以下のサイトからgit を用いてクローンできます。
コンパイル方法は以下のとおりです。
- ディレクトリを最上位ディレクトリに変更し(cd)、以下のコマンドを実行します。
./configure make
- 次に、実行するために以下のコマンドを入力します。
cd src ./LT_PMBusApp -i
この操作により、アプリケーションはテキスト・ベースのインターフェースによるインタラクティブ・モードで実行されます。-i を外すと、コマンド・ライン・オプションの一覧が表示されます。
注:前記の操作は、/dev/i2c-N の書込み権限によって決まります。
コマンド・ライン・オプションは以下のとおりです。
./LT_PMBusApp [-d dev] ( // Device Path [-p file] | // Program with File [-v address] | // Dump Faults [-x address] | // Disable Fault Log [-e address] | // Enable Fault Log [-s address] | // Store Fault Log [-c address] | // Clear Fault Log [-i]) // Menu
デバイス・パスは他の任意のオプションと組み合わせることができますが、他のオプションを使用できるのは一度に1 つです。デバイス・パス・オプションは、N がデフォルトの0 でない場合に指定するためのものです。
メニュー動作
メニュー・システムを動作させるには、メニュー選択のリストの左側に表示されている番号を入力し、Enter を押します。メニュー項目1から始めます。ここには、1 - Read All Voltages や4 - Sequence On/Off などの選択肢があります。1 – Read All Voltagesから始めます。
アプリケーションはすべてのPSM デバイスを検出し、各デバイスのページ数などを含む内部構造を保持します。電圧を選択すると、ツリー全体について、アドレス単位、ページ単位で値が記録されます。
システム内プログラミング
システム内プログラミングは、PSM デバイスの設定をEEPROM に直接書き込むことによって、デバイスの動作に影響することなくPSMデバイスをコード化する方法です。AN-166:In Flight Update with Linduino では、isphex ファイル(システム内プログラミングのhex ファイル)をLTpowerPlay からエクスポートするプロセスと方法を説明しています。
以下のコマンドでisphex ファイルを用いてデバイスをプログラムします。
./LT_PMBusApp -d N -p file
この方法は、Linux をテスト用に用いる製造環境で、すべてのデバイスを一度にプログラミングする場合に非常に有用です。
コードの変更
コードには 2 つのエントリ・ポイントがあります。呼び出しが一度の main()関数と、ループ内で繰り返し呼び出される loop()関数です。
メニューは、ヘルパ関数としてコード化され、loop()がメイン・メニュー関数を呼び出します。各メニューは、caseステートメントで処理され、各 case が 1 つのメニュー番号に対応します。
アプリケーションを変更することは、提供された API を用いてコード内の case ステートメントを変更することにすぎません。PMBus コマンドを発行するコード内の関数(API)は、独立したクラス階層から生じ、コードが行うべき処理を表す単純な名前が付けられています6。
例えば、
voltage = pmbus->readVout(0x30, false);
PMBus API オブジェクトを使用し、アドレス 0x30 の出力電圧をポーリングせずに読み出し、それを voltage という名の変数に格納することを意味します。
練習のため、簡単な変更をいくつか行ってみてください。例えば、出力電力を読み出して出力するメニュー項目を追加します。この関数をメニューから呼び出してみてください。
float readPout(uint8_t address, bool polling);
これを、DC1962C のアドレス 0x30 にある LTC3880 でテストします。動作を確認するには、DC1962C のチャンネル 0 に抵抗性負荷または電流負荷を加え、その結果がコードの出力する値と一致することを検証します。
PSM PMBus のクラス
PMBus のクラスは、src ディレクトリ内にあります。クラス階層は、レイヤ構造になっており、I2C、SMBus、最後に PMBus の順で構成されています。L11/L16(PMBusフォーマット)とフローティング・ポイントの間で値を変換するための数値変換APIがあります。最後に、グループ・コマンド・プロトコル・アシスタンス、デバイスおよびレール検出、フォルト・ログ・デコード、およびシステム内プログラミングまでサポートしています。
各レイヤは単純な C++クラスです。最終的な環境が C であっても、心配は無用です。シンプルとは、大量のメモリ・オーバーヘッドなしに C++クラスを利用できること、またはクラス・ラッピングを取り除いて純粋な C として容易に利用できることを意味します。C++ラッパーは、アプリケーション・コードを簡素化し、プログラミングが専門でない人にとっても扱いやすくします。
内部構造を知りたいプログラマ向けに説明すると、SMBus クラスは階層構造になっており、アプリケーション・コードはPEC のオン/オフから独立しています。また、ポーティングを容易にするため、I2C クラスは、/dev/i2c-N ファイルへのIO をまとめるラッパーになっています。コードを非Linux プラットフォームにポーティングする場合、I2C クラスを書き換えてレジスタや既存ライブラリを利用するようにします。
PMBus クラスの使用
API は、クラスを理解していなくても使用できます。必要なのは、いくつかのインポートと統計変数だけで、コードはすぐに動作可能な状態になります。
最も重要なものを以下に示します。
#include <lt_smbuspec.h> #include <lt_smbusnopec.h> #include <lt_pmbus.h> #include <lt_pmbusmath.h>および
static LT_PMBus *pmbus = new LT_PMBus(smbus);
デバッグ
Linux PSMアプリケーション、更には一般的なファームウェア・アプリケーションをデバッグするには、以下のような方法があります。
- 出力(Print)
- スパイ・ツール
- デバッガ
このアプリケーション・ノートでは、デバッグ・オプションは対象外となります。
Print ステートメントは、コードがコマンド・ライン・アプリケーションにコンパイルされるため、優れたデバッグ・ツールです。PSM ライブラリは、NACK やPEC などの一般的なエラーを検出する際にこの手法を利用しており、これらはコマンド・ラインに出力されます。既存のエラー・メッセージ出力コードをコピー・アンド・ペーストして、コードの主要な場所からメッセージを出力するよう変更することも可能です。
PMBus の究極のデバッガはスパイ・ツール(Beagle)です。スパイ・ツールが優れているのは、バスのトラフィックを監視できるだけでなく、トレースをコードと一緒にアナログ・デバイセズのフィールド・アプリケーション・エンジニアへ電子メールで送信できるため、支援が受けやすくなる点にあります。
このアプリケーション・ノートでは、Total Phase のBeagle と通信を行うTotal Phase のData Center アプリケーションから生成されたデータに焦点を置きます。Data Center アプリケーションのインストール情報については、Total Phase のサイト(www.totalphase.com)を参照してください。
最も簡単な開始方法は、アプリケーションを用いてバスをトレースすることです。例として、メニュー選択肢3(電圧の読出し)を使用します。
図3 にデータを示します。インデックスを使って進行を確認しながら、いくつかのトランザクションを読み解いてみましょう。
インデックス#1(I1)とインデックス#6(I6)には、2 つのバイト書込みトランザクションがあります。SMBus では、これはバイト書込みプロトコルとして定義されています。アドレスは0x30 で、これはコードに示されているようにLTC3880 です。最初のバイトは0x00 で、これはPAGE コマンドを表します。
LTC3880 のデータシートの表2 に、PAGE コマンドが示されています。この表は、Beagle データを迅速にデコードするための方法を示しています。Type 列に「R/W Byte」とある点に注目してください。つまり、このレジスタはバイトの読出し/書込みプロトコルに従っており、両方向がサポートされます。
I1 とI6 を確認すると、2 番目のバイトは0x00 と0x01 です。コードは、PAGE レジスタを0 および1 に設定しています。
次のように読み取ることができます。
Write 0x8B, Read 0x9A 0x0D Write 0x20, Read 0x14
0x8B はREAD_VOUT コマンドです。データシートの表2 によれば、これは「R Word」プロトコルであり、L16 フォーマットとなっています。
0x20 はVOUT_MODE コマンドです。データシートの表2 によれば、これは「R Byte」コマンドです。
READ_VOUT とVOUT_MODE を読み出すためのコードは次のとおりです。
vout_L16 = smbus_.readWord(address, READ_VOUT);
exp = (int8_t)
(smbus_.readByte(address, VOUT_MODE) & 0x1F);
return math_.lin16_to_float(vout_L16, exp);
このコードでは、まず
smbus_.readWord(address, READ_VOUT)
が実行され、その後に
smbus_.readByte(address, VOUT_MODE),
が続きます。モードから5 ビットが抽出され、exp 変数に格納されます。続いて、数学的変換により、L16 が指数exp を用いて浮動小数点に変換されます。
基本的に、このジェネリック・コードは電圧と指数の両方を読み出し、L16 を浮動小数点に変換します。LTC388XデバイスとLTC297Xデバイスは、異なる指数を使用します。そのため、2 回のトランザクションが必要となります。
注:指数が既に分かっている場合、その情報を使って書き込むことができ、このほうがやや高速に動作します。しかし、ジェネリック・コードのほうがバグが少なく、アプリケーション開発者にとって扱いやすくなります。カスタム・コードを書く際には、これがトレードオフとなります。
結論を述べる前に、興味深いトランザクションの1 つとして、リセットを見てみましょう。
図5 をご覧ください。3 つの書込みトランザクションがある点に注目してください。S/P の欄にはS が2 つ、SP が1 つあります。これは、I1 がスタート、I2 が反復スタート、I3 が反復スタートに続くストップであることを意味します。更に、アドレスがそれぞれ、0x30、0x32、0x33 と、異なっています。
これはグループ・コマンド・プロトコルです。すべてのコマンドは、I3 の最後、つまりストップの時点で処理されます。
Beagle のトレースのデコードにある程度時間をかければ、PSMデバイスのPMBus コマンドをより深く理解できます。一方、目標がコードを動作させることであれば、PSM ライブラリがこの重い処理を担ってくれます。
2 コントローラ・システム向けソリューション
前述のように、ほとんどのシステムはセット&フォーゲットですが、一部にはBMC が搭載されています。実際には、BMC を持つシステムは、セット&フォーゲットとファームウェアを組み合わせたものです。では、なぜ、BMC にすべてのセットアップを任せる必要があるのでしょうか。基本的なセットアップをPSM デバイスにプログラムし、BMC ファームウェアは付加価値機能にのみ使用するほうがはるかに簡単です。また、このほうがシステムの信頼性も高くなります。これは、多くのファームウェアがテレメトリやマージンを読み出し、わずかに電圧を変えるためです。ファームウェアに、シーケンス動作やPWM 周波数などの常に固定された重要機能を制御させる必要はありません。
LTpowerPlay は、PSM システムの設計、デバッグ、構築を行う際の汎用ツールです。そのため、ファームウェアをデバッグする場合は、物理クロックやデータ・ライン上にある別のPMBus コントローラに対処しなくてはなりません。
2 コントローラの実用的な影響に入る前に、まずはPMBus に2 つのコントローラがある場合に何が起こるかを確認しておくのが最善です。PMBus はSMBus をベースとしており、SMBus には複数のコントローラが含まれています。
クロックおよびデータ・ラインはオープン・ドレインです。つまり、任意のデバイス、コントローラ、またはターゲットは、ラインをプルダウンできますが、プルアップすることはできません。コントローラがデータ・ラインをプルダウンしていない状態で、データ・ラインがローであることを検知した場合、コントローラは、別のコントローラがデータ・ラインをローにプルダウンしていると判断します。その結果、自身のトランザクションを中止し、別のコントローラがそのトランザクションを続行できるようにします。
この手法は、ビット・ドミナンス・アービトレーションとも呼ばれ、データにゼロをアサートするコントローラが常に優勢となるという仕組みを表しています。
Linux PSM およびLTpowerPlay(DC1613)は、どちらもアービトレーションをサポートしているため、これですべてうまくいくと考えがちです。しかし、考慮すべき重要な点がもう1 つあります。
PMBus はPAGE コマンド(0x00)を定義しており、これはデータを指し示すアドレスのようなものです。ページはチャンネルのようなものです。例えば、LTC2977 は8 個の電源を管理できます。つまり8 つのチャンネルを持ち、それぞれがPAGE レジスタ/コマンドによってアドレス指定されます。
実際には、電圧のような値を読み出すには2 つのトランザクションが必要です。1 つはPAGE、もう1 つはREAD_VOUT です。2 つのコントローラが同じターゲットから同時にテレメトリを読み出そうとし、一方のコントローラが他方のPAGE コマンドとテレメトリ・コマンドの間にPAGE コマンドを挿入した場合、誤ったページが読み出されます。
LTpowerPlay が起動して動作している場合、その主な機能は、テレメトリを読み出し、その最新のステータスを出力やフォルトなどの重要な情報のプロットと共に表示し続けることです。では、通常ファームウェアは何をしているのでしょうか。テレメトリを読み出しているのです。
更に問題となるのは、ファームウェアがブート時に電圧識別(VID)機能を実行する場合です。LTpowerPlay がPAGE レジスタを変更していたために、ファームウェアが誤ったページに電圧値を書き込んだとしたらどうなるでしょうか。システムが故障で停止するか、更に悪い場合には損傷を与えるかもしれません。幸いにして、通常はVOUT_MAX レジスタがシステムの損傷を防ぎます。
PAGE コマンドの基本的な問題は、PMBus の仕様に起因しています。アナログ・デバイセズのパワー・システム・マネージメント・デバイスに固有のものではない点に注意が必要です。
LTpowerPlay とファームウェアを共存させ、PAGE の問題を回避できる方法が2 つあります。1 つ目は、単に2 つのコントローラが同時に通信しないようにすることです。2 つ目は、一方のコントローラで、PAGE_PLUS プロトコルやグローバル・アドレス、PAGE コマンドなどの別の方法を用いることです。
PAGE_PLUS は使用頻度がそれほど高くないため、まずはこちらを確認してみましょう。PAGE_PLUS を用いると、PAGE とCOMMAND を1 つのトランザクションに含めたアトミック・トランザクションが可能になります。ただし、すべてのデバイスが対応しているわけではないため、通常は特別な場合にのみ使用されます。そのため、このアプリケーション・ノートでは、PAGE_PLUS やその他の特殊な方法には焦点を当てません。明確なソリューションが見つからない場合は、アナログ・デバイセズのPSM であるLTC3887 およびLTC2977 のデータシートを参照するか、最寄りのフィールド・アプリケーション・エンジニアにご相談ください。
しかし、より一般的な方法は、LTpowerPlay とファームウェアが同時にターゲットと通信しないようにすることです。LTpowerPlay には、この動作を制御する非常に簡単な方法があります。図6 はテレメトリ・プロットを示しています。このツールバーには赤色の四角いボタンがあります。
このボタンを押すと、バス上のすべてのテレメトリとLTpowerPlay の動作が停止します。その後、このボタンは図7 に示すように緑色の矢印に変わります。
しかし、ファームウェアは必ずしもバスを停止するメカニズムを内蔵しているわけではありません。アナログ・デバイセズは、停止メカニズムを内蔵した新たなファームウェアを設計すること、あるいは、ハードウェアにバス・スイッチ/マルチプレクサまたはジャンパを設けることを推奨しています。
バス・コントローラのLTpowerPlay およびファームウェアが停止すれば、デバッグは必要に応じてツール間で切り替えるだけの作業となります。
要約すると、選択肢は2 つあります。
- 一度に1 つのマスタのみがバスで通信できるようにする。
- アナログ・デバイセズのフィールド・アプリケーション・エンジニアの支援を受けて、PAGE_PLUS などの先進的な手法の詳細を適用する。
新規設計の場合には、1 番目の選択肢がより適切です。
まとめ
Linux PSMコードとDevantech アダプタは、PSMデバイスのプログラミングを容易にします。コードには、SMBus およびPMBus の両方に対応するシンプルなAPI が用意されています。LTpowerPlay は引き続きデバッグに利用できます。更に、Total Phase のBeagle やその他のスパイ・ツールを接続してバスのトラフィックを監視することもできます。
Linux PSM は、コードをポーティングする場合にも、PMBus の動作を学ぶ場合にも、優れた開始点となります。PSM のプログラミングの基本を理解すれば、スキルを伸ばし、より自信を持ってその他のツールを使えるようになります。
注記
1規格に関する資料については、www.pmbus.org を参照してください。
2 DC1962C 評価用ボード | アナログ・デバイセズ
3 Beagle I2C/SPI Protocol Analyzer - Total Phase
4 Beagle I2C/SPI Protocol Analyzer - Total Phase
5 Beagle は必須ではありません。これは、DC1962C へのPMBus トラフィックを観察することで学習を助けるにすぎません。DC1962C のデフォルト構成をデバッグおよび復元するには、DC1613A の使用を強く推奨します。
6 DC1962C(パワー・システム・マネージメント・デモ・ボード(Power Stick))では、LTC3880 がアドレス0x30、LTC2975 がアドレス0x32、LTC2977 がアドレス0x33 に割り当てられています。






