2025年2月20日木曜日

STM32 DMAでGPIOへ出せな~い(解決)

設計が行き詰まって逃避してきた朝のスタバ。客の7割がPCで作業中。キモい。わたしはスマホでブログ書いてるのでキモくない。


STM32で任意の特性M系列を出力したい。つまり任意の1bit出力ですね.割り込みじゃ周期がフラつくので、DMAでやる必要がある。

以前こんな投稿をしたとき、1bit出力をするためにI2Sを利用した。
しかしI2Sには面倒事があって、clock周波数がaudio系なので48kHzまたは44.1kHzの倍数になっちまうとの苦い記憶。

いまやりたいのは、外部clockでドライブされる1bit出力である。しかも任意のclock周波数で。

未体験ゾーンの「GPIOへDMAで出力」が出来れば良い。

昨日の夕方にGPIO-DMAに着手したんだが動かない。

ーーーー
まずGPIOの叩き方はどうするか?
普段はHAL_GPIOWrite()を使ってしまう。
しかしDMAの場合はそうも行かない。
DMAの送り先アドレスにGPIOレジスタを指定してやれば良い。↓これな
 GPIOD−>BSSR
BSSRは32bitレジスタで、GPIOD[15:0]を出力制御出来る。
 BSSR[31:16]がbit set
 BSSR[15:0]がbit reset
みたいな感じ。set reset逆かもだが。
なので例えばDMAで10bit出力するのに32bit配列が10個必要というメモリ非効率はあるっちゃある。

ーーーー
DMAを動かすには、initはMXの自動生成codeにお任せするとして、こんなので起動すればイイと思われる。
 HAL_DMA_Start(&dma,元,行き先,個数)
行き先は上述の &(GPIOD−>BSSR) とする。

だが動かない。

ーーーー
CPUはSTM32H743だ。
このCPUにおけるGPIOの所在地、というか内部busのぶら下がり地点は、AHB4という辺境なんだ。

CPUは王様なので辺境でもアクセス出来る。
しかしDMAは自分の所属ドメイン内のRAMやperipheralしかアクセス出来ないとの制限がある。
APB1やAPB2にぶら下がったDMAはbus bridgeが繋いでくれてるみたいなのだけど、AHB4はあまり繋ぎが密でないみたいよ。それゆえ辺境呼ばわりしてる。
busについては知識が乏しい。

AHB4傘下のGPIOにアクセス出来るDMAは在るのか?
ある。BDMAだ。

BDMAがアクセス出来るRAMはどれだ?
RAM_D3 0x38000000からの64KBのやつ

指針を得たのでやってみた。だが動かない。

家に戻って考え直してみるなり。

ーーーー
指針というやつはこれ. →リンク
1)The GPIO banks are on AHB4, use BDMA to copy data from SRAM4 to GPIOx>BSRR or ODR.
2)SRAM4 is 64KB situated at 0x38000000.
3)Should be able to use LPTIM2 or LPTIM3 OUT as a clocking/triggering source.

BDMAのトリガにLPTIMを使えって言ってる.LPTIMって簡素なので使い勝手はあまりよくなくなくない?
あと、BDMAをEXTI0でトリガしたいんだがもしかしたらEXTI0がBDMAまで届いてないのかもしれない.

ーーーー
夕方まで粘りましたが、BDMAが治りません.いじる場所はそんなに多くないので手が出ない.

撤退して、SAIを試してみます.
 →SAIはmasterでexternal clkが使えませんでした

I2Sはpinが埋まっていて使えません.

詰みっ!

ーーーー
夜、動いたかもしれない.

以下、やったことをダラーッと書きます.みなさんの役に立ちますように.ボク人柱.

【やることポエム】
CPUはSTM32H743.
DMAをcircularで動かし、GPIOに3kHzの一定レートで1bit streamを出力する.
GPIO-D12が出力先.
3kHzはEXTI0へ入力されるパルスとする.

【DMAで制御可能なGPIO出力port】
GPIOD->BSRRに書き込むとGPIOD[15:0]に出力できる.
[31:16]に1を立てたbitがresetされる.
[15:0]に1を立てたbitがsetされる.
したがって下記をcyclicに回すと、D12に111100の繰り返しが出力される.1bitの送信に4BYTEを浪費することになるがやむを得ない.
 uint32_t LBP[6];
 LBP[0]=(1<<12); // GPIOD12=1
 LBP[1]=(1<<12); // GPIOD12=1
 LBP[2]=(1<<12); // GPIOD12=1
 LBP[3]=(1<<12); // GPIOD12=1
 LBP[4]=(1<<28); // GPIOD12=0
 LBP[5]=(1<<28); // GPIOD12=0

【制約】
GPIOはAHB4傘下に在る.通常のDMAはアクセス不能.
GPIOにアクセスできるのはBDMAである.(D3 domain)
また、BDMAがアクセスできるRAMは、SRAM4 64kB 0x380000000.

【D3 domain RAMの動かし方】
まず、リンカファイルを改造する.→STM32H743VITX_FLASH.ld
末尾のところにRAM D3を追加.
    .DATA_RAM_D3 (NOLOAD) :
  {
  } >RAM_D3
  
  .ARM.attributes 0 : { *(.ARM.attributes) }
}

送信データバッファを宣言.
RAM D3に置くようにattributeを追記しておく.
__attribute__ ((section (".DATA_RAM_D3"))) uint32_t LBP[6];

注意:LBP[]宣言と同時に初期化したものはCPUの起動時に上書きされちゃうみたいよ.なので送信データはmain()の然るべき場所でやりましょう.

【serial out DMA起動】
 // GPIOD12 serial output
 LBP[0]=(1<<12); // GPIOD12=1
 LBP[1]=(1<<12); // GPIOD12=1
 LBP[2]=(1<<12); // GPIOD12=1
 LBP[3]=(1<<12); // GPIOD12=1
 LBP[4]=(1<<28); // GPIOD12=0
 LBP[5]=(1<<28); // GPIOD12=0
 HAL_DMAEx_EnableMuxRequestGenerator(&hdma_bdma_generator0);
 HAL_DMA_Start( &hdma_bdma_generator0, (uint32_t)LBP, (uint32_t)&(GPIOD->BSRR), 6);
補足しておくと、、、こんなブロック図になっている.
 EXTI0→TRIGMUX→BDMA→GPIO
DMA起動の呪文は2つからなる.
1)TRIGGER MATRIXを起動 HAL_DMAEx_EnableMuxRequestGenerator()
2)BDMAを起動 HAL_DMA_Start()

【STM32cubeMXの設定】
EXTI0をGPIO入力にしておく操作は割愛する.EXTI0に3kHzを入れるのをお忘れなく.
BDMAの設定がキモ.といってもこれ↓で全てだと思う.

あでゅ〜

24 件のコメント:

  1. 1bit DACでシフトレジスタのロジックICで出力してるのを見たことがあるのですが、どこで見たんだったかな……。STM32だったらシンプレックスのSPI SlaveでSCKに外部クロックを突っ込めば代用できないですかね。

    返信削除
    返信
    1. シリパラ回路という意味で、I2SはSPIの回路と同じ物らしく、STM32では制御をちょこっと変えてるだけみたい

      SPIだとword毎に隙間が空いちゃうみたいなのでI2Sを使ったという事情

      なのでI2S masterの外部clk使いができれば良いという逃げ道が正解なのかもしんない

      さて帰ろ

      削除
    2. 読者
      aduino で動画を液晶モジュールで再生できないので
      SPI接続からパラレル接続に戻ったそうな
      74LS244のバッファをつけて
      パラレルで1ビットを出力するとか(うそかもしれない)
      セレクタICもつけないとなのか

      削除
    3. SPIもデータ4線式とか同8線式とかワケワカメなものがあるのです

      削除
  2. ワンチップ(CPU)はこの手の制限が多いですよね。内部バスも複数あったりしてDMAから届かないこと多いですね。あとは、使いたい転送モードがそのターゲットに限って使えないとか。
    IOのデバッグの場合、メモリにトレース結果を残せないしプリントデバッグ的なこともできないので厄介ですね。
    DMAが起動していないのか(GPIOに1回も書き込まれていないのか)、連続起動していないのか、不定値が書き込まれていないのかなどを順番に見ていく感じですかね。
    当たり前のことしか書けないですが。

    返信削除
    返信
    1. DMAで自走させてるんでウンスンだと手掛かりなくてなぁ

      シンプルな別のCPUで動くのかどうかためしてみるわ

      削除
    2. murasaki
      ですねー。ハード自走だと動かないときの取っ掛かりが無いですね。難しいことしようとするとハードがそこまで対応してないことがよくあって。マイナーなチップだとエラッタやネット情報もスカスカだし。
      昔から同じチップを何年もいじり倒して挙動を把握できていたのですが、近年はそうもいかず。
      コンパイラやツールやOS的なものも挟まってきて、いよいよわけわからない。
      FPGAで外付けハード作ったほうが早かったりして。

      削除
    3. 別のCPUでも動かないので起動方法がまちがってんのかな

      とにかく今日は丸一日無駄にしています

      削除
    4. murasaki
      おおっ!!!すごい。リンカファイルまで手を入れないと動かないとは。自分だったら間違いなく2週間コースですね💦
      定数の配列宣言はc言語でめんどくさいやつですね。
      なんかconstだかstaticだかをいい感じにくっつけると宣言時にうまく入れられたかと思います。うまく行ったかはmapファイル見て配列がROMに割り当てたセグメントに入っていればOKで、RAMのセグメントに入ってたらNGとかで確認できたかと。
      お疲れ様でした。

      削除
    5. 臨死体験しました

      highendのSTM32だからかしらんけど、やたらとバスで切れてるんです
      RAMも分割されててattribute宣言しなくちゃいけない

      STM32F401はバスが1つだけみたいよ

      削除
    6. murasaki
      チップ毎に流儀というか、こんな感じだろうという推測が必要なのでトラブったときは魂が抜けそうになりますね。PCも昔はノースとサウスくらいでしたが、今はもうデバイス毎に最適化されたバスとか通信経路があって設計が大変そうです。

      削除
    7. エクトプラズムまで出てしまいました

      削除
    8. 読者 あわててコンビニで黒い縁取りの袋を買うところでした(うそ)

      削除
    9. 戒名不要、葬式不要、香典不要、骨は捨ててくれ

      削除
  3. Raspberry Pi Pico (RP2040 / RP2350) には、
    ・PIO (Programmable IO)
    って言う機能ブロックがあって、こんなの簡単に出来るんだろうな・・・
    ※実は、RP2040 / RP2350 には、「I2S インターフェース」が、仕様書上には無いのに、
    「オーディオDACの駆動」とか、平気でやってるのを見て、
    ・どんなマジックだよ?
    と思って、調べて分かりました。
    「PIO (Programmable IO)」とは、その名の通り、「IO を、プログラミング出来る」仕組みです。平たく言えば、「RP2040 / RP2350」 の中に、更に「IO専用プロセッサ」があるようなモノです。
    そこで「専用命令(と言うか、ほぼ「出力ビットパターン」を、ベタ書きした感じ)」を使って、「どんな出力でも可能になる」と、書いてあります。
    この辺
    https://qiita.com/yunkya2/items/8fce43c0dbb97be97682
    Raspberry Pi PicoのPIOプログラミング(I2Sインターフェースの実装)
    に、サンプル載ってます。

    ※なんか、この辺りは、STM32は弱いですね。
    やはり、基本設計が出来てからだいぶ経つので「アラ」が、見えて来てるんですかね。つか、こんな状態で、
    「本社リストラ」とかして、大丈夫なのか??? > STMicro

    返信削除
    返信
    1. ラズベリーよきかな
      STMでは汎用IOするにはTIMER+DMA+GPIOなのですがちくしょううごかねぇ

      とにかく今日は丸一日無駄にしています

      削除
    2. スタバの帰りに赤いキツネを買ったので明日のおやつに食べようかと計画しています

      削除
    3. 読者 赤いキツネ売り切れで 緑のたぬき 買うツイートいっぱいある コンビニ発注担当 赤いキツネをポチる作業しているにちがいない

      削除
    4. 買えてラッキーでした

      削除
    5. 読者
      丸ちゃん水産「下請けさん 宣伝のことでちょっときれくれ」
      下請け「ど、どうしましたか」
      社長「アニメCMのせいで うれしい悲鳴だ お礼をいう」
      下請け「エクトプラズムがでるかと思った」

      削除
    6. 読者 まるちゃん製造工場 叡智小説
      きつねを増産することになった 採用担当ひらえもん
      女子社員「ひらさん あのお どういう基準なんですか
      もうちょっと しごとのできるひとを採用してくださいよ」
      ひら「あわわわわ」
      女子社員「この子は 顔面だけで採用してませんか」
      ひら「あわわわ」
      女子社員「それに この子は 巨乳というだけで採用してませんか」
      ひら「あわわわ」
      女子社員「ねえ ひらさん 今日も つきあってくれるなら ゆ・る・し・て・あ・げ・る」
      ナレーター 「女子社員にせめられているひらだった」

      削除
  4. 大変です!!
    ガルクラ2ndアニバーサリー セブン抽選落ちました…(~_~;)

    返信削除
    返信
    1. 大惨事
      わたしも落選
      DOMEのダイダスコラボは失われました

      #本当にやってるのかという疑念が渦巻いております

      削除