1.DMAの課題:マイコンがバッファ切り替えに追われる
DMAを使えば自動でデータを転送してくれます。
しかし「1つのバッファ」に書き込みつづけると、このような問題が出てきます。
●バッファにデータがいっぱいになる → マイコンが処理するまで次が書き込めない
●「処理中」と「受信中」がバッティングする
これを解決するのが ダブルバッファ方式 や リングバッファ方式 です。
2.ダブルバッファ方式とは

<特徴>
●Buffer A と Buffer B の2つを用意
●DMAは「A」にデータを書き込む
●一杯になったらマイコンに通知、次は「B」に書き込み開始
●マイコンは「A」を処理 → 「B」との交互でデータをロストしない
👉 ポイント:受信と処理を並列的に進めることができる
<実装(UART受信例)>
1)DMAチャネルにUART受信を割り当てる
2)転送先バッファを「Buffer A」と「Buffer B」に設定
3)転送完了 or 半分完了時に割り込み発生
4)割り込みで「どっちのバッファが埋まったか」を判定し、マイコン処理へ渡す
5)DMAは自動で次の空きバッファへ書き込み続行
<コード例(イメージ)>

3.リングバッファ方式とは

<特徴>
●DMAはメモリの先頭から順に書き込み
●終端まで行ったら先頭に戻る
●マイコンは「読み出しポインタ」を追いかけて処理
👉 ポイント:常時ストリームデータを吸い込み続けられる
<実装(ADC連続サンプリング例)>
1)DMAチャネルをADC変換完了に割り当てる
2)転送モードを「サーキュラ(循環/繰り返し)モード」に設定
3)リングバッファをRAMに確保
4)割り込みで処理位置を同期
5)マイコンは追いつく限り好きなタイミングでデータ処理
4.どちらを選ぶ?
ダブルバッファとリングバッファのどちらを選択するかは設計者の好みです。
(20年以上組み込みファームウェアにかかわってきた筆者の個人的な感想です)
あえて選択するなら以下です。
ダブルバッファ:
→ 「ブロック単位で処理したい」ケースに最適(UART受信、ログ保存など)
リングバッファ:
→ 「とにかく連続して取りこぼさず受信したい」ケースに最適(ADCサンプリング、ストリーミングデータ)


