Memory-Mapped I/O

© 2003 by Charles C. Lin. All rights reserved.

Preliminaries

It's useful to know about virtual addresses before reading about memory-mapped I/O, though not entirely critical.

Introduction

Suppose you want to communicate with an I/O device. Perhaps a printer or mouse. What's a good way to do this? You might think of sending a special signal to the I/O device. However, there is another way to do it.

Normally, you imagine that at every address, there's some memory associated with it. In a primitive CPU, you might imagine a byte of RAM associated with each address generated by a program.

Think about what happens when you try to load or store a byte from memory.

This is merely a protocol. It just happens to be between memory and the CPU.

If an I/O device can follow the same protocol, it can respond the same way, and as far as the CPU is concerned, it doesn't matter that the I/O device is doing the communication.

The only issue is to have memory respond to some of the (physical) addresses and the I/O device respond to other addresses. Thus, the set of addresses handed by memory and I/O devices should be disjoint.

Communication to I/O devices

You might wonder how the communication might work. Suppose you have a printer, and it has some status bits. These bits may reside at some memory address that the CPU "knows" is for the printer. Thus, to get information from the printer, you read a byte or a word from that address.

That byte might tell you if the printer is printing, or is out of paper, or out of toner, or what kind of paper is being used, etc.

You may also want to direct the printer to print. You can send it what characters to print, or what font, etc. This information can be written to a "memory" address. However, instead of having memory at that address, you have an I/O device. The CPU acts as if its writing to memory, and the I/O device reads this information.

Sophisticated Devices?

As CPUs and operating systems become more sophisticated, the way to communicate to I/O devices may not really be through memory mapped I/O. However, it's still a great idea to know, because it really emphasizes the notion that any device can be part of the protocol between CPU and memory. If an I/O device follows that protocol, and there's a way to make sure it's the only device that can respond, then there's nothing special the CPU needs to do to communicate with the I/O device.

volatile

Normally, the CPU is the only device updating a memory location. This is convenient when you write a program, because it means that when you assign a value to a variable, it shouldn't change values until the next time you assign it.

However, if you have a byte of at some memory address that is really the status of a printer, then the printer is updating that byte. If this corresponds to a variable in your C program, then that variable may be changing.

A problem occurs with caching. Suppose that value is placed in the cache. Now we have a copy, but the I/O device is updating what would be considered "memory", not the cache directly.

One way to have the compiler avoid caching is to use the volatile keyword. A variable that's volatile is expected to change outside the program's control. Thus, it should not be kept in cache, because the cache may not see the updates.

Special Instruction I/O

Some ISAs have special instructions for I/O. For example, the 8086 used IN and OUT to read and write to I/O devices. IN and OUT were considered I/O instructions (they're still assembly language instructions). The only difference between IN and OUT and loading and storing from memory was a single pin of output on the CPU.

This pin would be output, say, 0, if the address on the address bus was a memory address, and output 1 if the address was an I/O address.

This output pin would be used in the chip enable of memory and I/O devices. When the value is 0, then memory could have its chip enable active. When the value is 1, the I/O device could have its chip enable active.

Basically, the mechanism for communicating with I/O devices and memory is the same, as far as the signals sent to the devices from the CPU.

The main difference is just in the instruction set, where some ISAs support I/O instructions while others just use memory-mapped I/O, and reserve a section of memory for I/O devices.

Breakdown of Addresses

Physical Addresses can be broken down into three categories It is possible that there are some addresses that are invalid, because there's not enough RAM, and there's also no I/O devices. After all, a program can usually address up to 4 Gigs of memory, but it's typical to only use about 1M of RAM. Even though CPUs have 32 address pins, it's rare that all 232 addresses are used.

Much of it is invalid, and if an invalid physical address is generated, it may send an interrupt back to the CPU to indicate this has happened.

Summary

Memory-mapped I/O uses a section of memory for I/O. The idea is simple. Instead of having "real" memory (i.e., RAM) at that address, place an I/O device.

Thus, communicating to an I/O device can be the same as reading and writing to memory addresses devoted to the I/O device. The I/O device merely has to use the same protocol to communicate with the CPU as memory uses.

Some ISAs use special I/O instructions. However, the signals generated by the CPU for I/O instructions and for memory-mapped I/O are nearly the same. Usually, there's just one special I/O pin that lets you know whether its a memory address or an I/O address. Other than that, they behave nearly identically.

Web Accessibility