2026年5月4日月曜日

STM32H743 GPIOへ入力 DMA 動かな~い(解決)

なんとなく仕事してます.

1年以上前の投稿「STM32 DMAでGPIOへ出せな~い(解決)」の続きというか、ハマり第2段です.

AIに質問しても、ref-manualから得た情報を断片的かつ断定的に述べるだけなので、あまり役に立ちませんでした.

ーーーー
まず1年前の投稿を振り返ると、
やりたいこと:
・STM32H743
・内部RAM(WORD)→DMA→GPIOのルート
・DMAの宛先をGPIOD−>BSSRレジスタにすればいい
・リングバッファで自走させる
・リングバッファ満タンでcallback()関数で処理
・DMAの定時トリガはTIMが発生する3kHz  (いわばサンプリング周波数)

ほいでもって地雷リスト:
1:GPIOはバスのAHB4に在る
2:ゆえにDMAもAHB4になければならない →BDMAであること
3:さらにBDMAがアクセスできるRAMはRAM_D3 0x38000000からの64KBのやつ
4:123を無視するとSTM32は黙ってDMAが停まるから気づきにくい

という地雷があったという内容だった.

とりわけRAM_D3にbufferを配置するのが厄介でリンカスクリプトをいじる羽目にまでなった.ファイルはSTM32H743VITX_FLASH.ldである.
  .DATA_RAM_D3 (NOLOAD) :
  {
  } >RAM_D3

リングバッファの宣言でRAM_D3指定する.
__attribute__ ((section (".DATA_RAM_D3"))) uint32_t LBP[6];

最後にDMA起動のおまじない.
 HAL_DMAEx_EnableMuxRequestGenerator(&hdma_bdma_generator0);
 HAL_DMA_Start( &hdma_bdma_generator0, (uint32_t)LBP, (uint32_t)&(GPIOD->BSRR), 6);

ーーーー
ここからは今回のハマり第2段である.

やりたいこと:
GPIO→DMA→内部RAM(BYTE)のルート (外部信号をサンプルさせる
・願わくば外部Fs(3kHz)でDMAトリガしたいが、ダメなら内部TIMでやる
この他は前回のと同じ条件.

BDMAは8個のchannelから選べるが、、、トリガに癖がある.
・EXTI0という外部ピンをトリガに選べるch
・EXTI0を選べず、LPTIM2をトリガにするしかないch
ここでは前者を使う.BDMA_Channel2である.
だが動かない

そこで、LPTIM2をトリガにしてDMAをトリガする方向にする.
だが動かない

前回と今回でDMAデータ転送の向きは逆であるが、言ってしまえば違いはそこだけなので、別のなにかがfactorなのではと疑ってみると、データの幅が、
 前回 word
 今回 byte
そこで、RAM_D3の4バイト境界を疑ってみる.

前回のリンカスクリプトは中身が空白だったが、4バイト境界に規制してみる.
  .DATA_RAM_D3 (NOLOAD) :
  {
    . = ALIGN(4);
    *(.DATA_RAM_D3)
    . = ALIGN(4);
  } >RAM_D3

これで動いた.EXTI0によるトリガでもLPTIM2によるトリガでも動いた.
つまり、
地雷5:RAM_D3にbufferを置くときに4バイト境界にせよ

ーーーー
DMAでGPIOへ定期的に入出力するのはUSERにとって有用な機能だと思うんだけど、STM32のDMA-GPIO界隈の仕様を見ていると、
・アーキテクチャに後付け感が強い
・とくにDMAMUXでトリガするところ
・バスの隅っこゆえに地雷が多いのもなんかやだ
・謎の動かない現象がある

なんとか動いたけど、もう少し整理してくれないかな >ARM


かしこ

0 件のコメント:

コメントを投稿