Microprocessor Systems: CPU, Memory, Buses & I/O
A microprocessor system is a set of state-owning components coordinated by bus transactions: the CPU issues instruction and data accesses, memory and peripherals respond to decoded addresses, and interrupt or DMA logic changes who needs service or who owns the bus.
A microprocessor is not a complete computer by itself. It executes an instruction stream and initiates transfers, but useful behavior appears only when memory, clocks and reset logic, address decoding, peripherals, interrupt control, and sometimes other bus masters agree on a transaction protocol. A microcontroller integrates many of those blocks into one package; it does not remove their logical boundaries.
The system is a set of contracts #
- CPU
- Owns architecturally visible registers, fetches and executes instructions, and requests memory or I/O transfers.
- Memory
- Maps addresses to stored bytes. ROM or flash normally supplies boot code; RAM holds mutable state and stacks.
- Peripheral
- Exposes control, status, and data registers. The register may represent a UART byte, timer count, GPIO latch, or a command to a more complex device.
- Interconnect
- Carries an address, transfer direction and size, write data or returned read data, and completion or error status.
- Interrupt controller
- Prioritizes event requests and tells the CPU that software attention is required. It does not move the device's payload.
- DMA engine
- Becomes a bus master and moves data without making the CPU execute one load/store pair per element.
These are functional roles, not necessarily separate chips. A small microcontroller may put CPU, flash, SRAM, timers, interrupt routing, and buses on one die. A board built around the 8086 used external memory, latches, transceivers, interrupt control, and clock logic. The integration boundary changed; address decoding, state ownership, and transaction ordering did not disappear.
A transfer is more than data wires #
A bus transaction answers five questions:
- Who is the initiator? Usually the CPU, but possibly DMA or another processor.
- What location is selected? Address decoding chooses one memory range or peripheral register.
- Which direction and width? Read versus write and byte versus word determine active lanes and strobes.
- When is the value valid? Clock edges, request/acknowledge handshakes, or wait states define completion.
- What happened? The target may complete, delay, or report an error.
Calling a connection an “address bus” or “data bus” describes only signal purpose. Some processors multiplex address and data on the same pins at different phases. Internal SoC fabrics may packetize requests. The durable abstraction is the transaction lifecycle.
Memory-mapped and isolated I/O #
With memory-mapped I/O, device registers occupy ordinary addresses and normal load/store instructions access them. With isolated I/O, the processor exposes a separate address space and dedicated instructions or control signals. The original 8086 provides both a one-megabyte memory space and a separate port-I/O space accessed by IN and OUT.
Neither choice makes a device register behave like RAM. Reads may consume queued data or clear a status bit; writes may launch an operation; some bits are read-only, write-one-to-clear, or self-clearing. Compilers and CPUs must not silently remove, merge, cache, or reorder such accesses across the ordering boundary defined by the platform.
Reset, execution, and asynchronous events #
The normal lifecycle is:
- reset establishes a defined architectural state and instruction-fetch location;
- the CPU fetches instruction bytes from memory;
- decode identifies operands and the state transition;
- execution may use registers only or request memory/I/O transfers;
- retirement makes the architectural result visible;
- an accepted interrupt or exception redirects control through an architecture-defined entry mechanism.
An exception is caused synchronously by the current instruction or execution state. An interrupt is normally an asynchronous request from outside that instruction stream. Both transfer control, but the distinction determines restart behavior, masking, priority, and what state must be saved.
Interrupts and DMA solve different bottlenecks #
Polling spends instruction bandwidth repeatedly asking whether a device needs service. An interrupt lets the device announce that a condition changed. The handler still reads or writes device state.
DMA removes a different cost: repeated CPU-mediated payload copies. Software programs source, destination, length, and policy; the DMA engine arbitrates for the interconnect and performs transfers; an interrupt commonly reports completion or failure.
Work one transaction end to end #
Suppose a UART receive register is mapped at address 0x4000_1000:
- The UART samples a serial frame and deposits a byte in its receive register.
- It asserts an interrupt request because the receive-ready condition became true.
- Interrupt logic records and prioritizes the request; the CPU enters the handler.
- The handler loads
0x4000_1000. Address decoding selects the UART, not RAM. - The UART returns the byte and may clear receive-ready as a side effect.
- The handler stores the byte in RAM and acknowledges the interrupt condition.
Every bug in this chain has a different owner: pin and clock configuration, device state, interrupt routing, vector setup, register address, access width, ordering, or software lifecycle. “The UART is broken” is not yet a diagnosis.
Diagnostic map #
| Symptom | First boundary to inspect |
|---|---|
| CPU never fetches valid code | reset vector, clock/reset sequencing, code-memory mapping |
| Read always returns all zeros or ones | address decode, chip select, bus direction, unmapped-address behavior |
| Device state changes but no handler runs | device enable, interrupt route, priority/mask, vector entry |
| Handler runs repeatedly | source condition not cleared, wrong acknowledgement order, level-trigger still asserted |
| DMA buffer is stale or corrupted | ownership, cache coherency, transfer width/alignment, completion ordering |
| Byte accesses work but word accesses fail | lane selection, alignment, target width, multi-cycle transfer behavior |
The method is to trace ownership and one concrete transaction. Component names alone do not reveal the failed contract.