TalkThroughのオーバーヘッド
TalkThroughプログラムはPCMオーディオ信号入力をそのままPCMオーディオ信号として出力します。従って内部ではデータコピーしかしていません。
ここから考えを推し進めると、内部のデータコピー部だけ書き換えてオーディオ・アルゴリズムにすると、そのまま入力を信号処理するアプリケーションになります。たとえばギター・エフェクタなどを作ることができます。さて、この想像上のギター・エフェクタですが、エフェクトをかけるアルゴリズムと、その外側でDMAと同期を取っている管理コードや、OSのようなオーバーヘッドに分けることができます。オーバーヘッドはアプリケーションから見ると純粋な損失であり、言い換えると、総MIPS数からオーバーヘッドを引いたMIPS数が、そのアプリケーションで信号処理アルゴリズムが使う事のできるMIPSとなります。
さて、もう一度TalkThroughに戻りましょう。このプログラムの信号処理アルゴリズムは、単なるデータコピーです。従って、この部分の処理量を無視しうるとすると、TalkThroughの必要MIPSそのものが、オーディオ・アプリケーションのオーバーヘッドと考えることができます。そこで、あるシステムのオーディオ・信号処理能力に対する最初の評価は、TalkThroughの必要MIPS数はどのくらいになるかという事になります。たとえば総MIPS数の50%を消費するようなら、そのプラットホームは箸にも棒にもかからないと言えます。
実行中の組み込みプロセッサのCPU負荷を知る方法にはいくつかありますが、私が気に入っている方法は、割り込み待ちの前後でテストピンをトグルする方法です。この方式は、CPU負荷がまんべんなく発生する場合にはうまい具合にPWMとして機能するため、アナログ・テスタで簡単に負荷を読み取ることができます。
うまい具合にTOPPERS/ASPのCORTEX-M3実装では、割り込み待ちが一カ所にしかなく、かつ、TOPPERS_CUSTOM_IDELマクロを宣言することでこの割り込み待ちを入れ替えることができます。そこで、以下のようなコードをtarget_config.hに追加して、割り込み待ちを乗っ取り、GPIOのトグルを行いました。これでLPC1768を使用したプラットホームの性能評価ができます。
/** * \brief 待ち時間計測を指示する * \details * toppers_asm_custom_idleを使用する時には、このマクロを宣言する。 */ #define TOPPERS_CUSTOM_IDEL /** * \brief prc_suppport.S において、割り込み街を行う際、フラグをオン、オフする機能を追加する。 * \details * r6とr4を使って、GPIOのビットをオンオフする。R6とr4は、このマクロのあとにオーバーライトされているので * ここで使用しても安全なはずである。 * */ #define toppers_asm_custom_idle \ cpsid i /* PRIMASK をセット */ ;\ msr basepri, r0 /* 全割込み許可 */;\ ldr r4, =#0x2009C05C /* FIO2CLRレジスタのアドレス */;\ ldr r6, =0x100 /* bit 8. TESTピンの番号 */ ;\ str r6,[r4] /* GPIO2.8 をクリア */;\ wfi ;\ cpsie i /* PRIMASK をクリア(割込みを受け付ける) */;\ msr basepri, r1 /* CPUロック状態へ */ ;\ ldr r4, =#0x2009C058 /* FIO2SETレジスタのアドレス */;\ str r6,[r4] /* GPIO2.8 をセット */;\
set / clearをコメントアウトしてそれぞれテスタの針の読みが0V, 3.3Vであることを確認した後、DMAバッファ長96データ時の値を読み取りました。96データの場合、ステレオ48kHzなら1mS毎にDMA完了割り込みが発生し、同期して待ち状態だったオーディオタスクがコピーを実行します*1。
測定の結果、針はきわめて微量しか動かず、読み取りは困難でした*2。
そこでサンプル数を1/6の16にしました。0.16mS毎の割り込みになります。このときは電圧が目視で0.1Vでした。
電圧読み取りの精度は非常に低くはあるものの、おおざっぱに言って100MHz動作のLPC1768によるTalkThroughのMIPS消費量はDMA割り込みが1mS毎ならおおよそ0.5%と見積もることができます*3。少し良すぎる気もしますが、いずれにせよ満足できる値です。