Electronic – Why pass pointer to register as volatile

avrc

I'm working on learning to TDD embedded C by creating an LED driver for an AVR.
In James Grenning's book, he recommends injecting the PORT by passing a pointer to the register into the function.

I came across the following code in the AvrLibc documentation, How do I pass an IO port as a parameter to a function?, and am confused as to why the *port parameter is declared as volatile.

void
set_bits_func_correct (volatile uint8_t *port, uint8_t mask)
{
    *port |= mask;
}

Can anyone explain why they're passing it as volatile? As someone who's a beginner with C, I'm confused and would appreciate an explanation (if there is one).

Best Answer

It's passed as volatile so the compiler doesn't optimize away any accesses to said parameter. This is required because a compiler may see something like this:

port = 1;
port = 2;
port = 3;

Or perhaps

while (port & 0x01) ...

Assuming that the ending state is all that matters, that can be optimized to

port = 3;

And

some_cpu_register = port;
while (some_cpu_register & 0x01) ...

Saving on instructions, memory accesses, and code space. However, since port actually accesses physical resources, these reads and writes actually are significant and the compiler should be instructed that the programmer knows best here and the compiler should not remove any reads or writes so that the program will perform the intended operations.