2024年5月28日火曜日

STM32H723スピードtune up →audio帯域でDSPみたく使えそう

これまでBlackFin DSPでFIRを実装してきましたが、開発toolのCCESがlicense expiredで使えなくなったのを機に、STM32でDSPの代わりになるくらい高速演算できないかを試します.

目標は、300tap FIRが1演算10uSecぐらいで動いて欲しい.整数演算でもいい.

※元は数日前に投稿したものですが、結論を追記して再投稿します.CMSIS-DSP libraryを使うと、浮動小数点277tap FIR演算1回に3.36uSecを出せたのが結論です.はぇ~

ーーーー
STM32HシリーズはハイエンドCPUです.dual CPUのモノもありますけど、ここではsingle CPUのSTM32H723を使います.
 coretex-M7 550MHz SRAM: total 564 Kbytes (cash memを含む)
Nucleoを使います.

以下、いろんな条件でFIRを動かして所要時間を測定します.日々継ぎ足してゆくので長くなりそうですが、よろしくお願いします.

その1: 初歩の初歩 →FIR演算1回に56uSec
32bit整数演算の277tap FIR filter
何の色気もありません.たぶんcash memとかも使ってない.coretex-M7内蔵のFPUとかもたぶん使ってません.filter_tapsは.dataすなわちFLASHに格納されています.indataはRAM.56uSecは遅いですね.
↓codeは概念だけです、いい加減です.クリッピングはしてません.
int64 fir;
int32 filter_taps, indata;
for( int n = 0; n < 277; n++ )  fir += filter_taps[n] * indata[p];

その2: TAP係数をRAM上に配置 →FIR演算1回に60uSec
32bit整数演算の277tap FIR filter
その1はtap係数をFLASH置きでしたが、その2ではtap係数を通常RAM上に置きました.indataは元から通常RAM.
FLASHはアクセスが遅いと聞きますのでRAMに置いたら速くなるかなと期待したのですが、やや遅くなってしまいました.

その3: data cashのみON →FIR演算1回に35uSec
32bit整数演算の277tap FIR filter
tap係数をFLASH置きに戻しまして、coretex-M7のdata cashをONしてみる.
効果ありますねぇ.

その4: 命令cashのみON →FIR演算1回に40uSec
32bit整数演算の277tap FIR filter
tap係数FLASH置き.dataは通常RAM置き.
coretex-M7の命令cashをONしてみる.
効果ありますねぇ.

その5: 命令cashとdata cash両方ON →FIR演算1回に16uSec
32bit整数演算の277tap FIR filter
tap係数FLASH置き.dataは通常RAM置き.
coretex-M7の命令cash/data cashをONしてみる.
い・き・な・り・速くなった.ちゃんと動いてるのか心配になるレベル.

その6: 浮動小数点演算に切り替え →FIR演算1回に16uSec
その5までは整数演算(int32 x int32=int64t)でしたが、ここで単精度floatにしてみます.float x float=floatです.
浮動小数点演算の277tap FIR filter
tap係数FLASH置き.dataは通常RAM置き.
coretex-M7の命令cash/data cash ON.
なんと整数演算でもfloat演算でも速度が同じ.ミラクルだねぇ...
ホントに動いてるのか心配なので.listを見ると、
 vmul.f32
という浮動小数点乗算命令を使っているのでちゃんと動いてるみたいよ.
ちなみに、整数演算FIRのときは
 mul.w
という32bit整数乗算命令を使っていました.

その6: DTCM-RAMにtapとdataを置く →FIR演算1回に16uSec
その5に加えて、最もCPUに近いcashであるところのDTCM-RAMにtapとdataを置きました. →DTCMの使い方を末尾に記す
結果は16uSecで変わらず.期待したんだけどなぁ.

ここまでの結果から思うのは、命令cashとdata cashをONしただけで結構うまい事やってくれちゃってるということです.あと、浮動小数点演算命令も強力なんでしょうなぁ.

あっという間に行き詰まってしまいまして、次はもうFMACを使ってみるしかなくない?
FMACの調査の結果、使えそうにない.
FMACとは、16bitx16bit=16bitの固定小数点FIRを実装できる.
しかし、内部256wordのRAMを3分割し、入力85個、係数85個、出力85個のように使うしかないらしい.300tap FIRは実装できないみたいよ.

新たなプラン.CMSIS-DSP libraryというのがあります.ちょっと導入がかったるいけど、使えそうなlibraryで期待です.

その7: CMSIS-DSP libraryを使う(cashなし) →FIR演算1回に3.36uSec
倍精度浮動小数点演算の277tap FIR filter
信じられんくらい高速になりました.これならDSP要らないレベル.
ホントに動いているのかと疑りたくなりますが、FIR出力波形をDACで観測して正常であることを確認しています.

STM32CubeIDEのproject folder詰め合わせをこちらに置きます.説明は面倒なので略します.

その8: CMSIS-DSP libraryを使う(cashあり) →動かない
命令/data cash両方ともONにしたら、DMAが死んだみたいで動きません.早読みとDSPとは相性が悪いんじゃないかなと思ふ.

結論としては、CMSIS-DSP libraryは速くて便利で良いです.
どういう動かし方をしているかというと、こんな感じです.
 1)RAMに500個のfloat32をFIR input dataとして置く、繰り返し使う
 2)CMSISのFIRは倍精度演算277tap、500個を一括演算させる、所要1680uSec
 3)500個のFIR output dataを、intに変換し、DMAでDACへ送る、Fs=32kHz
 4)Fsを決めるのはTIM15が出力するTRIGで、DACをTRIGする
 5)DMA終了割り込みで2へ戻る
実際にはbuffer操作をもう少し複雑にしています.
500個のFIR演算に1680uSecかかったので、1個当たり3.36uSecです.
Fs=32kHzで500個ですと15.6mSecですから、FIR=1.68mSecなら余裕の計算速度です.DSPとして使えます.

CMSIS-DSP libraryのインスト~動かすまではいろいろめんどくさいので、末尾にて説明します.


===DTCM-RAMに変数を配置するやり方===
・STM32CubeIDEのproject内にある「STM32H7232CTX_FLASH.ld」を開く

・最初の方にこうゆうのがある.20000000番地以降がDTCMRAMになっている
MEMORY{
  ITCMRAM (xrw)    : ORIGIN = 0x00000000,   LENGTH = 64K
  DTCMRAM (xrw)    : ORIGIN = 0x20000000,   LENGTH = 128K
  FLASH    (rx)    : ORIGIN = 0x08000000,   LENGTH = 1024K
  RAM_D1  (xrw)    : ORIGIN = 0x24000000,   LENGTH = 320K
  RAM_D2  (xrw)    : ORIGIN = 0x30000000,   LENGTH = 32K
  RAM_D3  (xrw)    : ORIGIN = 0x38000000,   LENGTH = 16K

・同ファイルの下の方にあるDISCARDの上にでも、.myDTCMを追記する
.myDTCM :
{  
 . = ALIGN(4);
  *(.myDTCM)
 . = ALIGN(4);
} >DTCMRAM
 
/* Remove information from the standard libraries */
/DISCARD/ :  {
  libc.a ( * )
  libm.a ( * )
  libgcc.a ( * )

・DTCM-RAMに配置したい変数の宣言にattributeを追記する.
float filter_taps[]  __attribute__ ((section(".myDTCM")));
float indata[] __attribute__ ((section(".myDTCM")));

・buildしてから、project内の.mapを開く.
.myDTCM  0x20000000  0x13f4 ./Core/Src/main.o
         0x20000000         filter_taps
         0x20000454         indata
20000000番地以降にfilter_taps、indataが割り当てられているので目的達成



===CMSIS-DSP libraryをprojectへ組み込む方法===
執筆時点のversionは、STM32CubeIDE Version: 1.15.0 です.またCPUはSTM32H7でcoretex-m7です.異なるCPUですがこちらのページが参考になります.

CMSIS-DSP libraryはSTM32CubeIDEフォルダ内に存在しています.しかし、初期状態では組み込まれていないので自分でprojectに組み込む作業が面倒です.

最初は、project直下にこの2つのファイルを入れます.arm_xxxはすげーたくさんあるのですが、ここではFIR filterを使うのが目的なのでこれだけにしておきます.どこかのサイトで「STM32H7に有用なのはarm_coretexM7lfsp_mathだけ」との情報を得たので付和雷同します.
このファイルをdrug&dropで組み込めるのですが、どこに在るのでしょうか?
わたしの環境では、ずいぶん深い所です.
C:\Users\hira\STM32Cube\Repository\STM32Cube_FW_H7_V1.11.2\Drivers\CMSIS\DSP\Lib\ARM\arm_cortexM7lfsp_math.lib
C:\Users\hira\STM32Cube\Repository\STM32Cube_FW_H7_V1.11.2\Drivers\CMSIS\DSP\Lib\GCC\libarm_cortexM7lfsp_math.a

まだあります.この3ファイルをIncフォルダに入れます.
コピー元はここです.深いですねぇ.
C:\Users\hira\STM32Cube\Repository\STM32Cube_FW_H7_V1.11.2\Drivers\CMSIS\DSP\Include

まだやることがあります.
project→propertyを開き、下図の右の窓の2つを入力します.元は2つ共空欄でした.
上: arm_cortexM7lfsp_math
下: "${workspace_loc:/${ProjName}}"
わたしは以上で使えるようになりました.


===CMSIS-DSP libraryを眺める===
arm_math.hを開くと様々な関数があります.
 arm_fir_f32()    今回使った倍精度FIR
 arm_fir_q15()    たぶん整数16bitのFIRです
 arm_float_to_q31() float→int32に一括変換、あると便利ですね
 arm_mean_f32()  平均計算float32
 arm_rms_q31()   実効値int32、あらま便利
 arm_cfft_f32()   複素FFTなのかな? rfftもあります
 arm_dct4_q15()  DCTもあるぜ
 arm_mat_inverse_f64() 逆行列
こりゃ便利でいいや.
固有値(eigenvalue)は見当たらなかったかな?


CMSIS-DSP libraryを使ったproject folder詰め合わせをこちらに置きます.説明は面倒なので略します.PA4 portにDAC1出力を出すようになっています.

かしこ

24 件のコメント:

  1. PIC系は、開発環境が特殊(有償だったかも)なので、ハードルは高いカモですが。

    返信削除
  2. dsPICでもいいっちゃいいですなんでも動けばOKなり

    返信削除
  3. dsPIC って、
    ・I2S インターフェースやDMA
    は、持って無いんですね・・・
    ※と言うことは「オーディオ用途」は、想定してないのかな?

    そんなことは無いようです。型番(シリーズ)によって、有/無があるみたいです。
    (データシートで確認。少なくとも dsPIC33CH128MP508 FAMILY には存在します。)
    (秋月の商品ページには、記述がないだけでした。ちゃんと書いてくれ>秋月)

    返信削除
  4. >STM32 Nucleo Board STM32H723ZG
    STM32H723ZGは最大550MHz動作の32bit Arm Cortex-M7コア
    ※なんか、「クロックスピード」の、インフレ率には目をみはるものがありますね・・・
    そのうち、
    ・8 Pin DIP で、内蔵クロック 1GHz の CPU
    とか、当たり前に出て来そうですね(笑)
    (何に使うんだよ、そんなの? と、思ってられるのは今だけカモです。)

    返信削除
    返信
    1. 「Z80 4MHz」が、「劇速」だった頃が懐かしい・・・
      ※たったの「45年前」ですが。

      削除
    2. がんばり過ぎではないかと心配しちゃいます.
      いや、欲張り過ぎというべきか.
      乞食ちゃんとしては極楽なのでよかよか.

      削除
  5. わたしは乞食なので、安ければなんでも食べます
    STM32H7に挫折したらdsPIC食べるのかな?

    返信削除
  6. 秋葉原の情報
    自転車のバッテリーの充電の話
    マキタのバッテリーはある道具をバッテリーにつなぐと充電回数と残量がでるそうだ
    今日はスーパーマンに会えず
    この程度の情報
    顔が狭くて
    人徳のなさでした おわり

    返信削除
    返信
    1. あ、そういえば いろいろ教えてくれた人にきくのを忘れていた

      いつも予想外のところで会うので質問忘れていた

      削除
    2. マキタのリチウムで丸鋸とか、グラインダーとか、あれもすげぇなぁって思います.モバイルで丸鋸.

      削除
    3. SVHSの頃のビデオカメラのモバイルバッテリーみたいにモバイルバッテリー互換のACアダプタを出してもらえたらAC使いできて便利かもと思うます
      バッテリーを放電させてしまう自分としては
      メーカーはそれならモバイルでなくAC100V.の工具もどうぞなのだろうけど

      削除
    4. それはPHEVみたいでよろしかー
      ガソリンでもどうぞ

      削除
  7. STM32H7あんな高いもの誰買う?
    でしたが
    値上がり前のラズパイ4 7000円
    ラズパイ5 12000円を考えると 値段比較で それほどでもと金銭感覚狂ってきた自分
    秋月の補充後値上がりを考えると かってもよいかな?
    まあ使わないけど
    買うと 使わないのにと後悔
    買わないと やっぱり値上がりと後悔
    どつちにしても後悔する
    修学旅行学生の秋葉原でお金をおみやげで使いたい病

    返信削除
    返信
    1. $29が秋月で¥5980
      そんなもんですかね?

      そうも$1=¥100換算が身についてしまっているもので.
      円高乞食です.いや円安乞食か.

      削除
    2. $30として ドル150円なら 4500円 ドル100円のときの仕入れなら3000円 むむむ

      削除
  8. マキタの電池モバイル工具は、電池をダメにする自信あります
    ノートブックパソコンダメにする電池充電しない放置

    返信削除
    返信
    1. 電池に過酷な使い方www

      削除
    2. 電池アボーンのノートブックパソコン買ったあと、電池がだめとわかった瞬間
      ご愁傷さまでした チーン
      ジャンク買った時の最大の不幸
      まだ成仏できないで この世をさまよっている
      うちの事故物件 あなおそろしや
      呪われている
      不幸の現況を思い出しました
      はやく成仏してもらわないと
      なんまんだぶ アーメン
      なんだかねむくなってきたよ パトラッシュ

      削除
    3. PCってどうやったら捨てれるのかと思います

      削除
    4. ばらして燃えないごみ
      プラは燃えるごみ
      デスクトップケースなジモティであげますかな
      ラジオデパートの裏口にノートならおいておけば三分で消えます

      削除
    5. フルタワーのケースがなげてあり あれは持って帰れないなあと思ったら 夕方には消えてなくなっていた
      春くらいから 物を置いていく人はいないみたい
      どこかのツイートで 使えないと思ってノートパソコン投げてそれを話したらなおるよと言われてすぐにとりにいったら 秒で拾われていたというものをみたことある ツイートでは 1分から3分かな すぐに戻ったそうなので

      削除
    6. 銅線の束をゴミ出しするとサクッと盗まれて痛快です

      削除
    7. ソーラー発電場は、銅線からアルミ線に変えているそうです
      クルド人対策?
      捕まっても強○送還なし 不起○ばかりでわるいもの天国

      削除
    8. そうですか、ロスが増えても盗まれるよりは痛快です

      削除