6.3.8 · D3Interconnects, Buses & SoC

Worked examples — DMA controllers

2,663 words12 min readBack to topic

This page is a drill hall. The parent note built the machinery — the registers, the state machine, the transfer modes. Here we use it, and we deliberately hunt down the awkward corner cases: the transfer that isn't a whole number of words, the zero-length request, the moment the CPU starves, the fixed-width FIFO that must not auto-increment.

Every symbol we lean on is re-anchored the first time it appears, so you can read this cold.


The scenario matrix

Think of a DMA transfer as a little machine with four dials: how much data, how wide each step, which mode (does it hog the bus or share it?), and which addresses move (do source/destination auto-increment, or stay pinned to a hardware FIFO?). The bugs and exam traps all live at the extremes of those dials.

Cell Case class What makes it tricky Hit by
A Clean burst, everything divides The "textbook" baseline Ex 1
B Byte count not a multiple of width Leftover partial word — round up? error? Ex 2
C Zero-length transfer (BCR = 0) Degenerate: does it finish instantly or hang? Ex 3
D Cycle-stealing vs burst on the same job Throughput vs CPU latency trade-off Ex 4
E Fixed source address (peripheral FIFO) Increment bit must be 0 or you corrupt memory Ex 5
F Real-world word problem (SSD streaming) Pick a mode from a throughput requirement Ex 6
G Transparent mode, CPU heavily using bus Limiting behaviour: effective rate → tiny Ex 7
H Exam twist: two masters, priority scheme Starvation under fixed vs round-robin Ex 8

The eight examples below tile every cell. Keep the matrix open in your head as a checklist.


Recall The three counters we keep re-using

SAR = Source Address Register (where we read from). DAR = Destination Address Register (where we write to). BCR = Byte Count Register (bytes still to move — counts down). width = bytes moved per step (1 = byte, 2 = halfword, 4 = word). One step does: read at SAR, write at DAR, then SAR += width (if increment on), DAR += width (if on), BCR -= width. Transfer ends when BCR = 0. See Memory-Mapped IO for how the CPU pokes these registers.


Cell A — the clean baseline

  1. Count the transfers. . Why this step? Each step moves width = 4 bytes, so the number of steps is total bytes ÷ 4. It is fewer than 4096 — wider steps mean fewer of them.
  2. Add setup + per-transfer cycles. Burst time model from the parent: Why this step? In burst mode the DMA grabs the bus once (pay setup once) then fires all 1024 transfers back-to-back — the setup cost is amortised.
  3. Convert cycles → time. One cycle at 100 MHz is . Why this step? The bus clock sets the length of a cycle; frequency and period are reciprocals.

Verify: bytes ✓ (all data accounted for). CPU is blocked the full 10.28 μs because burst mode never releases the bus mid-transfer.

Figure — DMA controllers

Cell B — the byte count that doesn't divide

Forecast: decide which is safer for a memory-to-memory copy before reading.

  1. Do the integer division. full 32-bit transfers = 4096 bytes. Why this step? Floor, not round — you can never move more bytes than requested.
  2. Compute the remainder. bytes left over. Why this step? This is the tail the full-word engine can't reach.
  3. Emit a fix-up transfer. A well-designed controller drops width to 2 (halfword) for one final step: 1 halfword = 2 bytes → BCR hits exactly 0. Why this step? A narrower final beat lands on the exact byte boundary without over-writing the next memory location.
  4. Total transfers = 1024 (word) + 1 (halfword) = 1025 beats.

Verify: ✓. If the controller lacks remainder support, the correct behaviour is to error out — never silently write 4100 bytes (that would clobber 2 bytes past the buffer, a classic overflow bug).


Cell C — the degenerate zero-length transfer

Forecast: many students say "it does one transfer." Watch the ordering.

  1. Re-read the FSM exit test. The parent's machine checks BCR = 0 after a transfer, but a correct design also checks it on entry to the transfer state. Why this step? If you only test after, a zero-length job would perform one unwanted transfer before noticing — moving a byte you never asked to move.
  2. Entry guard fires immediately. With BCR already 0, State 2 (TRANSFER) is skipped entirely; the machine jumps IDLE → REQUEST → check → DONE. Why this step? Zero work requested = zero work done.
  3. Done bit + interrupt still fire. It sets CSR.Done = 1 and raises the IRQ if IE = 1. Why this step? Software waiting on completion must be woken even for an empty transfer, or it deadlocks.

Verify: transfers executed = ✓. Bytes written = 0 ✓. The machine terminates (does not hang), which is the whole point of the entry guard.


Cell D — same job, two modes

Forecast: guess the slowdown factor — 2×? 4×?

  1. Cycle-steal time model. DMA grabs and releases the bus every beat, so setup is paid per transfer: Why this step? No amortisation — each beat re-arbitrates. That is the price of politeness.
  2. Convert. .
  3. Slowdown factor. slower than burst. Why this step? Each beat now costs 4 cycles instead of 1 — hence ~4×.
  4. But: between every beat the CPU can seize the bus. Worst-case CPU wait shrinks from 1028 cycles (whole burst) to about 4 cycles (one beat). Why this step? Cycle-stealing trades throughput for latency — vital when the CPU has real-time deadlines.

Verify: ✓ and ✓. Burst wins on throughput; cycle-stealing wins on CPU responsiveness. See Bus Architecture for how request/grant lines make this hand-off possible.

Figure — DMA controllers

Cell E — fixed address (peripheral FIFO)

Forecast: which of the two increment bits is 0, and which is 1?

  1. Source is a FIFO → fix SAR. Set CSR bit 6 (Increment SAR) = 0. SAR stays 0x4000_1000 for all 16 reads. Why this step? Hardware re-presents a new byte each read from the same address; moving the address would read the wrong registers.
  2. Destination is a buffer → increment DAR. Set CSR bit 7 (Increment DAR) = 1. DAR walks 0x2000_0000, 0x2000_0001, …. Why this step? Each captured byte needs its own memory slot; RAM addresses must advance.
  3. BCR = 16, width = 1 beats.

Verify (trace last few beats):

Beat read from (SAR) write to (DAR) BCR after
1 0x40001000 0x20000000 15
2 0x40001000 0x20000001 14
0x40001000
16 0x40001000 0x2000000F 0

Final DAR = 0x2000_0000 + 15 = 0x2000_000F, BCR = 0 ✓. SAR never moved ✓.


Cell F — real-world word problem

Forecast: guess the required utilisation as a percentage — under 100%?

  1. Peak DMA bandwidth. Bytes/beat × beats/sec: Why this step? Bandwidth = (data per event) × (events per second). This is the ceiling if DMA owns the bus 100%.
  2. Compare to demand. Demand = 2.0 GB/s. Since , a single 64-bit/200 MHz channel cannot keep up even at full utilisation. Why this step? Required utilisation — impossible, you can't use a bus more than 100%.
  3. Fix options. Widen to 128-bit ( GB/s → need ) or raise clock to 250 MHz ( GB/s → need exactly 100%, no margin). Why this step? Bandwidth scales with both width and clock; you buy headroom by increasing either.

Verify: ✓; ✓; widened and ✓. Choose 128-bit for the 37.5% safety margin — real systems avoid running a shared bus at 100%.


Cell G — transparent mode, limiting behaviour

Forecast: if the CPU hogs 90%, roughly what fraction is left for DMA?

  1. Free-cycle fraction. CPU busy 90% ⇒ DMA sees only of cycles. Why this step? Transparent DMA is a scavenger — it lives on leftovers, never competes.
  2. Effective beats/sec. beats/s.
  3. Effective bandwidth. . Why this step? Same bandwidth formula, throttled by the free fraction.
  4. Limiting case. As CPU usage → 100%, free fraction → 0, so effective rate → 0 B/s. The transfer never finishes. Why this step? This is transparent mode's fatal flaw: zero CPU interference, but throughput becomes unpredictable and can collapse to nothing.

Verify: MB/s ✓; the ✓. Compare with burst mode's guaranteed 400 MB/s (100% × 100M × 4) — transparent mode trades that guarantee for zero CPU stall.


Cell H — exam twist: two masters, priority

Forecast: which scheme starves someone, and which is "fair but slow for both"?

  1. Check feasibility. — the bus is oversubscribed, someone must lose. Why this step? You cannot allocate more than 100% of a shared resource; the only question is how the shortfall is distributed.
  2. Fixed priority. Disk always wins arbitration ⇒ Disk gets its full 60%. Net gets whatever's left: . Net is starved below its 60% need (only 40% delivered). Why this step? Daisy-chained fixed priority (parent note) never lets a lower device pre-empt a higher one — simple hardware, unfair outcome.
  3. Round-robin. Bus alternates grants, so each channel gets an equal share of the 100%: each. Why this step? Rotating priority (parent's rule) equalises access — both fall short of 60%, but equally short.
  4. Compare shortfalls. Fixed: Net misses by points, Disk fine. Round-robin: each misses by points. Why this step? Fairness spreads the pain; the worst-case channel is better off (10 vs 20 points short).

Verify: fixed ✓ (Net starved by 20); round-robin ✓ (each short by 10). See Bus Architecture and the parent's arbitration section. When both devices are real-time, round-robin's bounded fairness is why it's preferred.


Recall checkpoint

Recall

A 4098-byte transfer at 32-bit width takes how many beats (with remainder support)? ::: 1025 — 1024 word beats (4096 B) plus one halfword beat (2 B). Why must the FSM test BCR=0 on entry, not only after a transfer? ::: So a zero-length request moves zero bytes instead of one unwanted byte before noticing it's done. For reading a fixed peripheral FIFO, which increment bit is 0? ::: Increment SAR (bit 6) = 0 — the FIFO address must stay pinned; only DAR advances. Cycle-stealing was ~4× slower than burst here. Where did the 4× come from? ::: Each beat pays 3 arbitration + 1 transfer = 4 cycles instead of burst's 1 amortised cycle. A 64-bit / 200 MHz bus peaks at what bandwidth? ::: 8 B × 200e6 = 1.6 GB/s — below a 2.0 GB/s SSD, so you must widen or clock up. In transparent mode, what is the DMA rate as CPU bus usage → 100%? ::: It → 0 B/s; the DMA starves entirely.

Related depth: Cache Coherency (why DMA writes can go stale in cache), SDRAM Controllers (the memory side of these beats), ARM AMBA AXI (a real bus that implements this arbitration).