Software that accesses hardware registers is not always written as clearly as one would like. A cause for this may be the assumption that using an abstraction for the register degrades performance too much. Also such code often lacks good support for testing, which is aggravated by the write-only property of many registers that complicates verifying if the software operates correctly. This article presents the approach that we use to addresses these issues in our software for scanning probe microscopy.
See also my page on our project for Scanning Probe Microscopy.
At nearly the same time, Ken Smith submitted an article draft on register access to Overload titled C++ Hardware Register Access Redux. It's both strikingly similar to my article and quite different at the same time: Take a look!
Ken's article inspired me to add read and write access control to the Register class, as is described below.
In a conversation with Dietmar Kühl at the ACCU Conference 2010 in Oxford (UK), Dietmar mentioned that the Technical Report on C++ Performance (2006) describes an abstraction to access hardware registers. Although I was aware of the report's existence I did not remember this fact. It is unfortunate that the report doesn't rank higher for a search phrase like C++ hardware register access.
A precursor to the technical report seems to be Technical Report on Basic I/O Hardware Addressing by the C++ performance group.
In C++ Hardware Register Access Redux [Smith10], Ken Smith shows how to use all information known about a hardware register to ensure safe and efficient access to it. My article addressed abstraction and efficiency, but lacked attention to the register's read and write properties.
To prevent unsupported access to a register and possible errors as a result, it is desirable to restrict the software's capabilities to those of the register:
To this end you can for example 1) use an read-write (channel) policy in accordance with the register's access properties, 2) adapt a read-write policy to the register's access properties, or 3) bring the access properties of the Register class in line with those of the register.
[Smith10] uses the first method of different mutability policies to provide access to the register that is restricted to register's capabilities, whereas [Moene10] uses the first method to provide full read-write access to it. To add access control to class Register, it now takes the extra access policy template parameter AP. This parameter brings the access properties of the Register class in line with those of the register (3rd method). By keeping the read-write (channel) policy separate from the access restriction policy, it may be easier to substitute one read-write policy for another, for example to support testing. Listing 1 shows a fragment of the adapted Register class.
Listing 1.
namespace spm {
namespace rap {
struct ReadOnly {};
struct WriteOnly {};
struct ReadWrite : public ReadOnly, public WriteOnly {};
} // namespace rap
template
< typename D
, typename A = volatile D*
, typename CP = MemoryChannel<D,A>
, typename AP = rap::ReadWrite
>
class Register
{
...
void write( rap::WriteOnly )
{
m_channel.write( m_address, m_cache );
}
void write()
{
write( AP() );
}
...
};
} // namespace spm
In the review of [Moene10], Overload's editor Ric Parkin mentioned that access to a register can also be restricted to read-only via const-ness of the register access methods in the Register class, such as read(), and use const RegisterType reg. This is a lighter-weight solution than the access policy, that however does not support write-only-ness. An argument against it may be that the very act of reading from a register may change it's contents. All in all I think it can be beneficial to also have this possibility to control access, e.g. if you only use read-write and read-only registers, and I've updated the Register class to this effect.
Source code
The updated source code is available in subdirectory Code2 from the tar.gz archive.
References
[Abrahams06] Dave Abrahams et al..
Technical Report on C++ Performance,
15 February 2006.
[Goodliffe05] Pete Goodliffe.
A Technique for Register Access in C++,
ACCU Overload 68, August 2005.
[Moene10] Martin Moene.
One approach to using hardware registers in C++,
Overload 95, February 2010.
[Smith10] Ken Smith.
C++ Hardware Register Access Redux,
10 February 2010.
Martin Moene