前回までの初心者講座を通してマルチコアアーキテクチャの基礎を理解いただけたと思います。今回は、実際の製品開発に欠かすことのできない「マルチコアとサブコアをシームレスに(コアの違いを意識することなく自然に)解析する」方法を紹介いたします。
サンプルアプリケーションとして、メインコアとサブコアを連携させるための同期プリミティブを繋ぎ合わせたシンプルなC/C++ソースコードを準備しました(後述)。
また、実践的なデバッグをすぐに体験いただけるよう、本記事ではASMPアーキテクチャとしてCortex-M4x6コアを搭載しているSPRESENSE™を活用。安価なJTAG-ICEデバッガと、無償の開発環境を利用して、コア間をシームレスにデバッグする様子や方法を動画にて紹介いたします。特別な作業なく簡単に使い始めることができるため、はじめてのマルチコアプログラミングに挑戦される方も、是非お手元でお試しください。
なお、今回紹介するメインコア/サブコアのデバッグにはSPRESENSE SDK v1.5.0(2019/12/20リリース)以降をベースとしたプロジェクトと開発環境が必要となります(理由についてはMakefileの節にて説明いたします)。
ASMP対応のビルド環境(Makefile)
ASMP上で動作するプログラムのデバッグを始める前に、プログラムがどのようにビルドされているかの手順を解説いたします。ビルド環境を理解することにより、デバッグ対象の実行プログラムがどのように生成され、どういったデバッグ情報を必要としているのかを知ることができます。デバッグに手間取った場合や、他環境で開発した経験をSPRESENSEの開発に活かす際の助けになるでしょう。
SPRESENSE SDKのビルド環境
SPRESENSE SDKでは、プロジェクトに含まれたソースコードから実行ファイルを生成するためのビルド作業に必要な操作を「Makefile」に定義しています。v1.4.0からv1.5.0へのアップデートにより、全Makefile(各アプリケーションそれぞれをビルドするルール)から共通となるステートメントを切り出し。「.vscode」フォルダーに共通部を集約することで、プロジェクト全体のMakefileを簡略化、シンプルなMakefile(ビルドルールの表現)を実現しています。
メインコア向けプログラムをビルドするための共通手順は「.vscode/application.mk」に、サブコア向けプログラムをビルドするための共通手順は「.vscode/worker.mk」に一本化されており、共通処理はアプリケーションごとのMakefileから「inlude」ステートメントにより参照されています(図1-1)。
参考として、SPRESENSE SDK v1.4.0以前のビルド環境を図1-2に示します。
C++(.cxx/.cpp)を使って開発する場合
SPRESENSE SDKのapplication.mk(メインコア用の共通ビルド手順)は、アプリケーションのエントリポイント「プロジェクト名_main」関数がC言語のソースコードファイル(.c)に含まれるものとして設計されています。( application.mk#L68)。
ifeq ($(MAINSRC),) MAINSRC = $(APP_FOLDER_NAME)_main.c endif ASRCS += CSRCS += $(filter-out $(MAINSRC),$(wildcard *.c) $(wildcard */*.c)) CXXSRCS += $(wildcard *.cpp) $(wildcard */*.cpp) $(wildcard *.cxx) $(wildcard */*.cxx)
そのため、C++言語「.cxx/.cpp」のプログラムを混在させる場合は、エントリポイントのみC言語のソースコードで実装し、そこからC++のエントリポイントを呼び出す構造とすることが良いでしょう。実行時に1回の関数呼び出しコストが発生しますが、Makefileやapplication.mkを変更せずに、C/C++が混在したアプリケーションを開発することができます(図2)。
デバッグ情報の生成
ASMPのサブコア(CPU#1〜#5まで)をデバッグするためには、サブコア上で動作する実行ファイル(ELF形式)に加えて、同名で拡張子が「*.debug」のデバッグ情報ファイルが必要となります。SPRESENSE SDK v1.5.0はデバッグ時に(JTAG-ICEにより操作の際に)、「*.debug」を参照し、サブコア上で実行中の関数名、コールスタックの内容、スコープ内の変数、それぞれのデータが格納されているメモリアドレスを特定。メインコア/サブコアの違いを感じさせることなく、実行中のC/C++言語をスムーズに追いかけることのできます。(図3)。
SPRESENSE SDK v1.5.0のサブコア用アプリケーション自動生成機能は、Makefileにworker.mkをインクルードするステートメントが含まれており(図3:inclueステートメント)、worker.mkにはデバッグ情報ファイルを生成するためのルール( worker.mk#L15)が定義されています。これにより、ビルドするだけで「デバッグ情報ファイル(*.debug)」を自動的に生成・更新することができます(SPRESENSE SDK v1.4.0以前のMakefileには、.debugをビルドするルールがないためサブコアのデバッグはできません)。
... BIN = $(OUTDIR)/$(WORKER_NAME) DBG = $(APPDIR)/$(WORKER_FOLDER_NAME)/$(WORKER_NAME).debug ...
なお、サブコアをデバッグする場合は、メインコアがサブコア上に実行するプログラムを展開した後(図4の②)、デバッグ情報ファイルを適用してください(図4の③:手順は後述)。
デバッグの準備
それでは、簡単でシームレスにマルチコアの状態を追いかけることのできる開発環境を構築して、利用してみましょう。
必要な機材
今回のデバッグ作業には、JTAG-ICEデバッガ(実機の内部状態を観測・制御することのできるデバッグ用ハードウェア)が必要となります。プログラムを実行するSPRESENSE Main Boardに加えて、 JTAG-ICEデバッガの接続ポートを備えた「SPRESENSE Extension Board」もしくは「SPRESENSE LTE Board(2019年12月20日発売)」をご用意ください。また、今回はJTAG-ICEデバッガとして「NXP LPC-Link2」を利用しました(詳細は後述の環境構築手順をご参照ください)。
ソースコードの入手
デバッグ対象となるサンプル・ソースコードは「 APS-Academy(Multicore) #9 Sample Code」として公開しております。下記の手順に従ってソースコード一式をPCにダウンロードしてください。本記事ではJTAG-ICEデバッガ「NXP LPC-Link2」の設定方法も紹介しています。
【APS-WEB】初心者講座マルチコア編のWindows開発環境、設定手順のまとめ
# SPRESENSEのgitのリリースリストが表示されます $ git tag -l v1.0.0 v1.0.1 ... v1.5.0.is.1.0 # ソースコードから"1.5.0.is.1.0"という名前のブランチを生成します $ git checkout -b 1.5.0.is.1.0 refs/tags/v1.5.0.is.1.0 Switched to a new branch '1.5.0.is.1.0' # このように切り替わっています $ git branch * 1.5.0.is.1.0 master # 1.5.0.is.1.0の初期状態にリセットします $ git reset --hard HEAD
ASMPの全コアを同時にデバッグする
今回は、上記の手順により入手できるサンプルアプリケーション「aps_template_asmp(メインコア用プログラム)」と「aps_template_asmp_worker(サブコア用プログラム)」を利用し、デバッグ方法を紹介いたします。
サンプルアプリケーションの動き
サンプルアプリケーションの動作は非常にシンプルです(図7)。本アプリケーションは、メインコア上で起動した後、メインコアがaps_template_asmp ELF実行ファイルを使ってサブコアを起動。メインコアとサブコアを繋ぐメッセージキューにより、メインコアがサブコアへ処理を依頼。サブコアは依頼内容に従って決められた処理を実行し、メインコアに完了通知を発行します。メインコアは、サブコアへ10回処理要求を発行した後、サブコアへ終了要求を発行します。最後に終了要求を受け取ったサブコアが自発的に終了、アプリケーションが停止します。
イベントドリブン/メッセージドリブン設計を実開発へ応用する
今回、デバッグ対象として扱ったプログラムは非常にシンプルですが、このような「イベントドリブン」「メッセージドリブン」型の実装は、世界中ありとあらゆるアプリケーションに採用されています。今回のプログラムに、要求のバリエーションを追加し、メッセージを受け取った際の処理をリッチにすることにより、様々なサービスを実現することができます。
例えば、対話的に操作できるWindowsアプリケーションは「クリックされた」「特定のキーが押された」というイベント(メッセージ)を契機に、適切なリアクションを実行しています。また、WEBサーバーもクライアントからの要求(メッセージ)に応じてコンテンツを生成し返答することにより、レスポンシブルで高機能なサービスを提供しています。
マルチコアをシームレスにデバッグする
すでに様々な組み込み開発を体験されている方にとっては、ASMP上のアーキテクチャをデバッグする手順を難しく感じるかもしれません。しかし、上記の動画を通して要点を抑えることで、SMPアーキテクチャやシングルコアアーキテクチャ(※)よりも簡単にデバッグできることに気付くと思います。是非お手元でお試しください。
SPRESENSEのデバッグは、大きく分けて5つの手順により行います。
- 前準備:ソースコードのビルド、構成ファイルを更新する
- メインコアとサブコアが最初に連携する箇所にブレークポイントを設定する
- メインコアのデバッグを開始する
- サブコアにデバッガをアタッチする
- メインコアとサブコアを同時にデバッグする
前準備:ソースコードのビルド、構成ファイルを更新する
上記の環境構築手順に従ってGitHubからソースコードを入手ください。ソースコードを入手し、Visual Studio Codeでワークスペースを開いた後、図8に示す①〜⑤の手順でデバッグ・実行の準備が整います。
- Visual Studio Codeの画面右に表示されている「デバッグ」アイコンをクリックする
- 左上のプルダウンから「Main Core(sandbox00)」を選択する
- プルダウン右の歯車マーク(設定ボタン)をクリックし、構成ファイルを開きます
- 画面右下の「構成の追加」からSubCore#1に関する設定を追加します
- ファイル構造にあわせて、構成にデバッグ対象の情報を追記します
本記事で利用しているデバッグ構成ファイル(launch.json)の内容
ブレークポイントを設定する
次に、ブレークポイントを設定します。マルチコアとサブコアの双方をデバッグするために「 タスク生成処理|ret = pwc->execTask();」の直後にブレークポイントを設定します(図9)。
メインコアのデバッグを開始する
続いて、メインコアのデバッグ操作を開始します。デバッグが開始されると、まずRTOS「NuttX」のエントリポイントである「__start」で実行が停止します。再開ボタンを押すことにより、NuttXが開始され、プロンプトであるNuttShellが起動、操作できる状態となります。NuttShellに「aps_template_asmp
」と入力しEnterキーを押下するとアプリケーションが開始され、前手順で設定していたサブコア起動直後の位置でプログラムが一時停止します。
サブコアへデバッガを接続する
メインコアが一時停止している状態で、①画面左上のプルダウンから「Sub Core 1(sandbox001)」を選択、緑色の再生マークをクリックしデバッグを開始します。サブコアのデバッグが開始すると、操作ウィンドウの横に(図11-②)各コアのプルダウンメニューが表示され、各コアを自由に操作できるようになります。
最後に、メインコアとサブコアを画面上の操作ボタンから再開(青色の再生ボタン)し、全コアのデバッグを開始します。これにより、図12の流れでマルチコア/サブコアを意識することなく動作中の命令をデバッグ・解析・検査することができます。
このように、Visual Studio CodeとSPRESENSE SDKを活用することにより、ASMPやマルチコアといった複雑なシステム開発であったとしても、すべてのプログラムの動作を精密に分析、効率的に不具合箇所の解析や、プログラムのテストを実施可能です。是非ご活用ください。
まとめ
新しいCPUアーキテクチャを次期製品開発に取り入れる場合、開発環境の導入方法や、デバッグ効率の検証は、その後の工数(開発効率)に大きく影響する重要な課題です。SPRESENSE SDK v1.5.0の提供するマルチコアをシームレスにデバッグできるGUIベースのデバッグ環境は、みなさまのマルチコア・プログラミングの開発効率を大きく改善してくれることでしょう。
是非ご活用ください。
SPRESENSE SDK v1.5.0アップデートによる改善点
開発環境がアップデートされたとしても「これまでの開発してきた資産や、追加の評価工数への懸念」などにより、なかなか移行に踏み切れない点もソフトウェア開発の難しさのひとつです。SPRESENSE SDKでは、2019/12/18にv1.5.0が公開され、v1.4.0の提供が終了となりました。今回の記事の補足として、マルチコア・プログラミングを学習している、または実際の開発に採用されているエンジニアの皆様への効果・影響の概略をまとめます。詳細はGitHubのリリースページをご参照ください。
SPRESENSE SDK v1.5.0のリリース情報|GitHub
アプリケーション生成ウィザードの操作性改善
Visual Studio Code上で実行できる「アプリケーションの生成機能」がウィザード形式(対話式)になり、使いやすくなっています。同じメニューから、メインコア専用プログラムの生成、またはメインコアとサブコアを連携させるプログラムの生成が可能となりました。
Makefileの変更
v1.5.0では、ビルドルールの共通処理を.vscodeフォルダにまとめ、アプリケーションごとのMakefileはincludeステートメントのみで完結していることから、簡単にアプリケーションのビルドルールを書き換えられるようになりました。ただし、共通部分を書き換えたい場合、.vscode内のルールを書き換えてしまうと全アプリケーションのビルドに影響が発生するため、v1.4.0のMakefileを参考に対象のアプリケーションに個別で独立したMakefileを準備することをオススメします。アプリケーションの開発効率や、システム全体のメンテナンスのしやすさ、今後のアップデートを見据えた上で、自身で管理しやすいビルド環境を選択してください。
SONY SPRESENSE
SPRESENSEは、Arm Cortex-M4コア(FPU機能搭載)を6コア搭載したシングルボードコンピュータです。マルチコアによる豊富な演算能力をはじめ、魅力的なペリフェラルを多数搭載しながら、電池のみでも駆動できる超低消費電力な製品です。本格的なエッジコンピューティングを是非ご体験ください。システムの試作はもちろん、PoC、製品化にもご活用いただけます。
開発者向けサイトを見る Switch-Scienceで購入する
APS学習ボード(SPRESENSE™ Extension Board用)
APS学習ボード(SPRESENSE™ Extension Board用)は、初心者講座の内容をはじめ、SPRESENSE SDKの提供するオーディオ入力機能やLCDドライバをはじめとする各種機能を、回路設計をすることなく簡単にお試しいただけるよう開発したAPSオリジナルの評価基板です。Web記事と併せてお楽しみください。
取扱説明書|APS学習ボード Switch-Scienceで購入する(ボード単体) Switch-Scienceで購入する(部品キット)
こちらも是非
“もっと見る” マルチコア|SPRESENSE編
SPRESENSE×Neural Network Console:第4回|推論モデルを最適化し、エッジAIによるオリジナルの音声識別システムを構築する
今回の初心者講座では、SPRESENSEの「ハイレゾオーディオ入力」と「DNNRT機能」により「Neural Network Console」で生成したディープニューラルネットワーク(DNN)の推論モデルを統合。エッジ単体で完結するオリジナルの音声識別システムを構築する技法を解説いたします。
SPRESENSE×Neural Network Console:第3回|オーディオ解析に必要な学習用データを採取し、PC上で学習・推論を実行する
今回の初心者講座では、SPRESENSEに搭載されたハイレゾオーディオ入力を活用し、環境音を録音し、ディープニューラルネットワークによる音声分類に不可欠な学習用データと検証用データを生成する方法について解説します。また、PC上で動作するNeural Network Consoleによって生成した推論モデルをエッジ・デバイスへ統合するために解決すべき課題を紹介します。
SPRESENSE×Neural Network Console:第2回|異常検知に活用できるニューラルネットワークで波形の扱い方を学ぶ
SPRESENSEのDNNRT機能が扱うことのできるデータは画像だけでなく、産業分野を中心に人気が高まっている「異常検知・故障予知」に活用できる加速度センサーや大気圧センサーなどから収集した波形データも解析することができます。さらにSPRESENSEに内蔵されたハイレゾオーディオ録音機能も周辺環境を可聴域の波形データとして記録することができる優れたセンサーとして利用可能です。そこで、今回の初心者講座では、まず簡単な波形データの解析方法を例に、DNNRT機能から波形データを扱うシステムの構築方法について解説。DNNRT機能を活用した製品開発に必要となる技術を紹介いたします。