メイン・コンテンツまでスキップ

STM32H7R7 & S7でのグラフィックスの実行

この記事ではSTM32H7R/Sシリーズのマイクロコントローラ固有のアーキテクチャを取り上げ、これをグラフィックス用に使用するときに必要な考慮事項について説明します。 ただし、これらの考慮事項のほとんどは、外部RAMとFlashでグラフィックスを実行するすべてのSTM32マイクロコントローラに適用されます。

この記事は、TouchGFXボード・セットアップ(TBS)の作成方法に関する初心者向けガイドではありません。 STM32H7R/Sは高性能で高度なマイクロコントローラだからです。 したがって、この記事ではSTM32H7R/Sに固有で重要な領域にも踏み込みます。 TouchGFX TBSの作成方法に関する一般的な概要については、ボードの立ち上げに関するガイドを参照してください。
STM32H7R7/S7の詳細については、製品ページまたはSTM32H7RSの完全なデモ・ワークショップを含むYouTubeプレイリストを参照してください。

TouchGFX DesignerにはSTM32H7S78 DK向けのTBSが含まれています。これはSTM32H7R/SでのTouchGFXの実行に関する完全なプロジェクト例です。 TBSは、STM32H7R/S向けにTouchGFXアプリケーションを開発する際のリファレンスとして使用できます。 このプロジェクトはSTM32CubeMXをベースにしているため、STM32H7S78-DK.iocファイルを開くことで、キャッシュ、MPU、外部メモリなどの推奨設定にアクセスできます。

TouchGFX Designerで使用できるTouchGFXボード・セットアップ

メモリのセットアップ

STM32H7R/SはブートFlashマイコンです。 ブートFlashマイコンは、ブートローダを格納した小型の内蔵Flashメモリ搭載のマイクロコントローラで、メインのアプリケーションはアセットと一緒に外部メモリに配置されています。 STM32H7R/Sには620kBの内蔵SRAMも搭載されています。 このためSTM32H7R/Sは、グラフィックス・アプリケーションの使用時に外部RAMとFlashの両方に依存します。 グラフィックス用に外部メモリを使用する際には、外部メモリへのメモリ帯域幅がボトルネックになることが多くあります。外部メモリがCPU周波数の半分または3分の1の速度で動作するからです。 STM32H7R7/S7の場合、2つのXSPIインタフェース(16および8ビット)がダブル転送レートで最大200 MHzで実行動作で、FMC(16または32ビット)は最大100 MHzで動作可能です。

外部メモリ・マネージャ

外部メモリ・マネージャと外部メモリ・ローダと呼ばれる2つのツールは、STM32CubeMXで[Categories]→[Middleware and Software Packs]を選択して使用できます。 これらのツールは、ブートFlashまたはFlashレスのアプリケーションで外部メモリをセットアップするユーザを支援するために作成されたものです。 外部ローダの作成やアプリケーション・タイプの選択などが簡単になります。 これらのツールの概要にはこちらからアクセスできます。 「Introduction to external serial memory with STM32(STM32での外部シリアル・メモリの概要)」という記事がまもなく公開される予定です。

Further reading

[外部メモリ・マネージャと外部メモリ・ローダの入門書]https://wiki.st.com/stm32mcu/wiki/Getting_started_with_External_memory_Manager_and_External_memory_loader)

外部RAMに配置したフレームバッファ

フレームバッファを外部RAMに配置する場合に最初に考慮すべき最も重要な事項は、メモリ帯域幅の要件と制約です。 GRAMを搭載しないディスプレイでは、ディスプレイごとに指定されたレートでフレームバッファを転送し続ける必要があります。 Discovery Kitで使用されるディスプレイの場合は60 Hzです。 つまり、LTDCの更新のためのみに、外部RAMインタフェース上の多くの帯域幅が占有されてしまうことになります。 LTDCで必要とされる帯域幅は次の計算で求められます。

ピクセル・クロック = LCD_CLK= 全スクリーンサイズ * リフレッシュレート
必要な帯域幅(LTDCレイヤ1つあたり)= LCD_CLK * Bpp

さらに、DMA2DとGPU2Dもフレームバッファ上で操作を行うときに外部RAMの帯域幅を必要とします。 メモリが何か他のこと(アプリケーション・コードなど)にも使用されている場合は、帯域幅がさらに減らされます。
これらの要因が組み合わさると、外部RAMのバスが混乱してしまいます。

外部RAM内のフレームバッファでグラフィックスを実行する場合の考慮事項を説明した記事には、こちらからアクセスできます。

外部RAMにLTDCディスプレイ・インタフェースとフレームバッファを配置する場合の制約と考慮事項については、LTDCアプリケーション・ノート を参照してください。 第5章「LTDCを用いたグラフィカル・アプリケーションの作成」と第7章「LTDCアプリケーション例」は、特に入念にご確認ください。
外部RAMの帯域幅が制限に達している場合は、第5.5.2章「外部メモリからフェッチするLTDCフレームバッファの最適化」と第5.5.3章「SDRAMからフェッチするLTDCフレームバッファの最適化」の内容を検討してください。

Further reading

密に結合されたメモリ

STM32H7R/S Cortex-M7は、密に結合されたメモリ(TCM)への0ウェイトステートの64ビット幅ダイレクト・アクセスを特徴としています。 最大192 kBのデータTCM(DTCM)と命令TCM(ITCM)の両方を備えています。 このためDTCMはデータの読み出し/書き込み、ITCMは命令フェッチにとって最適なロケーションになっています。 したがって、ITCMは、キャッシュミスによる待ち時間が許容されない割込みハンドラや重要な制御ループなど、決定論的な実行を伴う重要なコードのために使用する必要があります。 RTOSを使用するリアルタイムのアプリケーションでは、一般的にヒープが大規模に使用されます。 このため、RTOSのスタックとヒープはDTCM内に配置することが推奨されます。 いくらかスペースが残っている場合は、グローバル変数もそこに配置することが可能です。

ITCMとDTCMは、SRAM1メモリとSRAM3メモリのある部分を使用するので、注意することが重要です。 このことは、ITCMとDTCMを使用すると内部SRAMのサイズが縮小することを意味します。

STM32H7R/Sの密に結合されたメモリの図

他のH7マイクロコントローラと同様に、STM32H7R/Sにはレベル1(L1)キャッシュがあります。 L1キャッシュの詳細については、H7キャッシュのアプリケーション・ノートを参照してください。 第4章「ミスの予防とヒント」は特に注意して読んでください。

外部SPIメモリのセットアップ方法の詳細については、OSPI、HSPI、XSPIのアプリケーション・ノートを参照してください。

Further reading

アプリケーション・タイプ

起動時には、選択したアプリケーション・タイプによってブートローダの動作が異なります。 外部Flashにすでに配置済みのアプリケーションを示すか、アプリケーションを別のメモリ(通常は外部RAM)に読み込むかのどちらかが可能です。
外部Flashにすでに配置済みのアプリケーションの実行は、XIP(Execute in Place)と呼ばれます。 ブート時にアプリケーションをFlashからRAMにコピーして、RAMから実行することは、LRUN(Load and Run)と呼ばれます。

アプリケーションが暗号化されている場合は、LRUNのみが使用できます。 STM32での暗号化の詳細については、暗号化に関するアプリケーション・ノートを参照してください。

Further reading

[AN6088: STM32マイクロコントローラでの暗号化/復号化にMCEを使用する方法]https://www.st.com/resource/en/application_note/an6088-how-to-use-mce-for-encryptiondecryption-on-stm32-mcus-stmicroelectronics.pdf)

XiP(Execute in Place)

グラフィックス・アプリケーション向けのXiPのメモリ・レイアウトの例を以下に示します。 XiPはデフォルトのアプリケーション・タイプです。

グラフィックス用のXiPアプリケーションの図

XiPの図に示すように、外部Flashに対するOctoSPIインタフェースは、アプリケーション・コードとグラフィックス・アセットの両方へのアクセスに使用されます。 CPUがアプリケーション・コードに常時アクセスするので、アセットへのアクセス時にNeoChrom GPUまたはChrom-ARTのアクセスが低速になる可能性があります。 このことはグラフィックス性能に悪影響を及ぼします。 この問題を緩和するために、XiPの実行時には外部Flashの命令キャッシュを有効にすることを強く推奨します。 これにより、繰り返しの命令が外部Flashではなくキャッシュから読み出されるようになるため、帯域幅の負荷が減り、外部Flashインタフェースの効率が向上します。

LRUN(Load and Run)

LRUNに対応する例を以下の図に示します。

グラフィックス用のLRUNアプリケーションの図

LRUNの図に示すように、アプリケーション・コードがグラフィックス・アセットから切り離されるので、アセットのアクセスが向上します。 ただし、これにより外部RAMに対するインタフェースに負荷がかかります。フレームバッファとアプリケーション・コードの両方にアクセスする必要があるからです。 この場合は、外部RAMインタフェースで命令キャッシュを有効にすることを強く推奨します。

STM32H7R/S上のLRUNをグラフィックス・アプリケーションで使用する場合、可能な最高の性能を達成するためにいくつかの点を追加で考慮する必要があります。
まず、アセット(ビットマップ、フォントなど)を外部Flash内に格納できるかどうか検討します。 これらのアセットを頻繁にアクセスするので、これらが外部RAMに格納されていると、外部RAMの帯域幅を大幅に圧迫することになります。 さらに、通常はアセットの暗号化は不要です。
2つ目に、下の図に示すようにアプリケーション・コードが内部SRAMに収まるかどうか調査することは価値があります。 内部SRAMからであれば、外部Flashや外部RAMにある場合と比べて、アプリケーション・コードにさらに速くアクセスし実行することができます。内部バスの方が高速だからです。 内部SRAMの接続先であるSTM32H7R/SのAXIバスは、最大300 MHzの速度で動作できます。 さらに、この構成ではアセット、フレームバッファ、アプリケーション・コードを3つの異なる場所に配置できるので、3つの個別のバス間に帯域幅を分散できます。

アプリケーション・コードが内部RAMにある場合のグラフィックス用のLRUNアプリケーションの図

パフォーマンス比較

XiPとLRUNをそれぞれ使用した複雑なGUIの例を以下に示します。 LRUNアプリケーションでは、内部SRAMにアプリケーション・コードがあります。 この比較では、異なる設定別にマイクロコントローラが受ける負荷を示しています。 TouchGFXフレームワークとアプリケーションを内部SRAMに配置することで、外部RAMとFlash内でのフェッチのサイクル数が減少し、マイクロコントローラの負荷が効果的に削減されます。
リファレンスとなるデモは、STM32H7S78-DK向けのデモです。

LRUNおよびXiPアプリケーションでのマイクロコントローラの負荷の比較

この比較からは、アプリケーション・コードを内部SRAMに配置した場合にマイクロコントローラの負荷が減少することがわかります。 LRUNを使用した場合、マイクロコントローラの負荷はXiPの場合と比べて約50%減少しています。

この比較からは、アプリケーション・コードを内部SRAMに配置した場合にマイクロコントローラの負荷が大幅に減少することがわかります。 内部SRAMのアクセス時間の方が外部RAMとFlashよりも高速だからです。 内部SRAMにあるアプリケーション・コードでLRUNを使用すると、マイクロコントローラの負荷がXiPの場合と比べて50%削減されます。 内部SRAMに格納されたアプリケーション・コードでLRUNを使用することで、最高のパフォーマンスを実現できるのです。 ただし、この構成は、使用可能な内部SRAM内にアプリケーション・コードが収まる場合にのみ実現可能です。

MPUの設定

メモリ保護ユニット(MPU)は、意図しないメモリへのアクセスや実行からメモリ領域を保護するために使用されます。
Arm® Cortex®-M7プロセッサでは投機的アクセスを防ぐことが重要です。外部メモリでこれが実行されると、高いレイテンシやシステムエラーの原因になるからです。 STM32H7R/Sでは、AXIマスタのメモリへのアクセスに影響し、グラフィックス性能が著しく低下します。
MPUを使用して、アクセス可能なアドレス範囲を制御することで、投機的読み出しアクセスを防止できます。 このための最も簡単な方法は、メモリ領域全体でバックグラウンド領域を使用し、Strongly-Ordered、Execute-Neverに設定してアクセスを制限することです。

バックグラウンド領域はID -1のデフォルト領域内で定義する必要があります。これにより、その他すべての領域がこの領域よりも優先されることになるからです。 次に、アクセスの必要なメモリ領域に対して、その他のMPU領域をそれぞれの設定で定義する必要があります。 STM32H7R/Sでは最大16個の領域を定義できます。

STM32H7S78 DK TBSにおけるMPUの設定を以下に示します。 この設定はリファレンスとして使用できます。

領域0すべて
属性
MPU領域ベース・アドレス0x0
MPU領域サイズ4 GBマイクロコントローラの全メモリ領域に対応
MPUサブ領域の無効化0x0
MPU TEXフィールド・レベルLevel 0
MPUアクセス許可ALL ACCESS NOT PERMITTEDすべてのアクセスを制限
MPU命令アクセスDISABLE
MPU共有可能許可ENABLE
MPUキャッシュ可能許可DISABLE
MPUバッファ可能許可DISABLE
領域1外部Flash
属性
MPU領域ベース・アドレス0x70000000XSPI2のベース・アドレス(外部Flash)
MPU領域サイズ128 MBボード上に128 MBの外部Flash
MPUサブ領域の無効化0x0
MPU TEXフィールド・レベルLevel 1
MPUアクセス許可ALL ACCESS PERMITTED
MPU命令アクセスDISABLE
MPU共有可能許可DISABLE
MPUキャッシュ可能許可ENABLE
MPUバッファ可能許可ENABLE
領域2外部Flash
属性
MPU領域Enabled
MPU領域ベース・アドレス0x70000000XSPI2のベース・アドレス(外部Flash)
MPU領域サイズ2 MB外部Flashの最初の2 MBのプロパティで、アプリケーション・コードが配置され、上書きされる
MPUサブ領域の無効化0x0
MPU TEXフィールド・レベルLevel 1
MPUアクセス許可ALL ACCESS PERMITTED
MPU命令アクセスENABLE
MPU共有可能許可DISABLE
MPUキャッシュ可能許可ENABLE
MPUバッファ可能許可ENABLE
領域3外部PSRAM
属性
MPU領域ベース・アドレス0x90000000XSPI1のベース・アドレス(外部PSRAM)
MPU領域サイズ32 MBボード上に32 MBの外部PSRAM
MPUサブ領域の無効化0x0
MPU TEXフィールド・レベルLevel 1
MPUアクセス許可ALL ACCESS PERMITTED
MPU命令アクセスDISABLE
MPU共有可能許可DISABLE
MPUキャッシュ可能許可DISABLE
MPUバッファ可能許可DISABLE
領域4DTCM
属性
MPU領域ベース・アドレス0x20000000DTCMのベース・アドレス
MPU領域サイズ64 kBDTCMのデフォルトの64 kB
MPUサブ領域の無効化0x0
MPU TEXフィールド・レベルLevel 1
MPUアクセス許可ALL ACCESS PERMITTED
MPU命令アクセスDISABLE
MPU共有可能許可DISABLE
MPUキャッシュ可能許可DISABLEDTCM上でのキャッシュを無効にする(パフォーマンス向上をもたらさないため)
MPUバッファ可能許可DISABLE
領域5SRAM
属性
MPU領域ベース・アドレス0x24000000SRAM1のベース・アドレス
MPU領域サイズ512 kBSRAM1、SRAM2、SRAM3、SRAM4に対応
MPUサブ領域の無効化0x0
MPU TEXフィールド・レベルLevel 1
MPUアクセス許可ALL ACCESS PERMITTED
MPU命令アクセスDISABLE
MPU共有可能許可ENABLE
MPUキャッシュ可能許可ENABLE
MPUバッファ可能許可ENABLE
領域6GPU2Dコマンド・リスト
属性
MPU領域ベース・アドレス0x2406e000NeoChrom GPUコマンド・リストがここに配置される
MPU領域サイズ16 kBTouchGFX使用時のNeoChrom GPUコマンド・リストのデフォルト・サイズ(nema_hal.cで定義)
MPUサブ領域の無効化0x0
MPU TEXフィールド・レベルLevel 0
MPUアクセス許可ALL ACCESS PERMITTED
MPU命令アクセスDISABLE
MPU共有可能許可ENABLE
MPUキャッシュ可能許可DISABLEコマンド・リスト上のキャッシュを無効化
MPUバッファ可能許可ENABLE

グラフィックス固有のMPUの設定全般に関するヒントについては、LTDCアプリケーション・ノートの第5.6.2章「メモリ保護ユニット(MPU)の設定」を参照してください。

さらなるリファレンスについては、MPUアプリケーション・ノートを参照してください。 第3章「Cortex-M0+/M3/M4/M7メモリタイプ、レジスタ、属性」と第6章「Armv6およびArmv7アーキテクチャにおけるSTM32Cube HALでのMPUの設定例」は特に入念にご確認ください。

Further reading

デバッグ

以下のガイドはSTM32CubeIDEにおけるSTM32H7R/Sのデバッグに関するもので、TouchGFX DesignerにあるTBS内のreadmeで入手できます。

STM32H7S78-DKのTBSのブートローダとアプリケーションの構造が原因で、IDEでのコードのデバッグは複雑になっています。 STM32CubeIDEでTouchGFXアプリケーションのコードを調べるには、以下の手順を実行します。

  1. TouchGFX Designerでコードを生成する。
  2. STM32CubeIDEでプロジェクトを開く。
  3. Bootプロジェクトのデバッグ・セッションを起動する。
  4. コンパイルとフラッシングの完了を待つ。
  5. デバッグ・セッションを終了する(Ctrl + F2)。
  6. Appliプロジェクトのデバッグ・セッションを起動する。
  7. コンパイルとフラッシングの完了を待つ。
  8. [Resume (F8)]をクリックする。
  9. STM32H7S78-DKボード上の黒いNRSTボタンを押す。
  10. Appliプロジェクトのmain()の最初の行で、アプリケーションがブレーク・ポイントに達する。 そうでない場合は[Resume (F8)]を再度クリックする。
  11. [Resume (F8)]や[Step Over (F6)]をクリックするなどで続行する。

デバッグの詳細については、STM32H7RS上のDAアクセスで開始する方法に関するwikiページを参照してください。

Further reading

まとめとグラフィックス・アプリケーションに関する一般的な推奨事項

これまで説明したように、STM32H7R/Sでグラフィックス・アプリケーションを開発する際には複数の考慮事項があります。 しかし、こうした考慮事項への注意を怠らなければ、高速のCPUと強力なGPU2Dによって優れたグラフィックス性能を達成することができます。

何よりもまず、外部メモリ・バスの帯域幅に注意を払うことが重要です。 これは外部RAMとFlashを使用するすべてのマイクロコントローラに適用されますが、ブートFlash構造を持つSTM32H7R/Sでは特に重要な考慮点になります。

重要な命令とデータをITCMおよびDTCMメモリ内に配置することで、パフォーマンスが大幅に向上します。

Arm® Cortex®-M7プロセッサに統合されたL1命令とデータ・キャッシュを有効にします。こうすることでもパフォーマンスが向上します。

アプリケーションの要件に基づいてXiPまたはLRUNのどちらを実行するのか選択します。ただし、メモリの帯域幅に注意してください。 アプリケーション・コードが内部SRAMに収まる場合は、LRUNが最高のパフォーマンスを実現します。

投機的読み出しアクセスは著しく性能を低下させる可能性があるため、これを防ぐことが重要です。 このためには、すべてのメモリ領域に適切なMPU設定を適用します。