目次
  1. はじめに:学習はできた、で実装は?
  2. STM32Cube.AI とは(X-CUBE-AI / AI Studio / Edge AI Suite)
  3. 生成コードのファイル構成とメモリ 3 区分
  4. メモリ階層と速度の関係(STM32H7 を例に)
  5. 重み配置の 5 パターンとトレードオフ
  6. リンカスクリプト書き換え実践
  7. MPU + D-Cache 最適化
  8. CubeMX / CubeIDE での実装ワークフロー
  9. 最新動向:STM32N6 + Neural-ART NPU
  10. 公式リソース・参考文献
  11. まとめ
本記事の前提

本記事は STM32Cube.AI (X-CUBE-AI) v10 系を念頭に、STM32H7 / U5 を主軸として解説します。STM32N6(最新 NPU 搭載品)にも触れます。リンカスクリプト書き換えは GCC ベース(STM32CubeIDE / Arm GNU Toolchain)の .ld 書式で示しますが、IAR / Keil でも考え方は同じです。

はじめに:学習はできた、で実装は?

「Keras で MobileNet を学習させて 98% の精度が出た。さあ STM32 に載せよう」――ここで多くのエンジニアが詰まります。モデルサイズが 内蔵 Flash 容量を超える、または載せても 推論速度がリアルタイム要件に届かない。さらにバッテリ駆動製品なら 消費電流もシビア

これらをワンセットで解決するのが STM32Cube.AI(旧 X-CUBE-AI)です。Keras / TFLite / ONNX で学習済みのモデルを 量子化 + 最適化 + STM32 専用 C コード化し、さらに重み(weights)を 外部 Quad-SPI Flash に置いて Memory-Mapped Mode で読みに行くといった配置最適化まで可能です。

本記事は「Cube.AI で C コード化できた、でも内蔵 Flash に収まらない / 動かない」段階のエンジニアが、リンカスクリプト(.ld ファイル)書き換えレベルで外部メモリ配置に踏み込めるよう、ST 公式の UM2526 / AN5050 / AN4839 を一次資料に体系化します。基礎となる DMA は STM32 DMA 完全ガイド、FreeRTOS との連携は STM32 + FreeRTOS 入門 を併せてご覧ください。

弊社での活用実績

弊社は 画像認識・組込み AI 案件を多数 手がけており、STM32 系のエッジ推論実装でリンカスクリプト書き換えやキャッシュ最適化を伴う案件のノウハウを蓄積しています。本記事はその実案件で踏んだ落とし穴と公式ドキュメントの読み解きを整理したものです。

STM32Cube.AI とは(X-CUBE-AI / AI Studio / Edge AI Suite)

2026年現在、ST のエッジ AI ツールは 「ST Edge AI Suite」というブランド傘下に統合されつつあります。整理すると:

ツール位置付け使う場面
X-CUBE-AI (STM32Cube.AI)CubeMX 内蔵ミドルウェアパック。MCU 向けコード生成の中核既存の CubeMX フローを継続する案件
STM32Cube AI Studio2025-2026 リリースの新スタンドアロンデスクトップツール新規案件で、量子化~ベンチマーク~デプロイを統合 UI で進めたい
NanoEdge AI StudioAutoML(異常検知中心)、オンデバイス学習可異常検知 / 1-class classification
ST Edge AI Developer Cloudオンライン版、board farm で実機ベンチ可実機を持たずにベンチマーク取得したい
X-LINUX-AISTM32 MPU (Linux) 向けSTM32MP1 / MP2 系

X-CUBE-AI の基本機能

  • 対応モデル形式:Keras (.h5) / TFLite (.tflite) / ONNX (.onnx) / scikit-learn 等
  • 最適化:量子化(int8)、Pruning、メモリ最適化(共有バッファ活用)
  • 対応 STM32 系列:F3 / F4 / F7 / G4 / H7 / L4 / L4+ / L5 / WB / WL(H5 / U5 は最新版で要確認)。N6 は NPU 経由でサポート
  • AI Validation:PC 上での精度比較(validate on desktop)+ 実機での推論時間・精度検証(validate on target)
  • 統合形態:CubeMX のソフトウェアパック / CubeIDE プラグイン / CLI(stm32ai / stedgeai

(出典: UM2526「Getting started with X-CUBE-AI Expansion Package」)

生成コードのファイル構成とメモリ 3 区分

X-CUBE-AI が CubeMX 経由で生成するファイルは典型的に以下の構成です。

X-CUBE-AI/App/
├── app_x-cube-ai.c / .h     // MX_X_CUBE_AI_Init / Process(ユーザが触る層)
├── network.c / .h           // 推論関数(ai_network_create / init / run)
├── network_data.c / .h      // 重みデータ(const 配列)と参照関数
├── network_config.h         // モデルメタデータ(テンソル形状等)
└── network_generate_report.txt  // メモリ・MAC 使用量レポート

覚えるべきは「Weights / Activations / I/O buffers」の 3 区分

X-CUBE-AI の世界では、モデルが消費するメモリは次の 3 つに分けられます。

区分内容デフォルト配置典型サイズ
Weights推論パラメータ(モデル重み)内蔵 Flash(const 配列)数十 KB ~ 数 MB
Activationsレイヤ間中間バッファ(推論中のみ使用)内蔵 RAM数 KB ~ 数百 KB
I/O buffers入力テンソル / 出力テンソル内蔵 RAM数百 B ~ 数十 KB
RAM 節約の定番テクニック

CubeMX の X-CUBE-AI 設定で "Use activation buffer for input/output" をオンにすると、I/O バッファを activations と兼用してくれます。これだけで RAM 使用量が数〜数十 KB 削減されることが多く、まず最初に試すべきオプションです。

メモリ階層と速度の関係(STM32H7 を例に)

STM32H7 系は、AI 用途で最もよく使われる MCU の一つです。多階層のメモリ構造を持ち、各層でアクセス速度が大きく異なります。(出典: AN4891「STM32H72x/H73x system architecture and performance」/ RM0433)

メモリアドレス典型サイズレイテンシ備考
ITCM0x0000000064 KB0 wait stateコア最近接、命令専用
DTCM0x20000000128 KB0 wait stateコア最近接、データ専用
AXI SRAM (RAM_D1)0x24000000512 KB数サイクルD-Cache 有効可
SRAM (RAM_D2)0x30000000288 KB数サイクル-
SRAM (RAM_D3)0x3800000064 KB数サイクル-
内蔵 Flash0x08000000最大 2 MBキャッシュ要64-128 bit バス幅
外部 OCTOSPI/QSPI(Memory-Mapped)0x900000008 MB ~大幅レイテンシ4-bit / 8-bit シリアル
内蔵 Flash と Quad-SPI Flash の帯域差は約 1 桁

内蔵 Flash は 64-128 bit バスで接続されているのに対し、Quad-SPI Flash は 4 bit シリアルです。OCTOSPI でも 8 bit。理論帯域差は約 8-16 倍あります。さらに Quad-SPI は SPI ベースなのでオーバーヘッドが大きく、実測では 10 MB/s 程度に収まる報告もあります(STM32H735 ユーザ実測)。これを Cache 有効化で何倍にも改善するのが本記事の主役テクニックです。

重み配置の 5 パターンとトレードオフ

X-CUBE-AI 公式が STM32H747I-DISCO の FoodReco サンプル等で示している、重み・活性化の配置パターンは大きく 5 つです。(出典: AI:How to run larger models on STM32H747I-DISCO wiki / UM2611)

パターンWeightsActivations特徴
① 標準内蔵 Flash内蔵 RAM最高速。サイズ限界が早い
② Ext_Qspi外部 QSPI内蔵 RAM大モデル可。推論は遅い
③ Split_Qspi内蔵 Flash + QSPI 分割内蔵 RAMホット層を内蔵、大層を外部
④ Ext_SdramQSPI外部 SDRAM大活性化対応
⑤ Split_Sdram起動時 QSPI→SDRAM コピーSDRAMWEIGHT_EXEC_EXTRAM=1。SDRAM から実行

選択ガイド

  • モデル < 内蔵 Flash 容量 - アプリ用領域:迷わず①
  • モデル数 MB、推論レイテンシ寛容:②
  • モデル数 MB、最初の数層は高速処理したい:③(最重要)
  • 大画像 ResNet 等で活性化バッファが内蔵 RAM を超える:④
  • QSPI 読出しでも遅い、SDRAM を持っている:⑤

リンカスクリプト書き換え実践

パターン② Ext_Qspi(重みを QSPI に配置)を例に、リンカスクリプトの書き換え手順を示します。STM32H750 を題材にした典型例です。(出典: AN5050「Getting started with OCTOSPI, HEXADECASPI and XSPI interface」/ ControllersTech 公開例)

Step 1:MEMORY ブロックに QSPI を追加

CubeIDE 生成の STM32H750xx_FLASH.ld(または同等ファイル)の MEMORY セクションに QSPI 領域を追加します。

MEMORY
{
  ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
  DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
  RAM_D1  (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
  RAM_D2  (xrw) : ORIGIN = 0x30000000, LENGTH = 288K
  RAM_D3  (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
  FLASH   (rx)  : ORIGIN = 0x08000000, LENGTH = 128K
  QSPI    (rx)  : ORIGIN = 0x90000000, LENGTH = 8M    /* ← 追加 */
}

Step 2:SECTIONS に重み専用セクションを追加

SECTIONS
{
  /* (既存の .isr_vector / .text / .rodata / .data / .bss 等は省略) */

  .nn_weights :
  {
    . = ALIGN(4);
    *(.nn_weights*)         /* このパターンに合致する入力セクションを集める */
    . = ALIGN(4);
  } > QSPI                  /* QSPI 領域に配置 */
}

Step 3:重み配列に section 属性を付ける(生成コードを編集しない方法)

X-CUBE-AI 公式は 「生成された network_data.c は編集しない」を推奨します。代わりに、CubeMX の X-CUBE-AI 設定で "Split weights using linker script" オプションを有効化すると、重みが .nn_weights* 系のセクション名を持って生成されるので、Step 2 のリンカ側で配置を指定するだけで済みます。(出典: X-CUBE-AI documentation)

手動で配置を指定する必要がある場合(例:別のラッパーから重みを参照する場合)は、ソース側で __attribute__((section(...))) を付ける方法もあります。

__attribute__((section(".nn_weights")))
const ai_u8 ai_network_data_weights[] = { /* 重みバイナリ */ };

Step 4:起動コードで XSPI Memory-Mapped Mode を main 冒頭に有効化

これが最も重要かつ落とし穴の多いステップです。XSPI Memory-Mapped Mode は main() の冒頭で有効化する必要があります。これより前に重みアクセスする初期化コード(C++ コンストラクタ、__libc_init_array() 内の初期化等)が走るとハードフォルトします。

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    /* ★ ここで XSPI を Memory-Mapped Mode に。重みアクセスの前に必須 */
    MX_OCTOSPI1_Init();
    BSP_QSPI_Init();
    BSP_QSPI_EnableMemoryMappedMode();

    /* 必要なら MPU + Cache 設定(次セクション) */
    MPU_Config();
    SCB_EnableICache();
    SCB_EnableDCache();

    /* ここから先で QSPI 上の重みを参照できる */
    MX_X_CUBE_AI_Init();

    while (1) {
        MX_X_CUBE_AI_Process();
    }
}

MPU + D-Cache 最適化

QSPI Memory-Mapped Mode はそのままでは遅いですが、MPU で Cacheable 領域として設定 + D-Cache 有効化することで、初回読込み後はキャッシュヒットで内蔵 SRAM 並の速度を実現できます。(出典: AN4839「Level 1 cache on STM32F7 / STM32H7」/ AN4838「Managing the MPU」)

MPU 設定の鉄則(QSPI / OCTOSPI 領域)

  • Cacheable + Bufferable + Not Shareable + XN=0 が定石
  • Cortex-M7 では、何も設定しないと QSPI 領域は Strongly Ordered として扱われ、投機読み (speculative read) でバスエラーが起きる事例あり → 必ず MPU で明示設定
  • Shareable に設定すると D-Cache が無効化される(F7/H7 系)。共有しない領域は Shareable = 0
  • 重みは Read-Only なので Write-Through / Write-Back の選択は影響しない。Read-allocate のみ重要

MPU 設定コード例(QSPI 領域 8MB を Cacheable に)

void MPU_Config(void)
{
    MPU_Region_InitTypeDef MPU_InitStruct = {0};
    HAL_MPU_Disable();

    /* QSPI 領域: 0x90000000, 8MB, Cacheable Normal Memory */
    MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    MPU_InitStruct.BaseAddress      = 0x90000000;
    MPU_InitStruct.Size             = MPU_REGION_SIZE_8MB;
    MPU_InitStruct.SubRegionDisable = 0x00;
    MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RO_URO; /* Read-Only */
    MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
    MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    HAL_MPU_ConfigRegion(&MPU_InitStruct);

    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

その後 SCB_EnableICache() / SCB_EnableDCache() を呼ぶ順序を守れば、Cache 効果で QSPI 重み読み出しが初回後は数倍速くなります

STM32U5 の DCACHE は分業構成

STM32U5 は DCACHE が 2 系統あり、DCACHE1 は外部 RAM(OCTOSPI / HSPI / FMC)専用、DCACHE2 は内部 RAM 用に分業しています。重みを外部メモリに置く設計では DCACHE1 の設定が重要です。(出典: AN5212「How to use STM32 cache to optimize performance」/ STM32U5 system cache training)

CubeMX / CubeIDE での実装ワークフロー

0 から実装を始める場合の標準ステップです。

  1. STM32CubeMX で対象 MCU を選択(H743 / H747 / U585 / N657 など)
  2. Software Packs → STMicroelectronics.X-CUBE-AI を Enable
  3. 左ペインの X-CUBE-AI セクションで "Add network" → モデルファイル(.h5 / .tflite / .onnx)を投入
  4. 設定:
    • Compression(1x / 4x / 8x)
    • Optimization(Time / Balanced / RAM)
    • Use activation buffer for input/output(RAM 節約)
    • Split weights using linker script(外部メモリ配置するなら必須)
  5. "Analyze" でメモリフットプリント・MAC 数を確認
  6. "Validate on Desktop / Target" で精度・推論時間を実測
  7. Project Manager → Code Generator → "Generate Code"
  8. main.c に自動追加された MX_X_CUBE_AI_Init()(初期化)と MX_X_CUBE_AI_Process()(推論ループ)を確認
  9. (外部メモリ配置する場合)リンカスクリプト編集 + main 冒頭で BSP_QSPI_Init / MemoryMappedMode 呼出し追加
  10. ビルド → 書き込み → 動作確認

最新動向:STM32N6 + Neural-ART NPU

2024年12月にリリースされた STM32N6 は、ST 史上初の 内蔵 NPU 搭載マイコンです。X-CUBE-AI / ST Edge AI Suite の今後の主軸となる品種です。

主な仕様

  • CPU:Arm Cortex-M55 @ 800 MHz(Helium SIMD 拡張搭載)
  • NPU:ST 自社開発 Neural-ART Accelerator @ 1 GHz、最大 600 GOPS(電力効率は ST 公称で 3 TOPS/W 級。具体値は最新の製品資料を参照)
  • 内蔵 RAM:4.2 MB の連続 embedded RAM(STM32 史上最大)
  • 内蔵 Flash なし:外部 OCTOSPI / HSPI / FMC からブート前提
  • NeoChrom GPU、H.264 エンコーダ、JPEG、MIPI CSI-2 + ISP も内蔵

(出典: ST blog stm32n6 / STM32N6 Series page)

X-CUBE-AI v10 連携時の特殊事情

NPU 利用時、X-CUBE-AI は [modelname]_atonbuf.AXISRAM5.raw という extra raw ファイルを生成します。これは NPU からアクセス可能なメモリに実行時にロードする必要があり、リンカスクリプトでの配置だけでなく起動時ローダコードの記述も必要です。(出典: ST Community td-p/813915)

2026 年現在、CubeMX が N6 を完全にサポートできていない事例も報告されており(生成時エラー、メモリ未活性化など)、量産案件で採用するなら ST のサポートエンジニアと密に連携することを強く推奨します。

公式リソース・参考文献

最重要 Application Note / User Manual

Reference Manual / Datasheet

  • RM0433 – STM32H743 Reference Manual
  • AN4891 – STM32H72x/H73x/H74x/H75x system architecture and performance
  • AN5872 – Introduction to the system architecture and performance in STM32H5 MCUs

ベンチマーク / モデル Zoo

関連製品ページ

まとめ

この記事のまとめ

  • STM32Cube.AI (X-CUBE-AI) は Keras / TFLite / ONNX を STM32 用 C コードに変換する公式ツール。2026 年は STM32Cube AI Studio 移行期
  • メモリ消費は Weights / Activations / I/O buffers の 3 区分で把握。"Use activation buffer for input/output" でまず RAM 節約
  • 内蔵 Flash と外部 QSPI Flash の帯域差は約 1 桁。MPU + D-Cache 最適化で実用速度に
  • 重み配置の主要 5 パターン:標準 / Ext_Qspi / Split_Qspi / Ext_Sdram / Split_Sdram。Split_Qspi が大モデル × レイテンシ要件の現実解
  • リンカスクリプトに QSPI MEMORY 追加 → .nn_weights セクションを QSPI に配置 + main 冒頭で BSP_QSPI Memory-Mapped Mode 有効化 が定石
  • MPU 設定は Cacheable + Bufferable + Not Shareable + XN=0。Cortex-M7 で Strongly Ordered のまま放置すると投機読みでクラッシュ
  • STM32N6 + Neural-ART NPU は次世代の本命。CubeMX のサポート成熟度はまだ過渡期

STM32 を使った組込み AI 推論や TinyML 量産設計でお困りのことがあれば、弊社にお気軽にご相談ください。画像認識・AI 案件の実績をもとに、モデル選定から MCU 選定・メモリ配置最適化・量産品質まで一貫してサポートします。

STM32 + TinyML / エッジ AI 推論の PoC、モデル軽量化、量産品質の確保まで 組込み制御・マイコン開発 として対応しています。

/この内容の受託開発・PoC相談はこちら\

STM32 + TinyML / エッジ AI の受託開発・PoC

STM32Cube.AI / X-CUBE-AI を活用した予知保全・異常検知・キーワード認識・画像認識など、組込みエッジ AI の試作 PoC からモデル軽量化・量産品質確認まで一貫して対応します。

次に読む|STM32 シリーズ記事