Instant Engineering

エンジニアの仕事効率を上げる知識をシェアするWeb記事/機械設計/TPS/QC品質管理

DMAとは?CPUを使わないDMA転送の仕組み

「CPUの処理能力を上げたのに、なぜかデータ転送で処理が詰まる」。

組込み開発では、このような現象がよく起こります。センサー値の取り込み、通信データの受信、AD変換結果の保存、画像や音声データの転送など、CPUが本来の計算ではなく「データを右から左へ移す作業」に追われてしまうためです。

この問題を解決する仕組みがDMAです。

DMAとは、CPUを介さずにメモリと周辺機器、またはメモリ同士の間でデータを転送する仕組みです。CPUは転送の開始条件や転送先を設定するだけで、実際の転送作業はDMAコントローラが担当します。

本記事では、DMAの意味、DMA転送の仕組み、CPU転送との違い、割り込みとの関係、組込み開発で使うときの注意点までを実務目線で解説します。

 

1. DMAとは何か

DMAは「Direct Memory Access」の略です。

日本語では「直接メモリアクセス」と呼ばれ、CPUを経由せずに、周辺機器やメモリがデータをやり取りできる仕組みを指します。

CPUを使わないデータ転送の仕組み

通常、データ転送はCPUが命令を実行して行います。

たとえば、通信モジュールが受信した1バイトのデータをRAMへ保存する場合、CPUは周辺レジスタからデータを読み、RAMの指定アドレスへ書き込みます。

この処理自体は単純ですが、データ量が増えるとCPUは転送作業に時間を奪われます。

DMAを使うと、CPUは「どこから、どこへ、何バイト転送するか」をDMAコントローラへ設定します。

その後の実際のコピー処理はDMAコントローラが行うため、CPUは別の計算、制御、通信プロトコル処理などに集中できます。

DMAはCPUの代わりに計算する機能ではない

DMAは、CPUの代わりにプログラムを実行する機能ではありません。

あくまで、データ転送を効率化するためのハードウェア機能です。

CPUが行うべき判断処理、条件分岐、演算、状態管理までDMAが自動で実行するわけではありません。

そのため、DMAは「CPUを不要にする技術」ではなく、「CPUをデータ運搬係から解放する技術」と考えると理解しやすくなります。

マイコン内部のCPU、メモリ、I/Oの基本構成を先に整理したい場合は、マイコンとは?CPU・メモリ・I/Oの基本を解説もあわせて読むと理解しやすくなります。

 

2. DMAが必要になる理由

DMAが必要になる最大の理由は、CPUの処理時間を節約するためです。

組込みシステムでは、CPUは常に複数の仕事を抱えています。センサーを読む、モーターを制御する、通信を処理する、タイマーを監視する、異常を検出するなど、短い時間の中で多くの処理をこなさなければなりません。

単純な転送処理ほどCPUにはもったいない

データ転送は、処理内容としては非常に単純です。

「このレジスタの値を読む」「このメモリ番地へ書く」「アドレスを1つ進める」「指定回数まで繰り返す」という動作の連続です。

しかし、単純だからこそ、CPUが大量に実行すると無駄が大きくなります。

たとえば、AD変換で1秒間に1万回サンプリングし、その結果をすべてCPUが1件ずつRAMへ保存すると、CPUはデータ保存処理だけでかなりの時間を消費します。

DMAを使えば、AD変換結果を自動的にRAMへ格納できるため、CPUは一定数のデータがたまったタイミングでまとめて処理できます。

リアルタイム性を守るためにも重要

組込みシステムでは、処理が少し遅れただけで制御品質が悪化することがあります。

モーター制御では、周期処理が乱れると振動やハンチングにつながります。通信処理では、受信バッファを読み遅れるとデータ欠落が起こります。

DMAは、CPU負荷を下げるだけでなく、データ転送タイミングを安定させる役割も持ちます。

特にリアルタイムOSを使うシステムでは、タスク処理、割り込み処理、DMA転送をどう組み合わせるかが設計品質を左右します。

リアルタイム制御の考え方まで広げて理解したい場合は、リアルタイムOSとは?通常OS・Linuxとの違いも参考になります。

 

3. CPU転送とDMA転送の違い

DMAを理解するには、CPU転送との違いを押さえることが重要です。

どちらもデータを移動する点は同じですが、誰が転送作業を担当するかが異なります。

比較項目 CPU転送 DMA転送
転送主体 CPU DMAコントローラ
CPU負荷 データ量に比例して増える 設定時と完了処理が中心
向いている処理 少量データ、単発処理、条件判断を伴う処理 大量データ、周期データ、連続転送
設計の簡単さ 比較的わかりやすい 設定項目と同期設計が必要
注意点 CPU時間を消費しやすい キャッシュ、バッファ、転送完了管理に注意

CPU転送は小回りが利く

CPU転送は、条件判断を伴う処理に向いています。

たとえば、「受信したデータが特定の値なら処理を変える」「1バイトずつ中身を確認しながら保存する」といった処理では、CPUが直接扱う方が自然です。

また、数バイト程度の少量データであれば、DMAを設定する手間の方が大きくなることもあります。

DMA転送は大量・連続データに強い

DMA転送は、大量データや周期的に発生するデータに向いています。

代表例は、AD変換結果の連続保存、UARTやSPIの送受信、音声データのストリーミング、カメラ画像のフレームバッファ転送などです。

DMAを使うことで、CPUは転送が完了したタイミングだけを割り込みで受け取り、まとめてデータを処理できます。

この「CPUは段取りと後処理、DMAは転送実務」という分担が、DMAの本質です。

 

4. DMA転送の基本的な流れ

DMA転送は、単に「CPUを使わずに勝手に転送する」わけではありません。

CPUが事前に条件を設定し、その条件に従ってDMAコントローラが転送を実行します。

Step 1:転送元と転送先を設定する

最初に、転送元アドレスと転送先アドレスを設定します。

転送元は、周辺機器のデータレジスタ、メモリ領域、通信バッファなどです。

転送先は、RAM上の配列、送信用レジスタ、別のメモリ領域などになります。

Step 2:転送サイズと転送回数を設定する

次に、1回あたりの転送サイズを設定します。

8bit、16bit、32bitなど、転送対象のレジスタ幅やデータ型に合わせて指定します。

さらに、何回転送するかも設定します。たとえば、16bitのAD変換結果を1000個保存するなら、16bit転送を1000回行う設定になります。

Step 3:転送開始条件を設定する

DMAは、ソフトウェア命令で開始する場合もあれば、周辺機器のイベントで開始する場合もあります。

AD変換完了、UART受信、SPI送信バッファ空き、タイマーイベントなどが代表的なトリガーです。

このトリガー設定を誤ると、DMAが開始しない、想定外のタイミングで転送される、データがずれるといった問題が起こります。

Step 4:完了割り込みや状態フラグで確認する

転送が終わると、DMAは完了フラグを立てたり、割り込みを発生させたりします。

CPUはこの完了通知を受けて、バッファ内のデータを処理します。

実務では、転送完了だけでなく、半分まで転送した時点で通知する「ハーフ転送割り込み」を使うこともあります。

これは、連続サンプリングや音声処理のように、片方のバッファへDMAが書き込んでいる間に、CPUがもう片方のバッファを処理する設計で使われます。

 

5. DMAコントローラの役割

DMA転送を実際に実行するのがDMAコントローラです。

DMAコントローラは、CPUとは別に、バスを使ってメモリや周辺機器へアクセスします。

アドレスを自動で進める

DMAコントローラは、転送ごとにメモリアドレスを自動で進められます。

たとえば、AD変換結果をRAM配列へ保存する場合、転送元のAD変換データレジスタは固定のまま、転送先のRAMアドレスだけを1要素ずつ増やします。

逆に、メモリ上の送信データをUART送信レジスタへ送る場合は、転送元のRAMアドレスを進め、転送先のUART送信レジスタは固定にします。

用途 転送元アドレス 転送先アドレス
AD変換値の保存 固定:ADデータレジスタ 増加:RAM配列
UART送信 増加:送信バッファ 固定:送信データレジスタ
メモリコピー 増加:コピー元領域 増加:コピー先領域
表示データ転送 増加:画像バッファ 固定または増加:表示用I/O

バスの使用権を調停する

DMAはCPUと同じメモリや周辺機器へアクセスします。

そのため、CPUとDMAが同時に同じバスを使おうとした場合、どちらを優先するかを調停する必要があります。

この仕組みをバスアービトレーションと呼びます。

DMAを使うとCPU負荷は下がりますが、バス帯域は消費します。高頻度のDMA転送を大量に走らせると、CPUのメモリアクセスが遅くなることもあります。

つまり、DMAは万能の高速化機能ではなく、CPU負荷とバス負荷をどう配分するかを考えるための仕組みです。

 

6. DMA転送の代表的な種類

DMA転送には、いくつかの代表的なパターンがあります。

マイコンやSoCの種類によって名称は異なりますが、基本的な考え方は共通しています。

メモリからメモリへの転送

メモリ領域から別のメモリ領域へデータをコピーする使い方です。

大きなバッファをコピーしたい場合や、画像データを別領域へ移す場合に使われます。

ただし、単純なメモリコピーではCPUのキャッシュやライブラリ関数が高速な場合もあります。

DMAを使うべきかどうかは、データ量、バス構成、CPU負荷、同時処理の有無で判断します。

周辺機器からメモリへの転送

AD変換、UART受信、SPI受信、I2S音声入力などでよく使われます。

周辺機器がデータを生成するたびにDMAがRAMへ格納するため、CPUが1件ずつ読み出す必要がありません。

センサー値の高速サンプリングや通信受信の取りこぼし防止に有効です。

メモリから周辺機器への転送

UART送信、SPI送信、DAC出力、PWM波形テーブル出力などで使われます。

CPUが1件ずつ送信レジスタへ書き込まなくても、DMAが送信タイミングに合わせてデータを供給します。

一定周期で波形を出力する場合や、大量データを通信で送る場合に効果があります。

サーキュラモード

サーキュラモードは、指定したバッファ領域を循環しながら転送する方式です。

AD変換値を連続的に取得する場合など、一定サイズのバッファへ繰り返しデータを書き込む用途に向いています。

ただし、CPUがまだ読み終えていない領域へDMAが上書きするとデータ破壊が起こります。

サーキュラモードでは、ハーフ転送割り込みやダブルバッファ構成を使い、DMAが書き込む領域とCPUが読む領域を分けることが重要です。

 

7. DMAと割り込み処理の関係

DMAは、割り込み処理と組み合わせて使われることが多い機能です。

DMAがデータ転送を担当し、割り込みが転送完了や異常発生をCPUへ知らせます。

割り込みを減らすためにDMAを使う

DMAを使わない場合、周辺機器が1データを受信するたびに割り込みを発生させ、CPUがそのデータを読み出す設計になりがちです。

データ量が少なければ問題ありませんが、高速通信や高周期サンプリングでは割り込み回数が膨大になります。

DMAを使うと、1データごとの割り込みを減らし、「指定数のデータがたまったら割り込み」という設計にできます。

これにより、CPUの割り込み負荷を大きく下げられます。

割り込みそのものの基本を整理したい場合は、割り込み処理とは?仕組みと使い方もあわせて確認すると、DMAとの役割分担が理解しやすくなります。

DMA完了割り込みの使い方

DMA完了割り込みでは、転送が完了したことをCPUへ通知します。

CPUは割り込みハンドラ内で、完了フラグをクリアし、必要に応じて次の転送を開始します。

ただし、割り込みハンドラ内で重い処理を行うのは避けるべきです。

ハンドラでは「データが準備できた」というフラグだけを立て、実際の解析や通信処理はメインループやタスク側で行う設計が安定します。

 

8. DMAを使う具体例

ここでは、組込み開発でDMAが使われる代表例を整理します。

DMAは「高速化のための特殊機能」ではなく、実務ではかなり日常的に使われる基本機能です。

AD変換結果をRAMへ保存する

温度、圧力、電流、電圧、振動などのアナログ信号を一定周期でサンプリングする場合、AD変換結果をDMAでRAMへ保存します。

CPUは、一定数のサンプルがたまった時点で平均値、最大値、異常判定などを実行します。

この方式にすると、サンプリング周期を保ちながらCPU処理を平準化できます。

UARTやSPIの通信データを受信する

通信処理では、受信データを取りこぼさないことが重要です。

CPUが別処理中に受信レジスタを読み忘れると、次のデータで上書きされ、通信エラーになります。

DMA受信を使うと、受信データを自動的にRAMへ格納できます。

特にSPIのように高速な同期通信では、DMAを使うことでCPUの介入を最小限にできます。

DACやPWMへ波形データを送る

あらかじめ作成した波形テーブルをDMAでDACへ送ると、CPUが毎周期データを書き込まなくても波形を出力できます。

モーター制御、音声出力、試験用信号生成などで使われます。

タイマーイベントをDMAトリガーにすれば、一定周期で安定した出力が可能です。

表示データを転送する

LCDやカメラを扱うシステムでは、画像データの量が大きくなります。

CPUで画素データを1つずつ転送すると処理が重くなるため、DMAでフレームバッファや表示コントローラへ転送します。

ただし、画像系はメモリ帯域を大きく消費するため、DMAを使ってもバス帯域不足がボトルネックになることがあります。

 

9. DMAのメリットとデメリット

DMAには大きなメリットがありますが、設計を誤るとデバッグが難しい不具合を生みます。

導入判断では、利点だけでなく注意点もセットで見る必要があります。

メリット デメリット・注意点
CPU負荷を下げられる DMA設定が複雑になりやすい
大量データを効率よく転送できる バッファ管理ミスでデータ破壊が起こる
割り込み回数を減らせる キャッシュとの整合性に注意が必要
転送タイミングを安定させやすい バス帯域を圧迫する場合がある
CPUが別処理を並行できる 完了タイミングの同期設計が必要

DMAは高速化ではなく負荷分散と考える

DMAを使うと必ず全体処理が速くなる、とは限りません。

DMAもメモリバスを使うため、CPUや他の周辺機器とバス帯域を取り合います。

少量データでは、DMA設定のオーバーヘッドの方が大きくなることもあります。

DMAは「CPUの代わりに転送してくれるから速い」と単純に考えるより、「CPUの作業を分担し、リアルタイム性と処理余裕を確保する」と捉える方が実務に合っています。

デバッグが難しくなる場合がある

DMAはCPU命令の流れとは別に動くため、デバッガでステップ実行している間にも転送状態が変化することがあります。

また、バッファをどのタイミングで誰が書き、誰が読むのかを明確にしないと、再現性の低い不具合になります。

特に、DMAが書き込み中のメモリをCPUが同時に読む、CPUが書き換え中のデータをDMAが送信する、といった競合に注意が必要です。

 

10. DMA設計でよくあるトラブル

DMAの不具合は、単純な文法ミスよりも、設定・同期・メモリ管理の問題として現れます。

ここでは、実務で起きやすいトラブルを整理します。

転送元・転送先アドレスの設定ミス

最も基本的でありながら、実務でよく起きるのがアドレス設定ミスです。

周辺機器レジスタを固定すべきところでインクリメントしてしまう、RAM配列を進めるべきところで固定してしまう、といったミスです。

この場合、最初の1データだけ正常に見える、または一定周期で値が壊れるなど、原因が見えにくい症状になります。

転送サイズの不一致

16bitレジスタのデータを8bit転送にしてしまう、32bit幅のデータを16bit単位で扱ってしまうなど、転送サイズの不一致もよくあります。

このミスは、値の上位バイトや下位バイトだけが欠ける、配列の並びがずれる、エンディアンの見え方がおかしくなるといった形で表れます。

キャッシュとDMAの不整合

キャッシュを持つCPUでは、DMAとメモリの整合性に注意が必要です。

CPUが見ているデータがキャッシュ上の古い値で、DMAが更新したメモリ内容と一致しないことがあります。

逆に、CPUがキャッシュ上で更新したデータがまだメモリへ書き戻されておらず、DMAが古いメモリ内容を送信してしまうこともあります。

このような環境では、キャッシュ無効化、書き戻し、DMA用メモリ領域の指定など、マイコンやプロセッサごとの作法を守る必要があります。

バッファ上書き

サーキュラDMAでは、DMAが古いデータ領域へ戻ってきます。

CPUが処理し終える前にDMAが同じ領域へ書き込むと、データが途中で上書きされます。

この問題を防ぐには、ハーフ転送割り込み、ダブルバッファ、リングバッファ、処理時間の見積もりを組み合わせる必要があります。

 

11. DMAを使うべきか判断する基準

DMAは便利ですが、すべてのデータ転送に使うべきではありません。

設計時には、CPU転送で十分か、DMAを使う価値があるかを判断します。

DMAを使うべきケース

  • データ量が大きい
  • 一定周期で連続データが発生する
  • 受信取りこぼしを防ぎたい
  • 割り込み回数を減らしたい
  • CPUが別のリアルタイム処理を持っている
  • 波形出力やサンプリング周期を安定させたい

CPU転送で十分なケース

  • 数バイト程度の少量データである
  • 転送頻度が低い
  • データごとに複雑な条件判断が必要である
  • DMA設定の複雑さに対して効果が小さい
  • メモリ帯域の余裕が少ない

迷ったときは測定する

DMAを使うか迷った場合、CPU使用率、割り込み回数、転送周期のばらつき、通信エラー率を測定します。

感覚だけで「DMAの方が速そう」と判断すると、設定の複雑化に対して効果が小さい場合があります。

逆に、CPU転送で十分だと思っていても、実機で割り込み負荷が高く、制御周期が乱れている場合はDMA化の効果が大きくなります。

 

12. DMAとメモリマップドI/Oの関係

DMAを理解するうえで、メモリマップドI/Oの考え方も重要です。

多くのマイコンでは、周辺機器の制御レジスタやデータレジスタがメモリアドレス空間上に配置されています。

周辺機器レジスタもアドレスとして扱う

CPUから見ると、UARTの受信レジスタやAD変換データレジスタも、特定アドレスに存在するメモリのように見えます。

DMAコントローラも同じように、転送元や転送先としてそのアドレスを指定できます。

これにより、「AD変換データレジスタからRAM配列へ転送する」「RAM上の送信バッファからSPI送信レジスタへ転送する」といった動作が実現します。

volatileだけではDMA同期は解決しない

組込みCでは、周辺機器レジスタを扱うときにvolatileを使います。

しかし、volatileはコンパイラ最適化に対する指定であり、DMAとCPUのキャッシュ整合性やバッファ所有権を自動で解決するものではありません。

DMA設計では、レジスタアクセス、メモリ配置、キャッシュ、割り込み、バッファ管理を分けて考える必要があります。

メモリアドレス空間とI/Oの関係を深掘りする場合は、メモリマップの記事を別途用意して、DMA記事から接続するとトピッククラスターとして強くなります。

 

13. DMA設計のチェックリスト

最後に、DMAを実装するときの確認項目を一覧にします。

DMAは設定項目が多いため、最初からチェックリスト化しておくと不具合を減らせます。

確認項目 チェック内容
転送元 周辺レジスタかメモリか。アドレス固定か増加か。
転送先 RAM配列か周辺レジスタか。アドレス固定か増加か。
転送サイズ 8bit、16bit、32bitが対象データ幅と合っているか。
転送回数 配列サイズ、バッファサイズ、サンプル数と一致しているか。
開始条件 ソフト開始か、周辺イベント開始か。
完了通知 完了割り込み、ハーフ転送割り込み、エラー割り込みをどう使うか。
バッファ所有権 DMAが書く領域とCPUが読む領域を分けているか。
キャッシュ キャッシュ無効化や書き戻しが必要な環境か。
エラー処理 転送エラー、オーバーラン、タイムアウト時の復帰方法を決めているか。

設定値をコメントで残す

DMA設定は、レジスタ名やビット設定だけを見ると意図がわかりにくくなります。

実務では、なぜその転送サイズなのか、なぜアドレスを固定するのか、なぜハーフ転送割り込みを使うのかをコメントに残しておくと、保守性が上がります。

ファームウェアの保守や更新時に、DMA設定の意図が追えるかどうかは非常に重要です。

ファームウェア全体の役割や更新時の注意点は、ファームウェアとは?更新とソフトウェアの違いで整理しています。

 

14. よくある質問

Q1. DMAとは簡単に言うと何ですか?

DMAとは、CPUを使わずにデータ転送を行うための仕組みです。

CPUが転送元、転送先、転送サイズ、転送回数を設定し、実際の転送はDMAコントローラが担当します。

Q2. DMAを使うとCPUは完全に不要になりますか?

不要にはなりません。

CPUはDMAの初期設定、転送開始、完了確認、エラー処理、転送後のデータ解析を担当します。

DMAはCPUの代替ではなく、データ転送部分を肩代わりする機能です。

Q3. DMA転送は必ず速いですか?

必ず速いとは限りません。

少量データではDMA設定のオーバーヘッドが大きく、CPU転送の方が簡単で十分な場合があります。

DMAの価値は、単純な転送速度だけでなく、CPU負荷低減、割り込み回数削減、周期安定性にあります。

Q4. DMAと割り込みはどちらを使えばよいですか?

多くの場合、DMAと割り込みは組み合わせて使います。

DMAがデータ転送を行い、割り込みが転送完了やエラーをCPUへ知らせます。

1データごとに割り込み処理するよりも、DMAでまとめて転送し、完了時だけ割り込みを使う方がCPU負荷を抑えやすくなります。

Q5. DMAでよくある不具合は何ですか?

多いのは、転送元・転送先アドレスの設定ミス、転送サイズの不一致、バッファ上書き、キャッシュ不整合です。

特にキャッシュを持つCPUでは、DMAが更新したメモリをCPUが古いキャッシュのまま読んでしまうことがあるため注意が必要です。

 

15. まとめ

DMAとは、CPUを介さずにメモリと周辺機器、またはメモリ同士の間でデータを転送する仕組みです。

CPUは転送条件を設定し、DMAコントローラが実際の転送処理を担当します。

DMAを使うと、CPU負荷を下げ、大量データ転送や連続サンプリング、通信処理を効率化できます。

一方で、DMAは設定項目が多く、バッファ管理、割り込み同期、キャッシュ整合性、バス帯域に注意が必要です。

実務では「CPU転送かDMA転送か」を単純な速さだけで判断するのではなく、CPU負荷、リアルタイム性、割り込み回数、データ量、保守性を含めて判断することが重要です。

DMAを正しく使えるようになると、組込みシステムにおけるデータ取得、通信、波形出力、画像転送の設計自由度が大きく広がります。