How does the macro MMIO_WORD() actually work

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

:roll: Anyone point me to a good explanation of how macro MMIO_WORD() actually works.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Where did you get this macro?

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you using AS6? If so just put the cursor on a macro, right click and "Goto implementation". For example if I write:

int main(void) {
  PORTB = 0x55;
}

put the cursor on "PORTB" and use "Goto Implementation" it takes me to:

#define PORTB                _SFR_IO8(0x18)

That in turn is defined as:

#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)

and _MMIO_BYTE is defined as:

#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))

With __SFR_OFFSET defied as:

#    define __SFR_OFFSET 0x20

The path to __MMIO_WORD() is the same (just start with a 16bit wide SFR like TCNT1).

Another way to see all this is simply to specify -save-temps when you build. You will see the PORTB line expanded out in the .i file to be:

 (*(volatile uint8_t *)((0x18) + 0x20)) = 0x55;

In this (I happened to build for tiny13) the 0x18 address is the IO address of PORTB. The +0x20 is the offset from IO space to RAM space and the rest just casts the composite address to be a volatile pointer to uint8_t and then dereferences it to make the write of 0x55.

Doing the same for a __MMIO_WORD() target I get:

(*(volatile uint16_t *)((0x04) + 0x20)) = 0x1234;

that generated from:

ADC = 0x1234;

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was chasing around trying to work out how the baud rate register was set in some LUFA code

UBRR1 = (DoubleSpeed ? SERIAL_2X_UBBRVAL(BaudRate) : SERIAL_UBBRVAL(BaudRate));

found it used a macro _SFR_MEM16() and tried to find out what that was all about only to find,

#define _SFR_MEM16(mem_addr) _MMIO_WORD(mem_addr)

at the GarretLab web-site (playing with Arduino).

Guess their equivalent macros?

Last Edited: Wed. Mar 6, 2013 - 04:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When I'm using AS6.1 I do not get "Go to Implementation" option for some reason, I get others but they don't always give me what I want. I have to hunt it down by searching through the files, e.g. dependency files in the LUFA demo I'm currently looking at.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have found the GoTo Implementation you talk about so I'll be able to use that from now on. Its just my inexperience using AS6 and the software domain I strive to come to grips with - Happy days!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well often the best way to see what a macro is doing is just invoke it and then look at the pre-processed file. As I say it does no harm to always have -save-temps added to your compile options then for every foo.c you get a foo.i and a foo.s. The .i file is the C after it's passed through the pre-processor and the .s is the Asm source the C compiler created and passed to avr-as to generate the code from your C source.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

at the GarretLab web-site (playing with Arduino).

So, if you put your __MMIO_WORD mystery into Google, guess where the first hit takes you? GarretLab.
http://garretlab.web.fc2.com/en/...

And what does it say?

Quote:
_MMIO_WORD()
Abstract

The _MMIO_WORD() is a macro that returns two bytes of data at the specified address.

Source Code

The _MMIO_WORD() is defined in hardware/tools/avr/avr/include/avr/sfr_defs.h as below.

#define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr))

The input is mem_addr and returns its contents.

Version

Arduino 1.0.1

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Quote:

at the GarretLab web-site (playing with Arduino).

So, if you put your __MMIO_WORD mystery into Google, guess where the first hit takes you? GarretLab.
http://garretlab.web.fc2.com/en/...

And what does it say?

Quote:
_MMIO_WORD()
Abstract

The _MMIO_WORD() is a macro that returns two bytes of data at the specified address.

Source Code

The _MMIO_WORD() is defined in hardware/tools/avr/avr/include/avr/sfr_defs.h as below.

#define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr))

The input is mem_addr and returns its contents.

Version

Arduino 1.0.1

theusch : So, you think that was the good explanation I wanted?

clawson : Much better explanation

but I sure believe there was a better explanation, the more I delve into the C-language stuff the more I cringe. Happy Days

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Much better explanation

Really my explanation boils down to the same:

 (*(volatile uint16_t *)(mem_addr)) 

as theirs did. It's simply casting a number (IO address) as a pointer to some type then dereferencing through the pointer it creates.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I might have to go back to college, but I'll break my back first.(that's after I've dereferenced the complete AVR community, I guess)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

theusch : So, you think that was the good explanation I wanted?

Ummm--Didn't you say:
Quote:

Anyone point me to a good explanation of how macro MMIO_WORD() actually works.


Finding the source, which you were unable to do, indicates it is a dereferenced pointer cast to the desired type.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was hoping to get an answer in a language I might understand, but its all very clear now and I'll not be asking for any good explanations again. If I come up with one I'll let you know then you'll be able to use it as the aforementioned. Still Happy days!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"How does it work?"

"Nicely."

The largest known prime number: 282589933-1

Without adult supervision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Rfrost2 wrote:
I was hoping to get an answer in a language I might understand, but its all very clear now and I'll not be asking for any good explanations again. If I come up with one I'll let you know then you'll be able to use it as the aforementioned. Still Happy days!

I don't think you asked at which level of expertise you wanted the answer. The answers are good and correct.

If you forget the actual terminology in those answers, the macros instructs the compiler to read or write something to some memory address.

So when you write PORTB = 42, the macros expand to code that writes 42 to memory address where the PORTB register lives, nothing more. The difficulty is that some registers live in IO space and some registers live in memory space so they are accessed differently. The macros hide these ugly details from you, so you don't have to care about these macros, just use port names.