Re: bit fields and data structure
On Nov 17, 10:48 am, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 17, 1:53 am, ma740988 <ma740...@gmail.com> wrote:
I often peruse source that use memory mapped registers as a
configuration and/or command and status interface between
embedded software and FPGA logic. In doing so you're given
a register name accompanied by descriptions and a location
in memory for reading/ writing data.
For ex:.
Revision Register - Location 0x0000
[31...15] spare
[14...00] number
Control Register - Location 0x0001
[31..3] -- Spare
[2] -- Address Line 3
[1] -- Address Line 2
[0] -- Address Line 1
To describe these registers in source one could do:
struct RevisionRegister {
unsigned short number : 16;
unsigned short spare : 16;
};
struct ControlRegister {
unsigned int Spare : 29;
unsigned short AddressLine3 : 1;
unsigned short AddressLine2 : 1;
unsigned short AddressLine1 : 1 ;
} ;
Maybe. How a compiler lays out bitfields is implementation
defined.
The trouble with the composite type ControlRegister is sizeof
(ControlRegister) is not 32 bits.
It is with my compilers. But it definitely depends on the
compiler; a compiler for a 16 bit machine is likely to
systematically put any bit field greater or equal to 16 bits in
a separate word.
It is because bit-fields of different type can not be merged.
Since when? Both g++ and Sun CC merge them, under Solaris.
Fix:
struct ControlRegister {
unsigned Spare : 29;
unsigned AddressLine3 : 1;
unsigned AddressLine2 : 1;
unsigned AddressLine1 : 1 ;
} ;
It would be a pretty poor implementation which generated a
different layout for these two. I'm not even sure it's legal.
(The actual layout is implementation defined, and the standard
isn't really clear about the restrictions, if any. But laying
out these two differently certainly violates the spirit of the
standard, if not the actual wording.)
That said, its not possible to receive ControlRegister in
it's current form from an end user and overlay it at the
appropriate location. The fundamental issue surrounds the
use of bitfields and implementation defined nature of POD
types. The question: What are some of the - if you will -
tips for dealing with this issue?
Another issue is that bit-field bit order can be little or
big-endian depending on the platform and the compiler.
The layout is implementation defined, with very few
restrictions. But if you're reading and writing memory mapped
registers, portability is presumably not a concern. And
implementation defined means documented, so you know what the
compiler does. For any one particular version of the compiler,
of course, but from a QoI point of view, no reasonable compiler
will change the basic principles from one version to the next.
(Although... I've seen changes more radical than that, like the
byte order in a long. From a QoI point of view, the quality
wasn't there, but it was still the compiler we had to use.)
A portable way to read mapped registers is to read the
register, convert it from the byte order of the hardware that
exposes that register into the byte order of the cpu (if byte
orders are the same this is a noop), and then apply mask by
using bitwise and operator to extract the interesting bits.
This way you don't depend on the bit-field bit order.
"A portable way to read mapped registers"? Sounds like an
oxymoron to me.:-)
Seriously, of course, such problems don't affect just mapped
registers, and this is the way to solve them portably in other
cases (transmission protocols, etc.). The register is slightly
different, in that you can (maybe) read and write words, and not
just bytes, but other than that, the principles are the same.
Using bit fields results in less and cleaner code, but it only
works for mapped registers, and only then if your compiler does
something reasonable, and documents it. (If it doesn't, he
might want to consider changing compilers; under Windows, VC++
is more or less broken with regards to bit fields, but g++ works
fine.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=C3=A9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=C3=A9mard, 78210 St.-Cyr-l'=C3=89cole, France, +33 (0)1 30 23 00 =
34