Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

slightly weird C++ code

Tags:

c++

c

embedded

Sorry if this is simple, my C++ is rusty.

What is this doing? There is no assignment or function call as far as I can see. This code pattern is repeated many times in some code I inherited. If it matters it's embedded code.

*(volatile UINT16 *)&someVar->something;

edit: continuing from there, does the following additional code confirm Heaths suspicions? (exactly from code, including the repetition, except the names have been changed to protect the innocent)

if (!WaitForNotBusy(50)) 
    return ERROR_CODE_X;

*(volatile UINT16 *)& someVar->something;

if (!WaitForNotBusy(50)) 
    return ERROR_CODE_X;

*(volatile UINT16 *)& someVar->something;
x = SomeData;
like image 523
µBio Avatar asked Nov 24 '09 19:11

µBio


3 Answers

This is a fairly common idiom in embedded programming (though it should be encapsulated in a set of functions or macros) where a device register needs to be accessed. In many architectures, device registers are mapped to a memory address and are accessed like any other variable (though at a fixed address - either pointers can be used or the linker or a compiler extension can help with fixing the address). However, if the C compiler doesn't see a side effect to a variable access it can optimize it away - unless the variable (or the pointer used to access the variable) is marked as volatile.

So the expression;

*(volatile UINT16 *)&someVar->something;

will issue a 16-bit read at some offset (provided by the something structure element's offset) from the address stored in the someVar pointer. This read will occur and cannot be optimized away by the compiler due to the volatile keyword.

Note that some device registers perform some functionality even if they are simply read - even if the data read isn't otherwise used. This is quite common with status registers, where an error condition might be cleared after the read of the register that indicates the error state in a particular bit.

This is probably one of the more common reasons for the use of the volatile keyword.

like image 142
Michael Burr Avatar answered Sep 24 '22 09:09

Michael Burr


So here's a long shot.

If that address points to a memory mapped region on a FPGA or other device, then the device might actually be doing something when you read that address.

like image 40
Bill Lynch Avatar answered Sep 20 '22 09:09

Bill Lynch


I think the author's intent was to cause the compiler to emit memory barriers at these points. By evaluating the expression result of a volatile, the indication to the compiler is that this expression should not be optimized away, and should 'instantiate' the semantics of access to a volatile location (memory barriers, restrictions on optimizations) at each line where this idiom occurs.

This type of idiom could be "encapsulated" in a pre-processor macro (#define) in case another compile has a different way to cause the same effect. For example, a compiler with the ability to directly encode read or write memory barriers might use the built-in mechanism rather than this idiom. Implementing this type of code inside a macro enables changing the method all over your code base.

EDIT: User sharth has a great point that if this code runs in an environment where the address of the pointer is a physical rather than virtual address (or a virtual address mapped to a specific physical address), then performing this read operation might cause some action at a peripheral device.

like image 39
Heath Hunnicutt Avatar answered Sep 22 '22 09:09

Heath Hunnicutt