0
\$\begingroup\$

I am revisiting Microcontrollers and Microprocessor concepts.

Yes. I know this question has been asked many times like here and here. I have also visited many sites regarding this concept but still I find it difficult to grasp.

But still I am unable to get the concept in my head.

Can someone provide me some image/visual representation or an example(and an analogy) to help me understand the concept of Memory Mapped IO and IO mapped IO.

  1. Why is this necessary concept? Is this related to microprocessors or microcontrollers?

  2. Do we really use it somewhere. Please provide an example in simple terms

\$\endgroup\$
10
  • 1
    \$\begingroup\$ IO mapped IO (or a separate IO address space) is not necessary, but was used in the Intel 8080/8085 microprocessors. Even with those processors it was not necessary to use the dedicated IO space. I worked with 8085-based systems that had all the IO in the memory address space. The Motorola 6800 and some other processors of that vintage did not have a separate IO address space. \$\endgroup\$ Feb 27 '20 at 4:55
  • \$\begingroup\$ Could you please provide an answer with an example/analogy/visual representation? \$\endgroup\$
    – Newbie
    Feb 27 '20 at 5:27
  • \$\begingroup\$ I don't understand why you need a visual representation. Memory mapped IO addresses are treated just like any other memory address, whereas IO mapped IO addresses are distinct and treated differently from memory addresses. I guess it's like using the same notebook for math and science versus using a different notebook for math and science. In memory mapped, everything is lumped together. In IO mapped, they are separate. I'm not sure what it is you want. \$\endgroup\$
    – DKNguyen
    Feb 27 '20 at 5:47
  • \$\begingroup\$ This isn't really relevant on modern MCUs. A peripheral is either memory mapped or it's accessible through a serial bus like SPI or I2C. Parallel address buses used for directly accessing external hardware is a thing of the past, mainly because they were an EMC nightmare. \$\endgroup\$
    – Lundin
    Feb 27 '20 at 9:30
  • \$\begingroup\$ @Lundin I don't think so, as the I/O area addressable with 16 bit addresses still exists on all x86. This space is not mapped into the physical memory space AFAIK. \$\endgroup\$ Feb 27 '20 at 11:32
5
\$\begingroup\$

If you want to store a byte in memory, you use a CPU instruction WRITE with two parameters: address and value.

If you want to send a byte over UART (Serial), you need a way to write the byte somewhere. If the output register of UART is memory mapped, you will use the same WRITE instruction as to store to memory, but you will use an address which is not a memory, but writes to the peripheral.

In an CPU with separate IO address space, if you want to write a byte to UART, you will use a CPU instruction WRITE-IO for IO space write. It has too two parameters address and value, but this is address to IO space, not to memory.

An analogy could be a kitchen furniture with hidden appliances in a contrast with a traditional kitchen. In a kitchen furniture with built-in appliances, behind some doors is storage and behind some doors is an appliance. So if someone asks, where is the dishwasher, it is second door from right.

enter image description here

\$\endgroup\$
8
\$\begingroup\$

In memory mapped I/O the I/O register is selected at a memory address. To the CPU it looks just like a regular memory location. The advantage of this scheme is that no special instructions are required to perform I/O operations. Disadvantages are that the I/O registers take up space that could otherwise be used for RAM or ROM, and a lot of gates are required to fully decode the small address range required by the I/O registers (or if the addresses are not fully decoded, an even larger 'hole' is created in the memory map).

In the example circuit below the decoder has a 'granularity' of 16k, so the single I/O register uses up 16k of memory space.

schematic

simulate this circuit – Schematic created using CircuitLab

'I/O mapped' I/O uses a separate address space that is accessed by dedicated I/O instructions. The data and address lines may be shared with memory devices, but the control bus generates a separate enable signal for memory or I/O depending on the type of instruction. Advantages are that I/O doesn't use up memory space, and minimal decoding is needed to select individual registers. The address range can also be smaller (eg. 5 bits to access 32 registers) allowing to it to be embedded into the I/O instruction for faster execution. Disadvantages are the extra control signal line using up a pin on the CPU, and the dedicated I/O instructions using up opcodes that could otherwise be used for other purposes.

Here's an example implementation. In this circuit the I/O register is enabled via the I/O request signal from the CPU, so it doesn't conflict with memory even though it has no address decoding (if more ports were added then a separate decoder would be provided to decode the I/O addresses).

schematic

simulate this circuit

A classic example of memory mapped vs dedicated I/O is the 6502 vs Z80. The 6502 has 64k of address space selected with 16 address lines. If you want I/O (and who doesn't?) then you can't have 64k of RAM and/or ROM. Since RAM and ROM chips usually come in large sizes, one of them may have to be switched out at certain memory locations to insert the few I/O registers you need, which makes the address decoder quite complex.

The Z80 also has 64k of address space with 16 address lines, but has two enable signals - one for memory (/MREQ) and one for I/O (/IORQ). You can install a full 64k of RAM and/or ROM, plus another 64k of I/O registers. Some I/O instructions have an 8 bit address embedded in them which is put on the lower 8 address lines to select up to 256 I/O ports, while others use the BC register to send the full 64k address. In a low-end system the I/O addresses can be partially decoded by simply ORing one address line with the /IORQ line, providing select signals for up to 8 I/O devices without a decoder chip.

\$\endgroup\$
2
  • \$\begingroup\$ the AVR assmler has dedicated IN and OUT instructions, but they are just ordinary register copy instructions written using a different mnemonic, because on the AVR even the registers are memory mapped. \$\endgroup\$
    – Jasen
    Feb 27 '20 at 11:26
  • \$\begingroup\$ @jasen AVR has a separate I/O space with addresses ranging from 0x00 to 0x3F, which only needs 1 cycle because it is addressed directly by the instruction, but it also maps the I/O registers into data memory which takes an extra cycle to compute the full address. So it has some characteristics of both. This hybrid system might not be the best example though, so I have removed it. \$\endgroup\$ Feb 27 '20 at 20:17
1
\$\begingroup\$

1) There are always many ways to do things, no exception here. It is not a necessary context, either way is fine. It applies to both microcontrollers and microprocessors. Back in the mainframe days, a processor could have a memory channel and a IO channel for separate handling of peripherals. Peripherals usually have slower bus than memory so IO accesses can take longer than memory accesses, so it made sense to separate the two. E.g. 8086 and Z80 have separate IO address space and instructions for reading and writing IO ports, while 6502 and 6800 just have a single memory space so peripherals are accessed with memory reads and writes.

2) Even today your PC with x86 compatible CPU has support for accessing some legacy peripherals via IO ports, and accssing them is much slower than memory. Modern peripherals are more likely to sit on the memory bus.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you. I just need some example or an analogy to understand better. Everywhere I am seeing answers but I am unable to understand without an analogy or visual representation or an example. \$\endgroup\$
    – Newbie
    Feb 27 '20 at 5:30
1
\$\begingroup\$

At this point in time it doesnt really matter, while technical in nature you can consider this a marketing thing, a way to make motorola look better than intel, we have memory mapped I/O and a flat address space. Which kicked off a chain of events we still feel today.

Addressing is addressing. 123 main street in smith town could be an apartment complex. 123 main street in jones town, could be a house, either can hold people, a dog or a cat, a car in the garage, a large swimming pool in the back. Does it matter that one is an apartment or a house if you are interested in mailing something to a specific individual? Or you are a paving crew putting in a new driveway? No it doesnt. Does it matter if you drove to that dwelling by turning right on to main from 1st street or left from 2nd street? No, you just need to get to the right address.

Think in terms of modules, the processor is a module it has a bus that bus has control signals and address and data at a minimum. Some way to indicate a write or a read, todays busses are more complicated (essentially separate read address, write address, read data, write data busses) but still provide a divisible boundry. Then you have your first level address decoders and here is where the address space starts to form, there are generally a few to several to many layers of address decoders. I need to decode the country, then the state, then the city, jones town or smith town, the the street and then finally the address of the dwelling on that street. I might have the address 0x41100123 vs 0x41200123, as a designer of the chip I may have arbitrarily decided that addresses in the 0x40000000 to 0x4FFFFFFF range are where I am going to map my peripherals. And I decided that 0xx1xxxxxx is a certain sub space within 0x4xxxxxxx lets call it the state that jones and smith towns are in. and 0xxx1xxxxx indicates jones town and 0xxx2xxxxx indicates smith town and 0xxxxx0xxx indicates main street and 0xxxxxx123 indicates the address on that street so 0x41100123 is 123 main street in jones town and 0x41200123 is 123 main street in smith town. Now does everything have to have a main street? Nope, in this case perhaps think of this as two separate uarts and I want to access the status register in uart 0, I have decided as the designer, arbitrarily there is no grand science to this, that 0x41100123 is the status register for uart0, and 0x41200123 is the status register for uart 1, if I were to add a uart2 to my design later on if I have left room I would naturally put that at 0x41300123. So what I decided in my design was that 0x40000000 is where the peripherals start in the very early address decoder right on the edge of the chip I can route those accesses toward a peripheral address decoder, then within the peripheral address decoder bits 27:24 indicate that this is one of the uarts, so I push down into that decoder, then that decoder examines 23:20 to determine which uart, then the lower bits are examined by the individual uart. Each of these address decoders puts enables on the sub busses to indicate this address is for you. This address is for the chip comes from the processor, the first level in my design has examined the address and enabled on a peripheral bus this address is for the peripherals, then the next level this address is for the uarts, then the individual uart has its bus enabled with an address and it simply does what it is told

flash on my microcontroller say I choose to design it with four 0x1000 byte flash banks. and I choose primarily due to the processor design and how it boots to have the flash start at address 0x00000000 so the first bank is from 0x00000000 to 0x00000ffff the second 0x00001000 to 0x00001fff, and so on. so the first level address decoder only needs to look at bits 31:28 in my design to see that this is for the flashes. then bits 13:12 are examined to determine which flash bank and then the transaction is enabled to the specific bank.

ram same deal say I implemented ram as two banks of 0x2000 bytes, starting at the processors address space 0x20000000, so examine bits 31:28 in the first decoder, enable this on the sram bus, examine bit 13 on the sram bus to determine which bank then send bits 12:0 to the specific sram to have it do its thing.

address space is arbitrary, someone decided how they wanted to divide it up, had some number of things they needed to fit into the space, ideally decode as few bits as possible at each layer to save logic and simply implement it.

How do these addresses get used plays into the memory mapped vs I/O mapped. So most of the flash access is instruction fetches, so those are not generated by instructions those are part of the processor logic, driven by the programmer that lays the tracks for the train to follow, sequential segments of code with occasional turns or forks. Lets assume that all flash is accessed that way, even though we know it is there in the address space and can be accessed in other ways not to mention it has to be written somehow. Then there is SRAM we use that to store bits, numbers, strings, pixels, whatever. That is generally accessed using load/store instructions or an overloaded mov instruction.

What intel did which wasnt unique to them you can look at the DEC PDPs and others, was to create an instruction that caused a different kind of access, in intels case the I/O port read/write simply created an additional address/control line. You can easily see on the 8088/86 that you had address and data and some control signals including an I/O signal. That was it memory mapped I/O vs I/O mapped I/O had to do with did you use the mov instruction to read/write or the I/O instructions to read write? then an address goes out data comes back but along with read/write control and that address there was an additional addres/control signal.

In my fictional MCU I could have bit 31 be the I/O bit 0x41100123 could be some perihperal register and 0xC1100123 could be something else.

The implementation at the time for I/O mapped I/O in these early intel systems is take the video card as a good example. The control registers that determine how many pixels wide, how many high, bits per pixel/video mode, etc were control and status registers and they implemented control and status as I/O looking for I/O bus transactions. But the pixel memory itself, the relatively large block of ram that holds the pixels was memory mapped. They basically for that example and others memory on the peripheral was mapped using read/write/mov based transactions and control and status, non memory, using I/O. Was an interesting idea that had a history (specific instructions in the instruction set to access the tty/uart rather than addresses in I/O space), but became an easy marketing/design target for motorola to beat up intel on briefly. (the reality is everyone uses segmentation/windowing in addressing, they just hide it) they could have and I think later with pci did make it so you can get to control and status through either, I can get to 123 main street by turning right off of 1st street or by turning left off of 2nd two paths to the same dwelling.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ short answer there is no magic to I/O mapped vs memory it was a design choice decades ago it had value and made sense at the time, as with BCD instructions, later as processors and busses and peripherals evolved and we could cram more logic in and have more software, these notions dont make as much sense anymore. \$\endgroup\$
    – old_timer
    Feb 27 '20 at 16:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.