STM32でDDC/DCCを作ろう! INDEXページへ
前回「feedbackが動いた」と書いたらPVが多いようで、その投稿がランク上位をkeepしています.当ブログ読者層の質の高さというか、ニッチに群がる勇者達が居るものよのう.
さて、ここ数日間進捗が止まっています.理由はhard fault.
hard faultに至る事情を話せば長いことながら事情を書きますと、、、
----事情説明ここからーーーー
端的に言えば、STM32F205の速度が足りないのが発端.CPUはCoreTexM3だったと思うのですが、そんな小さなCPUに32bit384kHzのデータレート(約3Mbytes/Sec)をガチで処理させるのは微妙といったところ.結果として192kHzまでは行けるけど384kHzはキツイようだというのが現状認識です.
もっとも処理速度問題については連載初期に軽く確認というか、まぁなんとかなるかもぐらいの感触は得てから着手したんですがね.
ここでいう速度が足りないの意味は、「Little Endian→Big Endian変換を32bit384kHzの約3Mbytes/SecでSTM32F205にやらせるのは速度が足りない」という定義です.
今時、CPUにセコセコとデータ転送の仕事をさせるよな真似はしないのがフツーでそんな仕事はDMAにでもさせとけっ、なのですが、LE→BE変換が必要なのでどうしてもCPUに一肌脱いでもらわにゃならんという事情.
さらに事情を遡るならば、、、USB規格がLEで出来ているのと、WAVE等のaudio fileもLEが主流であるらしいのに対し、DACはMSB first serialですんでBEを欲します.なのでLE→BE変換が必要になりんす.
LE→BE変換をなるべく速くやらせるにはどうしたら良いのかについていろいろと試してみましたが、結局このcodeが最善でした.32bit読み→レジスタ内でごにょごにょ→32bit書き戻しできている模様.
uint32_t little2big32(uint32_t little) {
return ((little & 0xff000000) >> 24)
+ ((little & 0xff0000) >> 8)
+ ((little & 0xff00) << 8)
+ ((little & 0xff) << 24); }
勇者諸氏としては「FPGAでLEBE変換したらどうでしょ?」と考えると思いますが、これまではhardware処理をなるべく避ける方針で開発してきました.hardを増やすと価格が上昇しますから.
とはいえ現状で既にPCB上にはXC9536を載せています.master clock生成にどうしても小規模logicが必要なためです.しかしこのCPLDでは小さすぎてLEBE変換はできません.
XC9536ではなくXC95144にデバイス変更すればhardwareでLEBE変換が可能になるのですがそれは最終手段として、まず取り組んでいるのはSTM32F405に換装してみることです.
STM32F205 120MHz
STM32F405 168MHz 1.4倍
のように405はclockが速いのでLEBE変換も1.4倍の速度で動くのではないか?
datasheetをチラ読みしたところでは、205と405はピンコンパチであるうえ、peripheralも99.9%同じのようです.やってみたら、205の焼きファイルを405に焼けてしかも動いてしまうというおよそあり得ないほどの高いコンパチビリティでした.
ただしそれでは肝心のCPU clockを168MHzに出来ないので、205のcodeを405に移植する作業をここ数日間やっているんです.
そうしたら405でhard faultが出る.faultの場所は、feedback値を送信する時のHAL/LL USBライブラリ内部です.
ーーーー事情説明ここまでーーーー
内部状態をdumpなどしておぼろげに判ってきたところによると、
・USB peripheralのレジスタアクセスで例外発生
・そのアドレスをチェックすると、USB BASE ADDRESSよりも若干小さいoffsetへアクセスしようとしている (オイオイ)
205/405の移植に失敗しているのでしょう.
これから外出なので今日の作業はこれでおしまいです.
この先の予想としては、処理速度問題は405でも解決しないと予想はしています.
たぶんXC9536→XC95144へのデバイス変更が必要になるでしょう.hardwareでLEBE変換をするわけですね.
将来はDSDも通したいので、実レート処理能力を高めておくのは有利に働くと思われます.
かしこ
intel CPUのbswapにあたるものがARMにはないのかと調べたところ、
返信削除ARMv6以降ならREVという命令があるようですね。
これを使えれば早くなるのではないでしょーか。
ご参考:https://www.iar.com/jp/support/resources/articles/migration-techniques-for-different-endianness/
これはこれは有用な情報をありがとうございます.
削除ARMのマシン語にはほとんど目を通していないので知りませんでした.
調べてみます.多謝、多謝、
coretexM4のdatasheetにて、REV r3, r7 みたいのがあるのを確認しました
削除gccですと、__builtin_bswap32関数でよろしくやってくれるようですね。
削除__builtin_rev関数というのもあるようですが、ARMでしか使えないので移植性を考えてbswap32が好まれる模様。
ご参考:https://stackoverflow.com/questions/35133829/does-arm-gcc-have-a-builtin-function-for-the-assembly-rev-instruction
勇者の皆さんのご協力に感謝でーす.STM32cubeIDEも中身ではgccが動いてるみたいなのでこういうの使えるかもしれませんね.では
削除