はじめに

この記事は、Spresenseボードで音響信号処理を試してみたいが、サンプルコードがエラーで動かず困っているメイカー/電子工作初心者を対象にしています。
「LowPassSound」スケッチをArduino IDEから書き込んでもシリアルモニタに mptask_exec() failure. -12 が出て、期待通りのローパスフィルタ音が聞こえない……という現象に直面した方に、エラーの意味と回避策を最短で理解してもらうための記事です。
本記事を読めば、Spresense専用のMP(多核)タスクが起動失敗する理由と、自分の環境で動作するバージョンの選び方・書き換えポイントがすぐにわかります。

前提知識

  • Arduino IDE 2.x の基本的な使い方(ボード選択・ライブラリ追加・シリアルモニタ)
  • Spresense SDK 3.0.0 以降をボードマネージャでインストール済みであること
  • ローパスフィルタの概念をぼんやりと知っている(数学は不要)

SpresenseマルチコアとLowPassSoundサンプルの概要

SpresenseはCXD5602というARM® Cortex-M4を7コア搭載した異例のマイコンボードです。Arduino IDE向けに提供されている「スケッチ」は、通常の1コア(主にARM0)で動くだけでなく、残り6コアをアプリケーション用に起動できる「MP(Multi-Process)タスク」仕組みを内包しています。
LowPassSoundサンプルは、マイク入力→ARM0でPCM取得→ARM1で32-tap FIRローパス処理→I2S出力、というパイプラインを組み、リアルタイムに音を加工して聴かせるデモです。
この「ARM1で動くフィルタ処理」がMPタスクとして動くため、起動に失敗すると mptask_exec() failure. -12 がスピーカー鳴るより先に表示され、以降一切音が出ません。

エラーを再現して、なぜ起きるかを追う

ステップ1 問題のサンプルを開く

  1. Arduino IDEを起動
  2. メニュー「ファイル」→「スケッチ例」→「SignalProcessing」→「LowPassSound」選択
  3. スケッチが開いたら、ツール→ボード→Spresense Boardを選択して書き込み
  4. 書き込み後、シリアルモニタ(115200 bps)を開く

ほぼ100%の確率で以下が表示される:

LowPassSound example
mptask_exec() failure. -12

ステップ2 エラーコード-12の意味を調べる

Spresense Arduino Coreのソースを見ると、mptask_exec() の戻り値はNuttx(Spresense内部OS)のエラーコードをそのまま返しており、-12-ENOMEM つまり「メモリ確保失敗」を示します。
要するに「ARM1用にフィルタタスクを配置するメモリ(特にDDR領域)が足りない」ということです。
原因は主に3つ:

  1. 静的メモリ確保が大きすぎる(FIR係数バッファ512×4バイト×32タップで64 kB近く)
  2. Arduino IDE 2.xでビルド時に最適化レベル-Osが効かず、バイナリが膨張
  3. ボードマネージャで「Spresense SDK 3.1.0」以降を使うと、Bootloaderが予約メモリを増やしたため、ユーザー領域が減った

ハマりどころ

  • 公式Wikiには「メモリ不足なら-Xmxオプションを……」とあるが、それはPC側の話でマイコン側ではない
  • サンプルコードのarm1_main()内でstatic float coef[512]と宣言しているが、ARM1のスタティック領域(32 kB程度)を超えている
  • メモリ不足を知らせるだけで、自動的にARM0にフォールバックしない(設計仕様)

解決策

解決策1 バッファを動的確保&縮小

LowPassSound.inoのarm1_main.cppを以下のように書き換える:

Cpp
#define TAPS 32 #define FRAME 128 // 64→128に減らす static float *coef; // スタティック確保を廃止 void setup_arm1(){ coef = (float *)malloc(TAPS * sizeof(float)); if(!coef){ Serial.println("malloc failed"); return; } calc_lpf_coef(coef, TAPS, 0.25f); // カットオフ0.25×Fs/2 }

メモリ使用量は2 kBに収まり、-ENOMEMは出なくなる。

解決策2 SDKバージョンを3.0.2に固定

ボードマネージャで:

  1. 「追加のボードマネージャURL」に
    https://raw.githubusercontent.com/sonydevworld/spresense-arduino-compatible/master/package_spresense_index.json を追加済みであることを確認
  2. ツール→ボード→ボードマネージャ→「Spresense」でバージョン「3.0.2」を選択してインストール
  3. LowPassSoundを再ビルド・書き込み

3.0.2ではBootloader予約が小さく、ARM1に十分メモリが残る。

解決策3 外部RAMを使う(上級者向け)

Spresense Extension Boardを使ってDDRを512 Mbit化し、メモリ空間を増やす。platform.txtbuild.extra_flags
-DCONFIG_SDRAM_SIZE_MB=64 を追記→ビルド。これで-12が出ることはほぼなくなる。

まとめ

本記事では、SpresenseのLowPassSoundサンプルで「mptask_exec() failure. -12」が出る理由と、3つの回避策を紹介しました。

  • エラーコード-12はMPタスク用メモリ不足を示す
  • 静的バッファを動的確保&縮小するか、SDK 3.0.2に戻すと即解決
  • Extension Boardがあれば外部RAM化で根本解決も可能

この記事を通して、Spresenseのマルチコア仕組みとメモリレイアウトを意識したスケッチの書き方が身につきました。
次回は「ARM3以上で動かす高速FFTフィルタ」や「USB AudioでSpresenseを高音質DSP化する方法」について掘り下げていきます。

参考資料