マイコン工作実験日記

Microcontroller を用いての工作、実験記録

倍増

2013-08-22 11:34:24 | SAM4
先日、新しい版のデータシートを見つけたSAM4Lですが、この版からSAM4Lファミリーに追加されたATSAM4Lx8の説明も追加されています。このデバイスは、Flashが512k, RAMが64KBとどちらもSAM4Lx4の2倍に増えたものです。

これまでRAM容量32KBはちょっと少なめかなと感じていたので、64KB への倍増はわたしにとっては嬉しい知らせです。調べてみると、すでにDigikeyにはすでに在庫あり。ところが、例によって「日本サイト」からだと発注できません。もう少し、待ってみますか。。

こんどは、SAM4LC8を買ってみて、USBホストに挑戦してみようかと思案中。

SDカード追加

2013-08-19 21:43:34 | SAM4
SAM4LボードにSDカードを追加。LCDの下側に配置することにしました。



SAM3S/SAM4SにはHSMCIがあるのでSDモードの4ビット幅でSDカードをつなげられますが、SAM4LにはHSMCIが備わっていないので、SPIモードで接続するしかありません。今回はUSART1につないで、USARTがもつSPIモード機能を使ってみることにします。

SDカードの用途はフォントの格納ストレージです。これまではフォント格納用にSPIフラッシュを使っていたのですが、そこそこ容量の大きいものを使うと結構なお値段するので、使い勝手も入手性も良いSDカードを使うことにしました。容量たっぷりなので、フォントデータも単純なビットマップではなく、8ビットの深さをもったデータを使うことにします。

SPI最大クロック速度

2013-08-11 10:21:24 | SAM4
前回の記事で気になっていた、SPI送信時の最大クロック速度。「1.6MHzは、いくらなんでも遅すぎない?」と思っていましたが、ATMELのホームページを確認したら今月になって最新版のSAM4Lデータシート(Rev.E)が出てました。

やっぱり!! 最新版ではSPIのタイミング説明部分が修正されており、SPI2/SPI5の値が50ns以下になっています。これなら20MHzまでいけることになります。端子のスイッチング速度制限の方の制約もあるので、実際には15MHz~17MHzくらいが上限というところでしょうか。1時間ほど連続して動かしても何の問題もありませんでしたが、安心して12MHzで動かすことができます。

データシートは、四半期に一度はダウンロードしなおした方が良さそうです。

SPI割り込みではまる

2013-08-08 21:55:24 | SAM4
デジタルフィルターによるBPFは動いたので、LCDへの各バンドの音量表示をおこなっているのですが、画面表示で問題発生。

LCDはSPIで接続していますが、本来は描画しないはずの領域に時たまゴミのように線が入るという症状が発生。SPIへはDMAを使って出力していますが、その終了はSPIのTXEMPTYがセットされたことを割り込みで検出しています。この割り込みの動きがおかしいのではないかと考えて調べてみると、送信回数のおよそ2倍ちかい割り込みが発生しているではありませんか。どういうわけか許可していない条件でも割り込みが発生しているようです。さらに追いかけていくと、この問題はIISCとABDACBを動かしてWT32からのストリームを再生している時に発生するようです。

改めてデータシートでSPIタイミングを確認してみて愕然。SPI2/SPI5の時間が613nsとなっています。これではSPIの送信クロックの最大周波数は1.6MHz程度という計算になります。ほんとにこんなもんなんでしょうか?これまでSAM3Sで使っていたコードを流用していたので、12MHzで動かしてましたよぉ。クロック下げてみると確かにおかしな割り込みの発生頻度は減るようですが、ゼロにはなりません。

無駄な割り込みが発生しているのは気味が悪いので、送信終了の検出にはDMA完了割り込みを使うように変更。ただし、送信DMAが完了しても、それは最後のデータがSPIへ送られたことを示しているだけで、SPIからLCDへの実際の転送はその後発生します。そこで、送信DMA完了を検出したら、さらにTXEMPTYがセットされるのをポーリング待ちしてやります。

考えてみると、SPIのDMAよりもIISCやABDACBのDMAの方が優先度を高く設定していますので、SPIへのDMA送信がタイミングが遅くなる可能性があります。すると、自動的にCSかHighに戻ってしまうかもしれません。ゴミ表示はその影響で発生していたのかもしれません。そこで、SPIの初期化にCSAATを追加してCSをアクティブにしたまま保つことに。



今度は調子良く動いているようなのでSPIクロックを12MHzに戻してみましたが、問題無く動いているようです。

耳で聞いて確かめる

2013-08-04 20:29:32 | SAM4
しばらく停滞していたSAM4Lの作業を再開。ディジタルフィルタを使ってのスペアナ表示機能の実装です。DSP Linkを使って求めたBiquadフィルタの係数を実際に埋め込んで動かしてみました。

DSP Linkでは、フィルタの種類やカットオフ周波数等の条件を入力してやれば、それに応じたフィルタの係数を計算して、その結果をテキストファイルに出力することができます。今回は10バンドのBPFを用意することにしましたが、そのうちのひとつの係数は次のように出力されました。

この例では、31ビットで量子化した係数を10進数表記で示しています。フィルタ毎に係数を別々のファイルに書き出す操作をやらなきゃならないのが、ちょっと面倒でした。わたしとしては、複数フィルタの係数をいっぺんに出力して欲しいところ。

こうして求めた係数はCMSIS-DSP Libararyで使う係数の配列としてプログラムの一部として埋め込んでやります。

DSP Linkはq31_tの形式に合わせて正規化した係数を出力してくれていますので、基本的には求めた値をそのまま埋め込めばいいのですが、係数の並べ方には注意が必要です。上の例を見てもらってもわかるように、ひとつのフィルタは2段のBiquadフィルタで構成されていますので、5つの係数が2組でひとつのBPFに相当します。この5つの係数のうち、最後の2つの係数については符号を反転しておきます。これはCMSIS-DSPでは入力/出力の両方の係数ともに乗算後の値を足し込むのに対して、DSP Linkでは出力係数については反転してから足し込む仕様になっているためです。そのため、出力側係数を反転しておかないと正しくフィルタとして動作してくれません。なお、CMSIS-DSPでは入力側係数を b0, b1, b2 出力側係数をa1, a2と表記していますが、DSP Linkでは入力側をa0, a1, a2 出力側係数を b1, b2と表記しています。そのため、係数を並べる順番にも注意が必要ですが、CMSIS-DSPでは入力側係数から並べる仕様となっていますので、DSP Linkが出力した順番に係数を並べて、出力側の2つの係数だけ符号を反転すれば良いことになります。このように使うツール(あるいは参照する書籍やwebページ)によって、係数の名前付けや符号の扱いが異なるので、これを見落とすと大きな罠にはまります。

こうして用意いたフィルタを実際に動かしてみると....

フィルタを動かすと30MHz相当の負荷になっていることがわかります。そしてフィルタ結果に応じてLCD表示もしてみた際の数字が後半に表示されている値で、40MHzになっています。やはり結構CPUを喰いますね。16ビット演算に変更すると大幅に軽くなることも確認してみたのですが、低域のフィルタの動作が不安定でした。フィルタ後の音を実際に耳で聞いてみると、ブツブツとノイズが入るのです。こうして耳で聞いてみてフィルタの動作を確認できるのもおもしろいところですね。LCD表示はまだ「それらしく」表示できていないので、もう少し手を加えるつもりです。

フィルター設計ツールを探す

2013-07-14 23:37:57 | SAM4
SAM4Lにスペアナ表示機能を実装する作業を継続中。CMSIS-DSPの準備はできたので、実機での実装方法を検討します。CMSIS-DSPに用意されている機能を使ってスペアナ表示を実装するには、つぎの2つの方法が考えられます。
  1. FFTを使う。ストレートな方法ですが、ライブラリには窓関数処理までは含まれていないので、自分で補う必要があります。FFTでは帯域を点数で均等に分割したバンド幅毎のレベルを得ることができますが、オーディオ信号では低域の変化が主ですので、FFT結果をそのままプロットしても山が左に寄った表示になってしまいます。オクターブバンドのような帯域毎に結果を整理してから、表示した方が良さそうです。
  2. BPFを使う。表示するバントに対応するBFPを用意して、各帯域のレベルを調べる。従来のアナログ方式のスペアナ機能を、そのままデジタルに置き換える。

FFTを使うとなると、512点か1024点のFFTが必要ですね。このあいだIIRフィルタを使ったイコライザの動作確認をおこなったこともあり、今回はIIRでBPFを作ることでスペアナ表示してみることにします。

グライコの例では、Biquad IIRフィルタの係数はあらかじめMATLABで計算したものが使われていました。スペアナ用にBPFを用意するには、Biqud IIRフィルタの係数を求めてやらねばなりません。フリーのツールとかWebページとか探してみたのですが、なかなか気に入るものが見つけられません。とりあえずは、次の2つのツールで係数を求めて試してみようかと思います。
  • DSP Link
    フィルタの次数を指定することで、Biquadを複数つなげたフィルタを設計してくれる。係数を固定小数点形式で出力する機能も用意されており、量子化ビット数を15あるいは31と指定することでq15_t, q31_tの値を得ることができる。
  • PurePath Studio GDE
    TIのCODEC用のデザインツールですが、その中にBiquadのGUI設計機能が含まれています。GUIでは複数段のBiquadから構成されるBPFを直接デザインすることはできませんが、各段とも同じ中心周波数/バンド幅のBPFを複数段つなげてみようかと思います。係数はXMLファイルに書き出すことができますが、浮動小数点形式なので自分で固定小数点に変換してやります。

Biquad一段でもBPFは作れますが、急峻なフィルタ特性を得ることはできません。2段にすれば、まずまずだと思いますが、計算量も倍になるので実際に試してみるつもりです。スペアナ表示といっても正確な測定機能をめざすわけではなく、あくまでも音楽再生時のギミックなので、「それらしく」動くことが目標です。

CMSIS-DSPのグライコを試す - その2

2013-07-07 09:07:32 | SAM4
前回の記事では、CMSIS-DSPの例としてあげられているグライコを実際に走らせてみて、実時間でのオーディオ信号処理をやってみました。サンプルのとおりだと、およそ35MHzのクロック速度が必要なことがわかりましたが、もともとのプログラムはCortex-M4, M3, M0のいずれでも動作するようになっています。Cortex-M4/M3であれば、Biquad IIRフィルター処理には高速版のAPIを使うことができるので、こちらを使うようにプログラムを変更してみました。具体的には、arm_biquad_cascade_df1_q31( ) の代わりに arm_biquad_cascade_df1_fast_q31( ) を使うように変更するだけです。こちらを使うと、演算精度は犠牲になるものの、実行速度は速くなるハズだったのですが。。。



Fast版を使うと40MHz越えです。予想に反してfast版のAPIを使うと遅くなっちゃいました。どうして?  8ビットとか16ビットの演算であれば、Cortex-M4のSIMD命令を使って複数の乗算や加算を並行実行できますが、32ビットだとその恩恵を受けることができないからでしょうか?でも、これは早くならない理由にはなっても、遅くなる理由は別にあるはずですね。生成されたコードをobjdumpして調べれば原因調査可能ですが、Cortex-M4のアセンブラ勉強しなくてはならないので、そこまでの深追いは断念。せっかくなので、別の場所をいじってみます。

グライコのサンプルは、5つのバンドを5つのフィルターを通して処理していますが、低域の2つのフィルタにおいてはノイズを軽減するために32x64ビットの演算をするarm_biquad_cas_df1_32x64_q31を使用しています。通常版が内部的には64ビットでの演算をおこなっても状態変数には32ビットしか保存しないのに対して、こちらのAPIでは状態変数も64ビットで保存しているので32x64ビットの乗算が必要となり、時間がかかります。この部分を通常版のarm_biquad_cascade_df1_q31( ) に置き換えれば、演算精度が失われ音質は悪くなるでしょうが、時間は短縮できるはずです。

Fast版を使うのはやめて、32x32ビット演算に変更。効果てきめん。10MHzから15MHz程度で間に合うようになりました。これならステレオ処理もできるじゃんと喜びましたが、副作用も顕著。最低域の100Hz以下のバンドはゲインを付けると全く使い物にならなくなってしまいました。量子化誤差の影響でフィルタ動作が安定領域から逸脱したということかな。うーん、IIRフィルタは難しい。

CMSIS-DSPのグライコを試す

2013-07-05 21:38:03 | SAM4
SAM4LにつなげたSPI LCDでスペクトル表示を行うべく、その手段を調査中です。まずは、以前から使ってみようと思っていたCMSISに含まれるDSP Software Libraryを準備すべく最新版のCMSISをダウンロード。ドキュメント一式も中に含まれています。これまでも、CMSIS-COREの部分のAPIを使ってはいたのですが、CrossWorksのCPUサポートパッケージの中に含まれているものを使っていただけだったので、CMSIS一式をちゃんと見てみるのは初めてになります。

今回はDSP Libraryの部分を使ってみたいので、CMSIS-DSPの部分に目を通します。このライブラリ、Cortex-M3, M4だけでなくM0やM0+までサポートするようにできているのですね。SAM4LはCortex-M4なので、マクロARM_MATH_CM4を定義して、コンパイルしてやります。FPUが使える場合には__FPU_PESENT = 1 とすれば良いのですが、SAM4LはFPU無しなのでこれは必要無し。

さて、DSP libraryにはexampleもいくつか含まれているのですが、そのひとつとしてグライコ(Graphic Audio Equalizer Example)が用意されています。Exampleでは、あらかじめ用意されたオーディオデータをグライコ処理を通して、その結果を確認するというものになっていますが、処理の中心部分は5つのバンドに対応する 5本の 4次のBiquad IIRフィルターを通すというものになっています。演算処理には固定小数点形式であるq31_tを使っているので、このサンプルをほとんどそのままSAM4Lで動かしてみることにしました。Exampleの説明文中では明記されていませんが、周波数特性のグラフを見ると44.1KHzサンプリング用に設計されたフィルターであることが読み取れますので、Biquadフィルターの係数はそのまま流用することができます。

現在、音楽の再生処理はDMAを使って128サンプル毎にIISCで取り込んで、そのままABDACBに送っています。そこで、そのまま送るのではなく、イコライザー処理に対応するIIRフィルターを通した結果を送るようにしてやれば、イコライザーを通した結果を実際に耳で聞くことができます。まずは、試しに左チャンネルだけイコライザを通して、右チャンネルはそのまま再生することにしてみました。

結果、クロック24MHzでは動きませんでした。イコライザーのフィルタ処理は、128サンプル毎に行いますが、当然のことながら、次の128サンプルの受信が完了する前までに終了させねばなりません。44.1KHzサンプリングなので、128/44100 = 0.0029となりおよそ3msで処理を終えねばならないのですが、処理速度が足りずに間に合いません。しょうがないので、一気に48MHzにクロックを上げてみると、ちゃんと動くようになりました。FREQMを使って調べてみると....


となり、およそ38MHzのCPUクロック速度を必要としていることがわかります。FREQMでのクロック数計測には7.6msほどかかりますので、この間に2回はDMA終了割り込みに伴いイコライザー処理が走ります。そのため、FREQMの計測結果は、イコライザー処理によるCPU負荷に応じて変化します。SAM4Lでは48MHzがクロックの上限なので、とてもじゃないけどステレオ処理には力不足であることがわかります。

今のところ、サンプルのコードをそのまま持ってきただけなので、イコライザーのゲイン設定は固定となっていますが、イコライザーを通すと音が変わることが良くわかります。ちょっと手を加えればCLIからバンド毎にゲインを設定できるようになるので、やってみようかな。また、DSP LibraryのBiquad IIRフィルタには、高速処理が可能なAPIも用意されているので、そちらを使うようにプログラムを修正してみるつもりです。

使い回し

2013-06-28 22:09:12 | SAM4
これまでに何度も使っている1.8インチSPI LCDを接続。以前製作したBlueSAMでも使っていたLCDです。BlueSAMではCODECとしてTLV32AIC3254を使っていましたが、今回はこれを使わないでほとんどの処理をSAM4Lだけで実行させるつもりでいます。



BlueSAMではスペクトル表示をおこなうのに、TLV32AIC32が内蔵するMiniDSPを使って計算させていたので、CPUは表示処理をしていただけでした。計算もSAM4Lで処理するとなると、クロック24MHzでは苦しくなるかもしれませんが、まずはどこまでいけるか試してみたいと思います。

FREQMを使ってCPU使用率を調べる

2013-06-21 00:47:14 | SAM4
ABDACBの44.1KHzクロック用にクリスタルを交換するつもりでいましたが、数字を読み間違えていたことに気付いて挫折感に浸っています。しばらくは、交換しないでこのまま作業を続けることにします。

さて、先週の記事で示したように、現在のクロック系統ではPLL出力の192MHzを8分周した24MHzをmain clockとして選択し、これをCPUクロックとしています。

SAM4Lは48MHzでの動作が可能なのですが、36MHzを超える場合にはPower Scalingの機能を使ってPS2のモードに遷移する必要があります。また、フラッシュの読み出しにもウェイトを加えねばなりません。こんな理由で、いまのところはCPUクロックを24MHzとしています。FREQMでのクロック測定の結果も次のようになっていました。

この出力は、JTAGを使ってファームを書き込み/実行した際に取得したものです。ところが、いったんボードをリセットしたり、JTAG無しで動作させると、次のような出力になってしまいました。

CPUクロックの数値が激減してしまいました。それどころか、ゼロになってしまうことすらあります。FREQMの使い方をどこか間違っているのかとも思いましたが、他のクロックの数値は問題なく出ているので、FREQMの使い方に問題があるわけではありません。しばらく考えてみて、これはちゃんと正しくCPUクロック数を計測した結果なのだということに気がつきしまた。

以前の記事にも書いたように、FREQMによる周波数の計測には32KHzクリスタルを参照基準クロックとしてつかっています。今回の計測では、この参照基準クロックが250回カウントする間に、測定対象クロックが何回刻まれたかを数えることにより、測定対象クロックの周波数を算出しています。上記の出力とクロック系統図を見るとわかるように、GCLK0の出力は参照基準クロックの32KHzそのものです。そのため、GCLK0の測定クロック数も250となり、算出した周波数が32768Hzとなっているわけです。ちなみに、250クロックは7.62msに相当します。

続いて、CPUクロックの測定結果の意味を考えてみます。2回の測定結果は、7.62msの間にCPUクロックがそれぞれ285回と0回しか入らなかったことを意味します。CPUクロックが入らなければ、当然CPUは動いていないことになります。つまり、スリープしているということです。

FREQMによる周波数計測では、割り込みにより計測終了待ちをしており、割り込みが入るまではWFI命令を使ってスリープする作りになっています。そのため、計測が終わるまではCPUクロックが止まっていると考えることができます。1回目の計測のように0ではない計測結果が得られることもあります。これはどういうことかというと、7.62msの計測期間の間に、タスク制御に使用している10msに1回のsystick割り込みが発生した場合であると考えることができます。JTAGを使っていた時にはクロック源の周波数が出ていましたが、これはJTAGデバック時にはCPUのデバック機能を動かすためにCPUクロックが供給され続けるためのようです。

このようにCPUクロックの計測結果は、クロック生成部の出力を計っているのではなく、省電力機能によるクロック・ゲーティングが働いて実際にCPUに入っているクロック数を数えているのだと推測すると、つじつまが合うのです。試しに、割り込み待ちではなくポーリングにより計測終了待ちをしてみると....

ちゃんと24MHz相当の値になりました。CPUクロックは、実際にCPUが動いた割合を反映することが確認できました。したがって、実行すべきタスクが無い場合にはちゃんとスリープするようにソフトウェアが組まれていれば、この値からCPU使用率を導出できることになります。今度は、IISCとABDACBを動かして受信した音楽データの再生処理をしてみましょう。

再生処理が動いていない期間では、実効クロック速度が37KHz程度であったのが、再生中は146KHz程度に増えていますが、それでも24MHzの0.6%程度に過ぎません。再生処理といっても、その実態はDMA割り込み処理にしか過ぎないので、CPUの負荷は小さいことが良くわかります。