概要
はじめに
Microchip社のPolarFire® SoCは、不揮発性で低消費電力のミッドレンジSoC FPGAで、64ビットのRISC-V ISAを5コア搭載したプロセッサーと低消費電力FPGAを組み合わせたチップです。
この記事は、私自身の備忘録も兼ねて、PolarFire® SoCのMSS(Microprocessor Subsystem)における各種ペリフェラルの活用を目指して執筆しています。試行錯誤しながら実験を進めているため、内容に不備や不足がある可能性もございます。その際は、何卒ご容赦いただけますと幸いです。
記事の目的
これまでのPolarFire SoCに関する記事では、MSS単体またはFPGA単体での動作に焦点を当てており、それぞれの間の通信については触れてきませんでした。
今回は、MSSとFPGA間の通信に注目し、その設定方法と動作について解説します。
開発の手順
本シリーズでは、MSSとFPGA間の通信確認を目的として、開発を3回に分けて進めていきます。
今回:GPIOによる通信の確立
FPGAファブリックに接続されたスイッチやLEDを、MSSから制御して動作を確認します。
次回:APB(Advanced Peripheral Bus)を利用したLED制御
MSSからAPB経由で、LED2の点灯を制御します。
次々回:PCからの指令によるLED制御
シリアル通信などを通じて、PCからのコマンドでLEDを制御します。

改定履歴
| 公開/変更日 | 変更内容 |
| 25/6/10 | 初版 MSSとFPGAファブリックのGPIO通信 |
| 25/6/11 | タイトル修正 |
外部リンク
| タイトル | リンク |
| PolarFire SoCプロダクトページ (Microchip) | PolarFire® SoC FPGAs | Microchip Technology |
| PolarFire SoC Discoveryキット (Microchip) | PolarFire® SoC Discovery Kit | Microchip Technology |
| PolarFire SoC MSS テクニカルリファレンスマニュアル | PolarFire SoC MSS Technical Reference Manual (microchip.com) |
| Microprocessor Subsystem (MSS) User’s Guide | PolarFire SoC MSS Technical Reference Manual (microchip.com) |
| PolarFire SoCプロダクトページ (GitHub) | PolarFire-SoC · GitHub |
| ベアメタルプロジェクト (Github) | GitHub – polarfire-soc/polarfire-soc-bare-metal-examples: Bare metal example software projects for PolarFire SoC |
| GPIO Bare Metal Driver (Github) | polarfire-soc-documentation/bare-metal-embedded-software/bare-metal-driver-user-guides/polarfire-soc-mss-driver-user-guides/mss-gpio/mss-gpio-driver-user-guide.md at master · polarfire-soc/polarfire-soc-documentation · GitHub |
| 記事 | リンク | |
| 第1回 | Lチカ_FPGA編 | PolarFire® SoCシリーズ① Lチカ_FPGA編 – ぴくおの電子工作的な何かWP |
| 第2回 | Lチカ1_MSS編 | PolarFire® SoCシリーズ② Lチカ1_MSS編 – ぴくおの電子工作的な何かWP |
| 第3回 | コア間メモリ共有の方法 | PolarFire® SoCシリーズ③ コア間メモリ共有の方法 – ぴくおの電子工作的な何かWP |
| 第4回 (本記事) | 内部GPIOインターフェースの使い方 | PolarFire® SoCシリーズ④ 内部インターフェースの使い方 – ぴくおの電子工作的な何かWP |
| 第5回 | 内部APBインターフェースの使い方 |
第1回:GPIOによる通信の確立
1回目の記事はFPGAファブリックに接続されたスイッチやLEDを、MSSから制御して動作を確認します。

構成
前回の記事と同じく、PolarFire® SoC Discovery Kitを使用し、動作を確認していきます。
PolarFire® SoC Discovery Kit | Microchip Technology

[Step 1]MSS Configuratorで設定ファイルを作成
まずはMSS Configuratorツールを用います。これはMSS(Microprocessor Subsystem) を構成するための GUIベースの設定ツール で、ハード構成の設定やペリフェラルの有効化など設定します。
1.PolarFire® SoC MSS Configurator v2024.2を起動
アプリを起動すると以下の画面が立ち上がります。

2.プロジェクトの新規作成
①Project > Newをクリック

②Discovery Kitの場合は以下のように入力し「OK」をクリック(Module Nameは任意)

3.各種設定
①ペリフェラルの設定を行います。
今回はシンプルさを重視し、最小構成で進めます。
「GPIO(Fabric)」を選択し、GPIO2_0~GPIO2_3 を以下の設定で構成します。

②MMUART_1 のみ有効とします。IO Connectionを「MSS I/O Bank2」に割り当てます。

③「MSS to/from Fabric …」タブを開きFIC_3(APB)のみ有効にします。

3.保存と設定ファイルの生成
「Save」ボタンをクリックして設定内容を保存した後、「Generate」ボタンを押すことで、以下の2種類のファイルが自動生成されます:
.cxzファイル:Libero SoC で読み込むための設計情報ファイル- XMLファイル:SoftConsole で使用する、MSS設定情報を含むファイル
このステップを行うことで、MSSの設定が各ツールへ正しく連携され、FPGA設計とソフトウェア開発がシームレスに接続されます。

[Step 2-1] Libero SoC でFPGAデザインを生成
MSS(Microprocessor Subsystem)と連携するカスタムロジックをFPGAファブリック上に実装します。
Libero SoC 上でブロックを接続し、MSSと通信するための ロジックや入出力ポートの割り当てなどを行っていきます。
この構成により、FPGAとRISC-Vコア間のGPIOによるデータのやり取りが可能になります。
1.Libero SoCを起動しプロジェクトを作成
①Libero SoCを起動し、「Project」>「New Project」をクリック

②プロジェクト名と保存先を指定し「Next」をクリック

③デバイス情報を入力し「Next」をクリック

④コア電圧等を入力し「Finish」をクリック

2.MSS設定ファイルを読み込み
①「Create Design」直下の「Import MSS」を右クリックし、ポップアップ表示されたメニューから「Import MSS Component」をクリック

②コモンダイアログが開くので、MSS Configuratorで生成した「***.cxz」ファイルを開く

3.スマートデザインの生成
「Create Design」直下の「Create SmartDesign」をダブルクリックし、ポップアップ表示されたメニューの名前に任意のデザイン名(ここではPWM)を入力し「OK」をクリック

4.各モジュールの配置
MSSブロックの配置
①タブを「Design Hierarchy」に変更し、先ほど生成したSmartDesignのタブを選択、その後「work」直下の「MPFS_DISCOVERY_KIT_MSS」をドラッグアンドドロップで配置します。

②MSSブロックが配置されます

2.ANDブロックの配置と配線
①タブを「Catalog」に変更し、「Macro Library」直下の「AND2」をドラッグアンドドロップで配置します。

②追加したANDゲートの出力を「GPIO2_F2M_3」ピンに、「GPIO2_M2F_1」ピンの出力をANDゲートのB入力に接続します。

3.クロックバッファの配置と配線
①「Macro Library」直下の「CLKBUF」をドラッグアンドドロップで配置します。

②「CLKBUF」の出力を「FIC_3_PCLK」ピンに接続します。

3.未接続ピンの処理
①IPコアやモジュールの中にある 内部の信号やポート(例:LED制御ピン、スイッチ入力) を、
トップレベルのデザイン(例:FPGAファブリック全体)から見えるようにします。
ANDゲートのA入力を右クリックして「Promote to Top Level」をクリック

②同じように「GPIO2_M2F_1」ピンと「GPIO2_F2M_2」も可視化させます。

③未使用の「MSS_INT_F2M[63:0]」ピンをLowに接続

④続いて「MSS_RESET_N_F2M」ピンをHighに接続します。

5.HDLコードの自動生成
①「Build Hierarchy」ボタンをクリックして階層構造を構築した後、
続けて「Generate」ボタンをクリックして、各モジュールの接続や設定に基づいたHDLコードの自動生成を行います。

6. 論理合成
①Smart Designファイルを右クリックし「Set as a Root」を選択します。

②タブを「Design Flow」に切り替え、「Implement Design」セクションの中にある「Synthesize」を右クリックします。
表示されたメニューから「Run」を選択して、論理合成を実行します。

③処理が正常に完了すると、ステップの左側にチェックマーク(✔)が表示されます。
これにより、合成が問題なく終了したことを確認できます。

7. ピンのアサイン
①「Constraints」セクションの中にある「Manage Constraints」を右クリックします。
表示されたメニューから「Open Constraint Manager view」を選択して、ピンアサインビューを表示します。

②「Edit」ボタンの横の▼マークをクリックします。表示されたメニューから「Edit with I/O Editor」をクリックします。

③以下のように各ポートをピンにアサインします。
| Port Name | I/O Standard | Pin Number |
| GPIO_2_F2M_2 | LVCMOS18 | T19 |
| GPIO_2_M2F_0 | LVCMOS18 | T18 |
| PAD | LVCMOS18 | R18 |
| A_0 | LVCMOS18 | U17 |


④設定後、保存してウィンドウを閉じます。
8.配置配線の実行
①メニュー下部の「Place abd Route」ボタンをクリックし、配置配線を実行します。

②処理が正常に完了すると、「Place and Route」の左側にチェックマーク(✔)が表示されます。
これにより、配置配線が問題なく終了したことを確認できます。

9. プログラムのフラッシュ
①「Program Design」セクションの中にある「Run PROGRAM Action」を右クリックします。
表示されたメニューから「Run」をクリックして、書込みを実行します。

②処理が正常に完了すると、「Program Design」セクションに配置されている、各ステップの左側にチェックマーク(✔)が表示されます。
これにより、書込みが問題なく終了したことを確認できます。

[Step 2-2] SoftConsoleで制御部を作成
1.Gitからダウンロード
下記のGitHubからベアメタルサンプルプロジェクトをダウンロード&解凍を行います。
2.プロジェクトを開く
①SoftConsoleアプリケーションを起動すると、最初にワークスペースの保存場所を聞かれるので、ディレクトリを指定します。

②File > Open Project from File System をクリックします。

③「Directort..」ボタンを押し、Githubからダウンロードした「mpfs-gpio-interrupt」フォルダを指定します。中間のチェックボックスにチェックを入れ、最後に「Finish」ボタンを押します。

3.プロジェクトの設定
①プロジェクトを右クリックし、「Properties」を選択

②「C/C++ Builld 」 から「Build Variables」を選択します。
Configrationが「LIM-Debug-DiscoveryKit[Active]」になっていない場合、「Manage Configuration」ボタンを押します。

③LIM-Debug-DiscoveryKitを選択し「Set Active」ボタンを押します。

④「Apply」ボタンを押します。

⑤「C/C++ Builld 」 から「Setting」を選択し、Configrationが「LIM-Debug-DiscoveryKit[Active]」になっていることを確認します。

⑥「C/C++ Builld 」 から「Tool Chain Editor」を選択し、Configrationが「LIM-Debug-DiscoveryKit[Active]」になっていることを確認します。

⑦「Apply and Close」をクリックし、ウィンドウを閉じます。
4. LED点灯制御部の追加
デフォルトのコードの118行目以降に、以下のソースコードを追記します。

//ここから挿入
uint64_t led_cnt;
MSS_GPIO_config(GPIO2_LO, MSS_GPIO_0, MSS_GPIO_OUTPUT_MODE);
MSS_GPIO_config(GPIO2_LO, MSS_GPIO_1, MSS_GPIO_OUTPUT_MODE);
MSS_GPIO_config(GPIO2_LO, MSS_GPIO_2, MSS_GPIO_INPUT_MODE);
MSS_GPIO_config(GPIO2_LO, MSS_GPIO_3, MSS_GPIO_INPUT_MODE);
while(1u)
{
if ((MSS_GPIO_get_inputs(GPIO2_LO) >> 2) == 0)
{
MSS_GPIO_set_output(GPIO2_LO, MSS_GPIO_1, 1u);
}
else
{
MSS_GPIO_set_output(GPIO2_LO, MSS_GPIO_1, 0u);
}
if ((MSS_GPIO_get_inputs(GPIO2_LO) >> 3) == 1)
{
led_cnt ++;
if (led_cnt < 500000)
{
MSS_GPIO_set_output(GPIO2_LO, MSS_GPIO_0, 1u);
// led_cnt = 1;
}
else if (led_cnt < 1000000)
{
MSS_GPIO_set_output(GPIO2_LO, MSS_GPIO_0, 0u);
// led_cnt = 0;
}
else
{
led_cnt = 0;
}
}
// shared_var1 = led_cnt;
// write_to_shared_memory = led_cnt ;
}
//ここまで
5.書込み
「Launch Configration」タブの「GDB OpenOCD Debugging」直下の「mpfs-gpio-interrupt hw all-hart debug」をダブルクリックするとデバッグプログラムが書き込まれます

[Step 2-3]動作確認
SW1を押し、DIPスイッチの1番がOFFになっているときに、LED1が点滅するのが確認できるはずです。
編集後記
正直なところ、まだわからないことが多く、手探りで実験を進めている状態です。ドキュメントは多く揃っているものの、その分資料やページの量が膨大で初めて扱う内容も多いため、情報の整理に苦労しています。


コメント