📑

STM32MP157を使用したCM4側アプリの開発

に公開

STM32MP157を使用したCM4側アプリの開発

1. はじめに

近年の組み込み機器のプロトタイピングでは、高い処理性能とリアルタイム性を両立できるプラットフォームが求められます。Edge AIなどのアプリケーションでは、画像処理などの大規模計算処理を実行しながら、モータ制御などのIO制御を同時に行う必要があります。

STM32MP157では、Linuxを動かす二つのARM® Cortex®-A7コア(CAコア)と、RTOSを動作可能なARM® Cortex®-M4コア(CM4コア)を一枚のチップに統合されています。Linux側で複雑なネットワーク処理やファイル操作、大規模計算処理をまかせつつ、CM4側で厳密なタイミング制御や高速なI/O処理を実現できる、まさにハイブリッド型組み込み機器開発に最適な環境です。

本記事では、そんなSTM32MP157の“もう片方の主役”であるCM4コアにフォーカス。STM32MP157を搭載した、STM公式の開発者ボードであるSTM32MP157F-DK2の立ち上げからCM4側アプリを動かす一連の手順を解説します。

なおLinux側アプリ開発については、ST公式ドキュメントやYoctoプロジェクトの豊富なチュートリアルが既に多数存在するため、本記事ではあえて割愛。CM4側リアルタイム制御領域に集中し、読者の皆さんが最短で「Hello, CM4」を動かせるようガイドします。

1.1 STM32MP157の特徴と用途

STM32MP157は、STMicroelectronics製のMPUシリーズのヘテロジニアスマルチコアモデルです。

  • デュアルARM® Cortex®-A7(最大 800MHz)+ARM® Cortex®-M4(最大 209MHz)を同一チップに統合
  • 1GB DDR3L RAM、最大16GB eMMC、microSDスロットで柔軟なストレージ構成
  • Ethernet、USB(Host/OTG)、HDMI、MIPI-CSI/DSI、SPI/I²C/UARTなど豊富なI/Oをオンボードでサポート
  • PMIC内蔵によるシンプルな電源設計と拡張用Arduino互換コネクタ

これらのハードウェアスペックにより、

  • Cortex-A7上でLinuxを走らせ、ネットワークやGUI、データベースなど“重め”の処理を一手に担いつつ、
  • Cortex-M4(CM4)で厳密なタイミングが要求されるリアルタイム制御(モーター駆動、センサ取得、PWM生成など)を同時実行

といったハイブリッド制御が可能です。産業オートメーション、ロボティクス、IoTエッジデバイス、マルチメディアHMIなど、要求性能と制御性を両立したプロトタイピングに最適なプラットフォームと言えます。

1.2 STM32MP157 と Raspberry Pi 5 の比較

項目 STM32MP157F-DK2(STM32MP157) Raspberry Pi 5 (BCM2712)
アプリケーションプロセッサ Dual-core ARM Cortex-A7 @ 800MHz Quad-core ARM Cortex-A76 @ 2.4GHz
リアルタイム性 Cortex-M4によりRT制御に強い 標準Linux上の制御(RT性は限定的)
GPU Vivante GC320 VideoCore VII
RAM 最大 1GB DDR3L 最大 16GB LPDDR4X
ストレージ microSD / eMMC microSD / PCIe対応SSD(拡張可)
映像出力 HDMI 1.4 2× micro HDMI
USB USB 2.0 Host ×2、USB OTG ×1 USB 3.0 ×2、USB 2.0 ×2
ネットワーク 10/100 Ethernet Gigabit Ethernet、Wi-Fi 802.11ac、BT5.0
GPIO Arduino/Raspberry pi 互換ヘッダあり 40ピン GPIO ヘッダ
ソフトウェアエコシステム Yocto / OpenSTLinux / STM32Cube Raspberry Pi OS / Debian系豊富な環境
デバッグ性 ST-LINK によるSWD/JTAG JTAG利用には別途ハードウェアが必要
価格(目安) 約 ¥12,000〜¥15,000 約 ¥10,000(4GB版)、¥13,000(8GB版)
主な用途 産業用制御、RTシステム、ハイブリッド開発 教育、DIYプロジェクト、マルチメディア処理

1.3 CM4側アプリを動かすメリット

STM32MP157のCM4コアを活用すると、以下のような大きな利点が得られます。

  • 真のリアルタイム性
    Linuxが走るCA7とは独立したコアなので、OSのスケジューラや割り込みによる遅延を気にせず、µsオーダーの厳密なタイミング制御が可能です。

  • 負荷分散による性能向上
    GUI表示やファイルI/O、ネットワーク処理といった“重い”タスクをCA7コアに任せつつ、センサ取得やモーター制御といったリアルタイムタスクはCM4へオフロード。両コアが得意分野に集中できるため、システム全体のスループットと応答性を最大化できます。

  • 省電力/高速起動
    軽量RTOSやベアメタルで動作させればCM4だけをウェイクアップ・スリープ制御できるため、A7を常時動かすより大幅な省電力運用が可能。起動時間も数ms~数十msと短縮できます。

  • 開発/デバッグの切り分け
    CM4はベアメタル/RTOS向けのデバッグツール(ST-LINK、JTAG)がそのまま使えるため、A7上のLinuxに影響を与えずにステップ実行やレジスタ確認ができ、問題切り分けが容易です。

これらのメリットにより、産業用制御、ドローンやロボットのモーター駆動、精密センサーデータ取得など、リアルタイム性が要求されるアプリケーションを安心して開発できます。本書ではこの「リアルタイム制御特化領域」を最短で動かす方法にフォーカスしていきます。

2. 前提条件・準備物

本記事では Yocto を使った環境構築は行わず、ST 公式の Starter Packageを利用してボードを立ち上げます。

2.1 ホストPC環境

本記事での立ち上げでは、ボードへの書き込みとCM4側アプリケーションのbuildを行うだけであるため、PCスペックとしては下記のような最新の一般的なビジネスPCで十分です。

  • OS:Windows 7/10/11(64bit)
  • CPU:4コア以上
  • メモリ:8GB以上
  • ディスク空き容量:20GB以上(Starter Package のダウンロード・解凍用)
  • USB ポート ×2(ST-LINK 接続用+シリアルログ用)

2.2 必要なソフトウェア

  • STM32CubeIDE(最新バージョン)
  • STM32CubeProgrammer(最新バージョン)
    ・ST-LINK ドライバを含む
  • 7-Zip などのアーカイバ(Starter Package 解凍用)

2.3 必要なハードウェア

  • STM32MP157F-DK2 ボード
  • microSD カード(2GB 以上)
  • 電源アダプタ(5V/3A)
  • USB ケーブル(micro-USB:PC ⇔ ボードの ST-LINK)
  • (オプション)シリアルターミナル用 USB-UART ケーブル
  • Ethernet ケーブル
  • ルーター(ボードのIPアドレスを割り当てることのできるDHCPサーバ)

3. ボードセットアップ

本手順は下記公式のwikiサイトの内容を参考にしています。
https://wiki.st.com/stm32mpu/wiki/Getting_started/STM32MP1_boards/STM32MP157x-DK2/Let's_start/Populate_the_target_and_boot_the_image

3.1 STM32MP1 OpenSTLinux Starter Package のダウンロードと解凍

まず初めに、ボードを起動させるための一連のソフトウェアをダウンロードします。これは、「STM32MP1 OpenSTLinux Starter Package」にまとめてST公式から提供されています。

このStarter Packageには次のファイルが含まれています。

  • ROM code binaly
    CPUが起動したときに最初に読み込むソフトウェアで、クロックの初期化などの最小限の基本的な初期化を行い、FSBLを呼び出します。
  • First stage bootloader(FSBL) binaly
     ROM codeに引き続き、クロックの初期化や外部RAMの初期化などを行い、SSBLを呼び出します。
  • Second-stage bootloader(SSBL) = U-Boot binaly
    USB,Ethernet他デバイスを使用して、Linuxカーネルを柔軟に読み込み、Linuxカーネルを起動します。
    Start PackageではU-Bootが使用されています。
  • Linux kernel binaly
    STM32MP157で使用するためのBSPを含んだLinux kernelです。
  • 各種ファイルシステム
    rootfs,bootfsなどLinuxシステムを使用するためのデモンストレーションを含めたファイルシステム。
  • ボードに書き込むためのスクリプト
    STM32CubeProgrammerを使用してボードに上記張りなりを書き込むためのスクリプトファイル。

https://wiki.st.com/stm32mpu/wiki/Boot_chain_overview

3.2 STM32MP157F-DK2ボードとPCの接続と書き込み準備

下記の手順に従いボードの準備を行います。

  1. SDカードの挿入
    基板裏側のSDカードスロットに2GB以上のSDカードを挿入します。
  2. PCとボードをUSBで接続する
    CN7のUSB-CコネクタとPCをUSBケーブルで接続する。
  3. SW1スイッチを切り替える
  4. 電源を投入する


3.3 STM32CubeProgrammerによるプログラムの書き込み

  1. STM32CubeProgrammerの起動とボードとの接続
    STM32CubeProgrammerを起動し、画面右側の接続方式をUSBに変更の上Connectボタンをクリックします。
    Portが「No DFU detected」となっている場合には、PCとの接続を確認の上、右側にある再スキャンのボタンを押してください。
  2. 書き込みスクリプトの選択
    「+」マークをクリックして「Open file」を選択し、Starter Package内の
    stm32mp1-openstlinux-6.6-yocto-scarthgap-mpu-v24.11.06\images\stm32mp1\flashlayout_st-image-weston\optee\FlashLayout_sdcard_stm32mp157f-dk2-optee.tsv
    を選択します。

  3. Binaries pathの指定
    画面中央の「Binaries path」にStart Package内のstm32mp1-openstlinux-6.6-yocto-scarthgap-mpu-v24.11.06\images\stm32mp1を指定する。
  4. 書き込みの実行
    Downloadボタンをクリックし、ボードに書き込みをおこないます。
  5. 書き込み後の確認
    プログラム書き込み完了後に、正しく動くか確認をするために、CN11をPCと接続します。

    接続し電源を投入後に、STM32CubeIDEの画面上部のリボンから「Open Concole on MPU serial device」をクリックし、下部Console画面から「ST OpenSTLinux xxxx」のメッセージが出ていることを確認する。

4. CM4 アプリ開発の基本フロー

4.1 前提知識: remoteproc

OpenSTLinuxの設計では、CM4側のアプリケーションはCA7側から起動を行うように設定されています(おそらく変更可能)。
このCM4のアプリケーションを起動するタイミングは下記の二つがあります。

LinuxからCM4のアプリケーションを起動するにはLinuxカーネルに組み込まれているremoteproc frameworkを使用して実行します。
このフレームワークにより、Linuxカーネルの立ち上げ時、もしくはユーザ空間(ユーザアプリケーション)からCM4側ファームウェアを指定して実行することが可能です。

STM32CubeIDEではCubeIDEがボード上のLinuxとSSHで接続し、CM4側のファームウェアを転送、Linux側にコマンドを送信してCM4側のアプリケーションを起動するという変則的なデバッグを行えるようになっています。

4.2 STM32CubeIDEのプロジェクト作成

CM4側アプリケーションのプロジェクトを作成します。
プロジェクトはSTM32CubeIDE(CubeMX)を使用して作成することができます。
今回は、STM32MP157F-DK2を使用するため、Board Selectorから「STM32MP157F-DK2」を選択して、ボードに接続されているものについてはあらかじめ設定されたプロジェクトファイルを生成します。

4.3 プログラムの作成

今回サンプルアプリケーションとしてPA12のトグルアプリケーションを作成します。

  1. CubeMX画面からPA12をGPIO_Outputにアサイン
  2. PA12をCM4側からのみ制御できるように設定
  3. トグルプログラムの作成
    .iocファイルを保存し、コードを生成すると<project name>/Core/Src/main.cが生成されます。

    main.cのwhile(1)以下に次のコードを挿入します。
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_12);

4.4 プログラムの実行

STM32CubeIDEのdebug機能を使用してプログラムの実行を行います。

5. まとめと応用

5.1 周辺機能への展開ヒント

  1. Linux側Device Treeの生成
    今回の記事では対象外としていますが、CAとCMで同一のハードウェアを扱うことはできないため、これらは排他的に処理する必要があります。CubeMXではTIMはSPIなどのハードウェアリソースはどちらのコアから使用するかを選択することができ、この設定に伴って、CA側にはDevice Treeの生成、CM側にはインスタンスの生成をして排他的に処理できるようになっています。
    このため、.iocファイルを生成・更新した場合には常にLinuxのdtbファイルを更新して実行する必要があります。
    今回はGPIOだけだったので、その手順はスキップしました。

5.2 Linux側とのデータ連携方法

今回の記事では、CA側はほとんど触らずCMだけのアプリケーションを作成しましたが、実ユースケースではこれらは同期してしようされます。
この同期には、rpmsgというフレームワークを使用することができます。rpmsgはLinux側はremoteproc framework内に、CM側はOpenAMPの中に含まれており、CAとCMで共有されているメモリを介し効率よくデータを共有できるようになっています。

6. 参考

https://wiki.st.com/stm32mpu/wiki/Main_Page
https://wiki.st.com/stm32mpu/wiki/STM32MP15_Discovery_kits_-_Starter_Package

Discussion