LoginSignup
8
0

More than 1 year has passed since last update.

マイコンでインテル🄬 FPGA のコンフィグレーション ROM をアップデート! ~ NXP i.MX RT1050 編 ~

Last updated at Posted at 2022-12-17

目次

はじめに
1. サンプル・ソフトウェア/ハードウェアのブロック図
2. MCU 開発環境 MCUXpresso Software and Tools
3. 使用する開発キット
 3-1. NXP クロスオーバー MCU i.MX RT1050 Evaluation Kit
 3-2. Intel Cyclone 10 LP FPGA Evaluation Kit
4. Intel Quartus Prime 開発ソフトウエア/Platform Designer の構成
 4-1. Remote System Upgrade の概要紹介
 4-2. Intel FPGA I2C Agent to Avalon-MM Host Bridge Core の設定
 4-3. Generic Serial Flash Interface Intel FPGA IP の設定
 4-4. Remote Update Intel FPGA IP の設定
 4-5. I2C Interface の TOP 階層での接続
 4-6. Remote Update System 設定の有効化
 4-7. Full Compile の実施
 4-8. Factory と Application 1 用の JIC ファイルの生成
 4-9. Application 2 Configuration Data(RPD ファイル)の生成
5. NXP MCUXpresso IDE の構成
 5-1. 作成する NXP マイコン・プロジェクトの構成
 5-2. MCUXpresso サンプル・プロジェクトの構成
 5-3. I2C の Driver を追加
 5-4. I2C の Pin 情報を追加
 5-5. I2C Core 制御ソフトウェア - I2C Write
 5-6. I2C Core 制御ソフトウェア - I2C Read
 5-7. GSFI サンプル・ソフトウェア(Nios II サンプルから移植)
 5-8. main ソフトウェア
 5-9. Generic FAT Filesystem NXP Driver
6. 動作確認
 6-1. 使用する Tool の準備
 6-2. Cyclone 10 LP Evaluation Kit と i.MX RT1050 Evaluation Kit をジャンパーで接続
 6-3. i.MX RT1050 Evaluation Kit に SD Card を挿入
 6-4. Cyclone 10 LP Evaluation Kit に JIC ファイルを書き込み
 6-5. MCUXpresso の sdcard_fatfs サンプル・プロジェクトを新規作成しソースコードを追加
 6-6. サンプル・ソフトウェアの printf 表示するための Terminal を接続
 6-7. MCUXpresso Project の Build と Debug
 6-8. Remote System Upgrade で考慮すべき事項

はじめに

この記事では、NXP i.MXRT1050 Evaluation Kit で I2C を制御して、Intel Cyclone 10LP Evaluation Kit 上の Configuration ROM を Update する内容を説明しています。外部のマイコンCPU から FPGA を Remote Update させることに興味をお持ちの方へのご参考になれば幸いです。
また、Intel FPGA の Remote System Upgrade を題材としているため、I2C Bridge や Remote Update IP 、Generic Serial Flash Interface(GSFI)IP についても併せて説明しています。
そして、実際にアップデートさせるために必要な、NXP マイコンのソフトウェアについても説明します。

1. サンプル・ソフトウェア/ハードウェアのブロック図

サンプルの構成は【図1】のように、NXP i.MXRT1050 Evaluation Kit で I2C を制御し、Intel Cyclone 10LP Evaluation Kit 上の Configuration ROM を Update するものとなっています。
NXP i.MXRT1050 Evaluation Kitには SD Card が用意されており、その中に Update 用 Configuration Data が格納されています。
このサンプルを使用することで、「Intel FPGA を外部 CPU から制御可能」かつ、「Remote System Upgrade に応用可能」となっています。
【図2】は、Cyclone 10 LP Evaluation Kit と i.MX RT1050 Evaluation Kit を接続した状態を示しています。
図-001.png
           【図1】 サンプル・ソフトウェアとハードウェアのブロック図
     図-002.png
         【図2】 Cyclone 10 LP Evaluation Kit と i.MX RT1050 Evaluation Kit の接続
                                            🔝 目次に戻る

2. MCU 開発環境 MCUXpresso Software and Tools

マイコンの開発ツールは、NXP から提供されている無償の MCUExpresso Tool を使用します。
Elipse ベースの MCUXpresso IDE でソフトウェア開発を行います。マイコンを動かすために必要なソフトウェア群は SDK と呼ばれ、WEB からダウンロードしてインポートして使用することができます。
MCUXrpresso Config Tools は、IDE に付属しているツールで、Clock や Pin および Peripheral の設定等を GUI で変更可能です。
図-003.png
             【図3】 MCU 開発環境 MCUXpresso Software and Tools
                                            🔝 目次に戻る

3. 使用する開発キット

3-1. NXP クロスオーバー MCU i.MX RT1050 Evaluation Kit

i.MXRT 1050 Evaluation Kit は、Kit 単体では $100 以下で購入でき、最大動作周波数は 600MHz のボードです。搭載している主なインターフェースとしては、外部SDRAM、SD Card スロット、外部 Hyper Flash、外部 QSPI Flash、Ethernet、Camera Parallel Interface、Audio Jack、Debug USB Port などが搭載されています。
【参考】
i.MX RT1050 Evaluation Kit | NXP Semiconductors

3-2. Intel Cyclone 10 LP FPGA Evaluation Kit

今回使用した Intel FPGA は Cyclone 10 LP FPGA Evaluation Kit です。
低コスト、低消費電力なデバイスで、 USB ケーブル1本で電源供給やデバッグなどが行えるため、Intel FPGA の導入としては最適な評価キットだと思います。
【参考】
Intel🄬 Cyclone🄬 10 LP FPGA Evaluation Kit (intel.co.jp)
                                            🔝 目次に戻る

4. Intel Quartus Prime 開発ソフトウェア/ Platform Designer の構成

4-1. Remote System Upgrade の概要紹介

4-1-1. Remote System Upgrade の概念

まず Remote System Upgrade の概念について以下に説明します。
① Intel FPGA の Configuration ROM の中に Factory と Application の Data を格納しておき、Remote System Upgrade を実行する際は、Factory Image で起動しておきます。
図-004.png
    【図4】 Remote System Upgrade を実行する際は Factory Image で起動

② Factory Image で 外部マイコンから Application 2 を書き込み、Application を Update させます。
図-005.png
              【図5】 Application を Update

③ Factory Image で Remote Update IP RU を制御して、Reconfiguration を実行し、Application 2 を起動させます。
図-006.png
        【図6】 Reconfiguration を実行し Application 2 を起動

④ Application 2 が無事起動しますと、Remote System Upgrade の完了です。
図-007.png
       【図7】 Application 2 が起動し Remote System Upgrade が完了

お気づきの通り、Factory Image は最小限のデザインで構築しておき、Application に本番のデザインを構築します。また、Application にて Configuration ROM にアクセスしないのであれば、Generic Serial Flash Interface(GSFI)は削除しても問題ありません。
                                            🔝 目次に戻る

4-1-2. 作成する FPGA Configuration Data の種類

今回作成した Intel FPGA の Configuration Data は 3種類です。便宜上どれも同じデザインとなっており、LED の点灯パターンのみが異なります。
Factory の場合 LED0 が遅く点滅、Applicatoin 1 の場合 LED3 が遅く点滅、Application 2 の場合 LED3 が速く点滅となっています。
 ◦ Factory Design :    LED[0] 点滅(遅い)
 ◦ Application Design1 : LED[3] 点滅(遅い)
 ◦ Application Design2 : LED[3] 点滅(速い)
図-008.png
           【図8】 Configuration Data による LED の点灯パターンの違い

4-1-3. Intel Quartus Prime の階層構造

デザイン構成は下図のようになっています。どの Configuration Data で起動しているかわかるように、Verilog にてカウンター回路を用意して LED を点滅させています。Configuration ROM は AS Interface 経由で EPCQ128A が接続されています。
● HW 動作確認用として LED Counter 1bit を用意
 ◦ Factory Design :    LED[0] 点滅(遅い)
 ◦ Application Design1 : LED[3] 点滅(遅い)
 ◦ Application Design2 : LED[3] 点滅(速い)
● Configuration ROM は AS Interface 経由で EPCQ128A と接続
図-009.png
           【図9】 Intel Cyclone 10 LP FPGA Evaluation Kit でのデザイン構成
                                            🔝 目次に戻る

4-1-4. Platform Designer の構成

デザインを Platform Designer で構築すると下図ような構成になります。上から I2C Bridge、 GSFI、 LED、 Remote Update IP となっています。NXP マイコン・ソフトウェアで使用するため、アドレス値はロックをして固定値としています。
図-010.png
                  【図10】 Platform Designer の構成

以下にそれぞれの IP に関して説明します。
                                            🔝 目次に戻る

4-2. Intel FPGA I2C Agent to Avalon-MM Host Bridge Core の設定

まずは Intel FPGA I2C Agent to Avalon-MM Host Bridge Core の設定について説明します。この IP は、外部から入力された I2C Interface を Platform Designer の内部配線である Avalon Master 信号に変換するものです。つまり外部マイコンを Master として、FPGA 内部の IP を Slave として構成できる IP です。外部マイコンから見た I2C Slave の アドレス値を設定でき、今回は 0x55 を設定しています。32bit アドレス空間を用意するので Byte Addressing Mode は 4 です。
I2C Bridge の仕様書を見ると、Read の場合と Write の場合の I2C シーケンスが規定されています。この仕様に基づいて NXP のマイコンを制御します。
図-011.png
          【図11】 Intel FPGA I2C Agent to Avalon-MM Host Bridge Core の設定
【参考】
Intel🄬 FPGA I2C Agent to Avalon🄬-MM Host Bridge Core
                                            🔝 目次に戻る

4-3. Generic Serial Flash Interface Intel FPGA IP の設定

次に Generic Serial Flash Interface(GSFI)IPの設定について説明します。この IP は様々なメーカーの QSPI Flash にアクセスすることが可能な IP です。今回は AS Interface 経由で Configuration ROM にアクセスしていますが、User IO に接続した QSPI Flash にもアクセスできます。
様々な QSPI Flash に対応している代わりに、QSPI Flash の仕様に合わせて Register を設定する必要があります。その Register は初期値として設定することもできるので、起動後アプリケーションで初期化しなくても、起動直後アクセスできるようにすることも可能です。
今回は EPCQA128 なので、128 を設定する際に他のチェックボックスは外します。
初期値を設定する Default Settings では、Control Register で IP Enable を有効にするために、0x1 を設定します。
SPI の Clock 周波数は 1/2 に設定していますので、25MHz です。Standard 設定なので、データ線は 1 本です。
Read Instruction Register は、Dummy Cycle 0、Read Opcode 0x3 なので、0x3 を設定します。
Write Instruction Register は、Polling opcode に Read Status Register の 0x5 、Write Opcode に 0x2 を設定します。
図-012.png
          【図12】 Generic Serial Flash Interface Intel FPGA IP の設定
【参考】
Generic Serial Flash Interface Intel🄬 FPGA IP
                                            🔝 目次に戻る

4-4. Remote Update Intel FPGA IP の設定

最後に Remote Update Intel FPGA IP の設定についてです。各 FPGA Davice 毎に用意されていて Configuration を内部から制御可能です。
例えば通常、外部 Pin を制御する必要がある Reconfiguration や Application の移行、Configuration が発生した時のトリガー情報などを確認することができます。
今回は EPCQ128A を使用するのでその型番を設定します。Avalon Interface 経由で Write ができるように、2つチェックボックスを ON にします。
Application 移行のの手順を Register Map で説明すると、制御手順①にて Application 格納先アドレスを設定して、制御手順②で Reconfiguraiton を実行すると Application の移行が完了します。
図-013.png
               【図13】 Remote Update Intel FPGA IP の設定
【参考】
Remote Update Intel🄬 FPGA IP
                                            🔝 目次に戻る

4-5. I2C Interface の TOP 階層での接続

Quartus Prime の Top 階層での Verilog の記述を行います。Embedded Peripherals IP User Guide の記載を参考に記述を行います。I2C Interface の場合、SCL と SDA を抵抗でプルアップする必要があります。Intel Quartus Prime 開発ソフトウェア、あるいは NXP MCUXpresso のどちらかで設定します。

top.v
module top(
  c10_resetn,
  c10_clk50m,

//PIO
  user_led,
  user_pb ,
  user_dip,

//I2C  
  I2C_SLAVE_SCL,
  I2C_SLAVE_SDA,

);
input        c10_clk50m;
input        c10_resetn;

//LED PB DIPSW
output wire [3:0] user_led;
input       [3:0] user_pb;
input       [2:0] user_dip;

input			I2C_SLAVE_SCL; //GPIO 0 [1] with weak-pullup
inout			I2C_SLAVE_SDA; //GPIO 0 [3] with weak-pullup


//---------------------------------------------------------
//System
//---------------------------------------------------------

//=======================================================
//  REG/WIRE declarations
//=======================================================

wire i2c_mst_scl_oe;
wire i2c_mst_sda_oe;
assign I2C_MST_SCL = i2c_mst_scl_oe ? 0 : 1'bz;
assign I2C_MST_SDA = i2c_mst_sda_oe ? 0 : 1'bz;


wire i2c_slv_sda_oe;
assign I2C_SLAVE_SDA = i2c_slv_sda_oe ? 0 : 1'bz;


    I2C_Slave_GSFI u0 (
        .clk_clk                                                (c10_clk50m),			// clk.clk
        .i2cslave_to_avlmm_bridge_0_conduit_end_conduit_data_in (I2C_SLAVE_SDA),		// i2cslave_to_avlmm_bridge_0_conduit_end.conduit_data_in
        .i2cslave_to_avlmm_bridge_0_conduit_end_conduit_clk_in  (I2C_SLAVE_SCL),		// .conduit_clk_in
        .i2cslave_to_avlmm_bridge_0_conduit_end_conduit_data_oe (i2c_slv_sda_oe),   // .conduit_data_oe
        .i2cslave_to_avlmm_bridge_0_conduit_end_conduit_clk_oe  (),						// .conduit_clk_oe
        .led_pio_external_connection_export                     (user_led[3:1]),    // led_pio_external_connection.export
        .reset_reset_n                                          (c10_resetn)        // reset.reset_n
    );


//-----------------------------------------
//Heart beat by 50MHz clock
//-----------------------------------------
//Heart-beat counter
reg   [25:0]  heart_beat_cnt;

always @(posedge c10_clk50m or negedge c10_resetn)
  if (!c10_resetn)
      heart_beat_cnt <= 26'h0;
  else
      heart_beat_cnt <= heart_beat_cnt + 1'b1;

assign user_led[0] = heart_beat_cnt[25];


endmodule

【参考】
Embedded Peripherals IP User Guide
How to Translate the Bridge's I2C Data and I2C I/O Ports to an I2C Interface

補足) I2C Pull-up の有効方法
Tool により Week Pull-up の設定が必要です。今回は Quartus Prime 側で設定を行いました。
NXP マイコンにも内部 Pull-up の機能が搭載されているデバイスがあり、MCUXpresso の Config Tool で設定が可能です。

● Intel Quartus Prime 開発ソフトウェアの Assignment Editor で Week Pull-up を有効にする方法
図-014.png
      【図14】 Intel Quartus Prime の Assignment Editor で Week Pull-up を有効にする設定

● NXP MCUXresso Pin Configuration で Week Pull-up を有効にする方法
図-015.png
        【図15】 NXP MCUXresso Pin Configuration で Week Pull-up を有効にする設定
                                            🔝 目次に戻る

4-6. Remote Update System 設定の有効化

FPGA では Remote Updata 機能を使用するので設定を有効にします。Quartus Prime の[Assignments]メニューから、[Device]⇒[Device and Pin Options...]⇒[Configuration]を選択し、Configuration Mode の設定を Remote に変更します。
図-016.png
              【図16】 Remote Update System 設定の有効化
                                            🔝 目次に戻る

4-7. Full Compile の実施

設定が完了したら、Quartus Prime から[Start Compilation]ボタンをクリックして、Full Compile を実行します。Compile が完了すると、SOF ファイルが生成されるので、使用する Configuration Data(JIC ファイルと RPD ファイル)に変換して実機確認の準備をします。
Factory 用と Application1 用、Application 2 用をそれぞれ Full Compile して、3種類のファイルを生成します。
図-017.png
                  【図17】 Full Compile の実施
                                            🔝 目次に戻る

4-8. Factory と Application 1 用の JIC ファイルの生成

まず Factory と Application 1 の SOF ファイルが格納されている JIC ファイルを生成します。
型番は EPCQ128A で、Flash Loader にて Cyclone 10 LP を指定します。
Update をする前の Configuration ROM の状態は、0番地に Factory、0x000B_0000 番地に Application 1 という形にするので、2つの SOF を指定し、Properties で Application 1 のアドレス値を明示的に指定して Generate します。
図-018.png
            【図18】 Factory と Application 1 用の JIC ファイルの生成
                                            🔝 目次に戻る

4-9. Application 2 Configuration Data(RPD ファイル)の生成

続いて Application 2 の RPD ファイルを生成します。手順は先程と同様で JIC ファイルの生成を行いますが、自動で RPD ファイルを生成するオプションがあるのでそれを使用します。
型番は EPCQA128 に設定し、自動 RPD Option を有効にします。
左にある Options をクリックし Big Endian の設定に変更します。Properties での Start Address はデフォルトの 0x0 に設定します。
最後に JIC と RPD の差分について解説します。JIC は Intel FPGA が持っている JTAG IF 経由で、PC から Configuration ROM に Data を格納するためのファイルになります。ヘッダー情報を持っており、通常 Little Endian で生成します。RPD は JIC POF ファイルの中に記載さ入れいる Configuration Data の バイナリーファイルになり、ヘッダー情報などは付与されていなく Update 用として使用されます。通常 Big Endian で生成します。Intel Quartus Prime 側の設定はこれで完了です。
図-019.png
          【図19】 Application 2 Configuration Data(RPD ファイル)の生成
                                            🔝 目次に戻る

5. NXP MCUXpresso IDE の構成

5-1. 作成する NXP マイコン・プロジェクトの構成

作成する NXP マイコン・プロジェクトは下図の通りです。必要なペリフェラルは、I2C Core である LPI2C と SD Card Core です。
今回は、SD Card にある RPD ファイルを I2C Interface 経由で FPGA に転送するので、作成が必要なソフトウェアは図の右側の星マークのものです。
main ソフトウェアと、GSFI を制御するソフトウェア、I2C Bridge を制御するソフトウェアの3つになります。オレンジ色のソフトウェアは NXP 付属の SDK を使用しています。
図-020.png
            【図20】 作成する NXP マイコン・プロジェクトの構成
                                            🔝 目次に戻る

5-2. MCUXpresso サンプル・プロジェクトの構成

最初の作業としては MCUXpresso を起動し、サンプル・プロジェクトを構築することです。1からプロジェクトを作成するのではなく、サンプルベースで作成するのが簡単な方法です。
今回は、I2C より SD Card Core のほうが構成が複雑なため、SD Card Core のサンプルをベースに、I2C の機能を拡充していく形で作成を進めています。
Project をインポートすると、下図右側のような構成のプロジェクトが生成され、ファイルの種類によってフォルダー分けされています。
図-021.png
            【図21】 MCUXpresso サンプル・プロジェクトの構成
                                            🔝 目次に戻る

5-3. I2C の Driver を追加

I2C Driver の追加方法は、Project Exploar から[Manage SDK Components]ボタンをクリックすることで行えます。Driver タブから I2C にチェックを入れます。
図-022.png
                  【図22】 I2C の Driver を追加
                                            🔝 目次に戻る

5-4. I2C の Pin 情報を追加

続いて I2C の Pin 情報の追加を行います。Project Explorer の[Open Pins]をクリックすることで、Pin の設定を GUI で行うことができます。今回は、J11 を SCL 信号、K11 を SDA 信号に設定します。Pull UP は FPGA ツール側で設定しているため、ここでは OFF です。
設定が完了したら、Update Code をクリックしソースコードを自動生成します。
図-023.png
                   【図23】 I2C の Pin 情報を追加
                                            🔝 目次に戻る

5-5. I2C Core 制御ソフトウェア - I2C Write

ここから、作成したソフトウェアの概要について説明します。まずは、I2C Core 制御ソフウェアの Write の処理についてです。
I2C Bridge の仕様の通り、下図の①では LPI2C_MasterStart() を実行して、Start Bit と I2C Address を送ります。②では LPI2C_MasterSend() により Address と Data を送り、最後に LPI2C_MasterStop() で Stop Bit を送ります。
このように、SDK には I2C 制御用関数が用意されていますので、ユーザーは Slave の仕様に合わせてシーケンスを組み込むだけで実装することができます。
図-024.png
              【図24】 I2C Core 制御ソフトウェア - I2C Write

I2C_to_FPGA_Opelation.c のソースコード抜粋
#include <stdio.h>
#include <string.h>
#include "fsl_lpi2c.h"
size_t txCount    = 0xFFU;

status_t fpga_i2c_bridge_write(LPI2C_Type *LPI2C_BASE, uint32_t i2c_slave_addr, uint32_t target_addr, uint8_t *data, size_t txSize)
{
	status_t reVal;
	uint8_t tx_addr[16]={0};
	uint32_t tx_addr_size;
	tx_addr_size = 0;
	tx_addr[tx_addr_size++] = (target_addr >> 24) & 0xFF;
	tx_addr[tx_addr_size++] = (target_addr >> 16) & 0xFF;
	tx_addr[tx_addr_size++] = (target_addr >> 8) & 0xFF;
	tx_addr[tx_addr_size++] = (target_addr >> 0) & 0xFF;

	/* Send master blocking data to slave */
	reVal = LPI2C_MasterStart(LPI2C_BASE, i2c_slave_addr, kLPI2C_Write);
	if (reVal == kStatus_Success)
	{
		/* Check master tx FIFO empty or not */
		LPI2C_MasterGetFifoCounts(LPI2C_BASE, NULL, &txCount);
		while (txCount)
		{
			LPI2C_MasterGetFifoCounts(LPI2C_BASE, NULL, &txCount);
		}
		/* Check communicate with slave successful or not */
		if (LPI2C_MasterGetStatusFlags(LPI2C_BASE) & kLPI2C_MasterNackDetectFlag)
		{
			return kStatus_LPI2C_Nak;
		}
		reVal = LPI2C_MasterSend(LPI2C_BASE, &tx_addr, tx_addr_size);
		if (reVal != kStatus_Success)
		{
			if (reVal == kStatus_LPI2C_Nak)
			{
				LPI2C_MasterStop(LPI2C_BASE);
			}
			return reVal;
		}

		reVal = LPI2C_MasterSend(LPI2C_BASE, data, txSize);
		if (reVal != kStatus_Success)
		{
			if (reVal == kStatus_LPI2C_Nak)
			{
				LPI2C_MasterStop(LPI2C_BASE);
			}
			return reVal;
		}

		reVal = LPI2C_MasterStop(LPI2C_BASE);
		if (reVal != kStatus_Success)
		{
			return reVal;
		}
	}
	return reVal;
}

                                            🔝 目次に戻る

5-6. I2C Core 制御ソフトウェア - I2C Read

次に I2C Read の処理内容について説明します。I2C Bridge の仕様の通り、①の LPI2C_MasterStart() で Start Bit と I2C Address を送信し、②の LPI2C_MasterSend() で Address を転送します。Write と少し異なる点は、もう一度 Start Bit と I2C Address を送る必要があるため、③で LPI2C_MasterRepeatedStart() を実行して、①と同じ内容を再実行します。④で LPI2C の Read Data を取得し、最後に⑤で Stop Bit を送ります。
図-025.png
               【図25】 I2C Core 制御ソフトウェア - I2C Read

I2C_to_FPGA_Opelation.c のソースコード抜粋
status_t fpga_i2c_bridge_read(LPI2C_Type *LPI2C_BASE, uint32_t i2c_slave_addr, uint32_t target_addr, uint8_t *data, size_t rxSize)
{
	status_t reVal;
	uint8_t tx_addr[16]={0};
	uint32_t tx_addr_size;
	tx_addr_size = 0;
	tx_addr[tx_addr_size++] = (target_addr >> 24) & 0xFF;
	tx_addr[tx_addr_size++] = (target_addr >> 16) & 0xFF;
	tx_addr[tx_addr_size++] = (target_addr >> 8) & 0xFF;
	tx_addr[tx_addr_size++] = (target_addr >> 0) & 0xFF;

	/* Receive blocking data from slave */
	reVal = LPI2C_MasterStart(LPI2C_BASE, i2c_slave_addr, kLPI2C_Write);
	if (reVal == kStatus_Success)
	{
		/* Check master tx FIFO empty or not */
		LPI2C_MasterGetFifoCounts(LPI2C_BASE, NULL, &txCount);
		while (txCount)
		{
			LPI2C_MasterGetFifoCounts(LPI2C_BASE, NULL, &txCount);
		}
		/* Check communicate with slave successful or not */
		if (LPI2C_MasterGetStatusFlags(LPI2C_BASE) & kLPI2C_MasterNackDetectFlag)
		{
			return kStatus_LPI2C_Nak;
		}
		reVal = LPI2C_MasterSend(LPI2C_BASE, &tx_addr, tx_addr_size);
		if (reVal != kStatus_Success)
		{
			if (reVal == kStatus_LPI2C_Nak)
			{
				LPI2C_MasterStop(LPI2C_BASE);
			}
			return reVal;
		}

		reVal = LPI2C_MasterRepeatedStart(LPI2C_BASE, i2c_slave_addr, kLPI2C_Read);
		if (reVal != kStatus_Success)
		{
			return reVal;
		}

		reVal = LPI2C_MasterReceive(LPI2C_BASE, data, rxSize);
		if (reVal != kStatus_Success)
		{
			if (reVal == kStatus_LPI2C_Nak)
			{
				LPI2C_MasterStop(LPI2C_BASE);
			}
			return reVal;
		}

		reVal = LPI2C_MasterStop(LPI2C_BASE);
		if (reVal != kStatus_Success)
		{
			return reVal;
		}
	}
	return reVal;
}

                                            🔝 目次に戻る

5-7. GSFI サンプル・ソフトウェア(Nios II サンプルから移植)

GSFI のソフトウェアは、もともと Nios II で実装されているサンプルを参考に作成した I2C Driver に置き換えて使用しています。
Read Status Register 関数を例に説明すると、まず Read Command の設定を行い、その後 Command Run Register を 1 にして、最後に Read Data の取得を行い完了となる形です。
また、Data の Read と Write の場合は、Command の設定は GSFI 初期化ルーチンで行っているので、GSFI の Memory 領域にアクセスするだけで完了します。
図-026.png
           【図26】 GSFI サンプル・ソフトウェア(Nios II から移植)

GSFI_Operation_sample.c のソースコード抜粋
status_t read_various_register(gsfi_flash_info *flash_info, LPI2C_Type *LPI2C_BASE, uint32_t cmd, uint32_t num_data_bytes){
	uint32_t cmd_set = 0;
	uint32_t read_data = 0;
	uint8_t data1[4] = {0};
	uint8_t data2[4] = {0};
	uint8_t data3[4] = {0};
	num_data_bytes = num_data_bytes << GSFI_CMD_SET_NUM_DATA_BYTES_BIT;
	cmd_set = (
			(GSFI_CMD_SET_NUM_DATA_BYTES_MASK & num_data_bytes)
			+(GSFI_CMD_SET_DATA_TYPE_MASK)
			+(cmd)
	);
	data1[0] = (cmd_set >> 0)  & 0xFF;
	data1[1] = (cmd_set >> 8)  & 0xFF;
	data1[2] = (cmd_set >> 16) & 0xFF;
	data1[3] = (cmd_set >> 24) & 0xFF;

	fpga_i2c_bridge_write(LPI2C_BASE, flash_info->i2c_slave_addr, flash_info->gsfi_csr_base + GSFI_CMD_SET_REG*4, data1, 4);

	data2[0] = (GSFI_CMD_CONTROL_START_MASK >> 0)  & 0xFF;
	data2[1] = (GSFI_CMD_CONTROL_START_MASK >> 8)  & 0xFF;
	data2[2] = (GSFI_CMD_CONTROL_START_MASK >> 16) & 0xFF;
	data2[3] = (GSFI_CMD_CONTROL_START_MASK >> 24) & 0xFF;

	fpga_i2c_bridge_write(LPI2C_BASE, flash_info->i2c_slave_addr, flash_info->gsfi_csr_base + GSFI_CMD_CONTROL_REG*4, data2, 4);
	fpga_i2c_bridge_read(LPI2C_BASE, flash_info->i2c_slave_addr, flash_info->gsfi_csr_base + GSFI_CMD_READ_DATA0_REG*4, data3, 4);

	read_data =  data3[0];
	read_data |= data3[1] << 8;
	read_data |= data3[2] << 16;
	read_data |= data3[3] << 24;
	return read_data;
}

【参考】
Embedded Peripherals IP - Generic Serial Flash Interface メモリーテストサンプル
                                            🔝 目次に戻る

5-8. main ソフトウェア

main ソフトウェアについてですが、これはマイコン起動後に GSFI 経由で Flash ROM にアクセスし自動的に Device ID を確認して接続を行います。接続に失敗する場合は、I2C Interface の構築に失敗していますので接続状況等を確認します。
その後は、SD Card の挿入確認と SD Card 階層パスの指定を行い、RPD ファイルが格納されていることを確認します。コマンドメニューで Remote System Upgrade の実行等を指定できます。
図-027.png
                  【図27】 main ソフトウェア

lpi2c_fatfs_fpga_update_sample.c のソースコード抜粋
	while (true){
		PRINTF("\r\n");
		uint8_t reconfig_write_data[1];
		switch(num){
		case 48:
			reVal = sdcardChangeDirectory(&directory, directoryPath);
			if(reVal != kStatus_Success){
				break;
			}
			reVal = sdcardListDirectory(&directory, fileInformation, directoryPath);
			break;
		case 49:
			sdcardOpenFile(g_fileObject, flash_info, sd_file_info , BUFFER_SIZE);
			break;
		case 50:
			reVal = update_to_gsfi_from_sd(flash_info, Example_LPI2C1_BASE, sd_file_info, g_fileObject);
			break;
		case 51:
			reVal = change_fpga_config_mode(flash_info, Example_LPI2C1_BASE, sd_file_info, g_fileObject);
			break;
		case 52:
			led_blink_to_pio(flash_info, Example_LPI2C1_BASE,3);
			break;
		case 53:
			goto FINISH;
			break;
		default:
			PRINTF("Don't input other number and character. num = %d\r\n",num);
			break;
		}

		if(reVal != kStatus_Success){
			if (reVal == kStatus_Fail){
				PRINTF(" kStatus_Fail : reVal = 0x%x\r\n",reVal);
				goto FINISH;
			}else if(reVal == kStatus_OutOfRange){
				PRINTF(" kStatus_OutOfRange : reVal = 0x%x\r\n",reVal);
			}else if(reVal == kStatus_NoData){
				PRINTF(" kStatus_NoData : reVal = 0x%x\r\n",reVal);
			}else if(reVal == kStatus_InvalidArgument){
				PRINTF(" kStatus_InvalidArgument : reVal = 0x%x\r\n",reVal);
			}else{
				PRINTF(" Other Error : reVal = 0x%x\r\n",reVal);
			}
		}
		PRINTF("\r\n----------------------------\r\n");
		PRINTF("Please Input 0~5.\r\n");
		PRINTF("0:SDCARD List Directory\r\n");
		PRINTF("1:SDCARD Open File\r\n");
		PRINTF("2:GSFI Update Configuration ROM\r\n");
		PRINTF("3:Re-Configuration FPGA\r\n");
		PRINTF("4:LED Blink\r\n");
		PRINTF("5:Finish Application");
		PRINTF("\r\n----------------------------\r\n");
		num = GETCHAR();
		PUTCHAR(num);
	}

                                            🔝 目次に戻る

5-9. Generic FAT Filesystem NXP Driver

最後に SD Card の Driver についての説明ですが、一般的な Fat File System の Driver であり NXP SDK に標準で用意されています。
SD Card の Data にファイル形式でアクセスすることができ、f_lseek() というファイルの中で Offset を移動させることができる関数もあるので、ファイルを分割して Read していくことが可能です。今回は128Byte ごと Read しています。
図-028.png
               【図28】 Generic FAT Filesystem NXP Driver
                                            🔝 目次に戻る

6. 動作確認

6-1. 使用する Tool の準備

まず最初に使用する Tool の準備ですが、それぞれ参考ページが用意されていますので、そちらを確認してください。

  1. インテル Quartus Prime 開発ソフトウェア light エディションをダウンロードしてインストール
    インテル Quartus Prime 開発ソフトウェアおよび Questa - Intel FPGA Edition のダウンロード方法
    ◦ lightエディションであれば、無償で使用可能
  2. MCUXpresso IDE をダウンロードしてインストール
    [NXP マイコン初心者ガイド 0] MCUXpresso IDE のインストール方法
  3. MCUXpresso SDK をダウンロードして、MCUXpresso IDE にインストール
    [NXP マイコン初心者ガイド 1] MCUXpresso IDE でサンプルプロジェクトを作成する方法

6-2. Cyclone 10 LP Evaluation Kit と i.MX RT1050 Evaluation Kit をジャンパーで接続

実際の基板の接続は下図のようになっています。左側が Cyclone 10 LP Evaluation Kit、右側が I.MXRT1050 Evaluation Kit です。Cyclone 10 LP 側は 40pin の0,1番を使用します。i.MXRT 側は Arduino Interface に接続しています。
図-029.png
      【図29】 Cyclone 10 LP Evaluation Kit と i.MX RT1050 Evaluation Kit の接続
                                            🔝 目次に戻る

6-3. i.MX RT1050 Evaluation Kit に SD Card を挿入

i.MXRT Evaluation Kit には SD Card を挿入しますが、SD Card の中には RPD ファイルを格納しておきます。
1番は、factory と Application の 両方が格納された RPD
2番は 1番のファイルに格納されている Application 1 だけの RPD
3番は LED の点灯速度が速い Application 2 だけの RPD となっており、3番をアップデートしていきます。
差分は下図記載の通りです。
図-030.png
             【図30】 i.MX RT1050 Evaluation Kit に SD Card を挿入
                                            🔝 目次に戻る

6-4. Cyclone 10 LP Evaluation Kit に JIC ファイルを書き込み

Cyclone 10 LP Evaluation Kit の Configuration ROM には、あらかじめ Factory と Application1 が入った JIC ファイルを書き込んでおきます。起動後 LED0 だけが遅く点滅していることを確認できます。
        458_260_8.33MB.gif
          【動画1】 Cyclone 10 LP Evaluation Kit に JIC ファイルを書き込み
                                            🔝 目次に戻る

6-5. MCUXpresso の sdcard_fatfs サンプル・プロジェクトを新規作成しソースコードを追加

6-5-1. MCUXpresso sdcard_fatfs サンプル・プロジェクトの新規作成

続いて MCUXpresso で NXP マイコンの Debug 環境を構築します。下図の通り sdcard_fatfs サンプル・ソフトウェアを選択し新規プロジェクトを生成します。
詳細の手順は下記参考リンクをご覧ください。
図-031.png
          【図31】 MCUXpresso sdcard_fatfs サンプル・プロジェクトの新規作成

【参考】
[NXP マイコン初心者ガイド 1] MCUXpresso IDE でサンプルプロジェクトを作成する方法
                                            🔝 目次に戻る

6-5-2. MCUXpresso sdcard_fatfs サンプル・プロジェクトへのソースコード追加

sdcard_fatfs サンプル・プロジェクトをベースに、「5-3. I2C の Driver を追加」、「5-4. I2C の Pin 情報を追加」で説明した方法で、I2C の Driver と Pin 設定を行います。
その後、下図で削除と記載しているソフトウェア4つを削除し、今回作成したソースコードを Source フォルダーにすべて追加します。Build が成功すれば準備完了です。
図-032.png
      【図32】 MCUXpresso sdcard_fatfs サンプル・プロジェクトへのソースコード追加
                                            🔝 目次に戻る

6-6. サンプル・ソフトウェアの printf 表示するための Terminal を接続

サンプルをインポートしたら、printf 文を表示させる Terminal を接続します。MCUXpresso から Terminal を接続するか、Tera Term などを使用して接続します。
ボーレート115200 bps、データサイズ 8bit、パリティ無し、1ストップビット に設定します。

6-7. MCUXpresso Project の Build と Debug

左下にある Quickstart Panel から Build アイコンをクリックしてプロジェクトを Build します。Build が完成したら Debug アイコンをクリックして実行させます。
              図-033.png
            【図33】 MCUXpresso Project の Build と Debug
                                            🔝 目次に戻る

6-8. Remote System Upgrade で考慮すべき事項

最後に、Remote System Upgrade を実装するうえで、考慮すべき事項について説明します。それは、Update File をどうやって Configuration ROM に書き換えるかということです。
Factory Design と Application Design を2面持たせることは容易に実装可能ですが、Application を Update する機能を実装するのはそれなりに手間がかかります。
構成の例として、下図左上の UART と 外部マイコンを使用した例の場合、FPGA 内部にも Nios II や SoC などのマイコンやプロセッサーを実装して、UART の Data Register からその都度 Data を取り出す必要があります。
また、下図左下にある Ethernet 経由で Data を Update することも可能ですが、これもマイコンやプロセッサーを実装している必要があります。
Nios II を実装する場合、最低でも 100k 以上のRAM 容量が必要であったり、SoC を搭載している高級な FPGA デバイスにしなければならなかったりと、すべてのユーザーが実装できる構成では無い場合があります。
一方、下図右上の黄色枠で囲っている構成の場合、FPGA のロジックはかなり少なく、安価な外部マイコンさえ搭載してしまえば、簡単に実装することができます。Remote System Upgrade を検討される場合には、今回の例のように外部マイコンから実行する方法も視野に入れることができるかもしれません。
図-034.png
             【図34】 Remote System Upgrade で考慮すべき事項
                                            🔝 目次に戻る

8
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
0