Nick
Nick

Reputation: 1413

How do most embedded C compilers define symbols for memory mapped I/O?

I often times write to memory mapped I/O pins like this

P3OUT |= BIT1;

I assumed that P3OUT was being replaced with something like this by my preprocessor:

*((unsigned short *) 0x0222u)

But I dug into an H file today and saw something along these lines:

 volatile unsigned short P3OUT @ 0x0222u;

There's some more expansion going on before that, but it is generally that. A symbol '@' is being used. Above that there are some #pragma's about using an extended set of the C language. I am assuming this is some sort of directive to the linker and effectively a symbol is being defined as being at that location in the memory map.

Was my assumption right for what happens most of the time on most compilers? Does it matter one way or the other? Where did that @ notation come from, is it some sort of standard?

I am using IAR Embedded workbench.

This question is similar to this one: How to place a variable at a given absolute address in memory (with GCC). It matches what I assumed my compiler was doing anyway.

Upvotes: 0

Views: 588

Answers (2)

supercat
supercat

Reputation: 81169

Although an expression like (unsigned char *)0x1234 will, on many compilers, yield a pointer to hardware address 0x1234, nothing in the standard requires any particular relationship between an integer which is cast to a pointer and the resulting address. The only thing which the standard specifies is that if a particular integer type is at least as large as intptr_t, and casting a pointer to that particular type yields some value, then casting that particular value back to the original pointer type will yield a pointer equivalent to the original.

The IAR compiler offers a non-standard extension which allows the compiler to request that variables be placed at specified hard-coded addresses. This offers some advantages compared to using macros to create pointer expressions. For one thing, it ensures that such variables will be regarded syntactically as variables; while pointer-kludge expressions will generally be interpreted correctly when used in legitimate code, it's possible for illegitimate code which should fail with a compile-time error to compile but produce something other than the desired effect. Further, the IAR syntax defines symbols which are available to the linker and may thus be used within assembly-language modules. By contrast, a .H file which defines pointer-kludge macros will not be usable within an assembly-language module; any hardware which will be used in both C and assembly code will need to have its address specified in two separate places.

Upvotes: 1

kdopen
kdopen

Reputation: 8215

The short answer to the question in your title is "differently". What's worse is that compilers from different vendors for the same target processor will use different approaches. This one

volatile unsigned short P3OUT @ 0x0222u;

Is a common way to place a variable at a fixed address. But you will also see it used to identify individual bits within a memory mapped location = especially for microcontrollers which have bit-wide instructions like the PIC families.

These are things that the C Standard does not address, and should IMHO, as small embedded microcontrollers will eventually end up being the main market for C (yes, I know the kernel is written in C, but a lot of user-space stuff is moving to C++).

I actually joined the C committee to try and drive for changes in this area, but my sponsorship went away and it's a very expensive hobby.

A similar area is declaring a function to be an ISR.

This document shows one of the approaches we considered

Upvotes: 1

Related Questions