Accessing hardware with dual-ported memory

Hardware devices with dual-ported memory may "pack" their respective fields on nonaligned boundaries.

For example, if we had a piece of hardware with the following layout, we'd have a problem:

Address

Size

Name

0x18000000

1

PKTTYPE

0x18000001

4

PKTCRC

0x18000005

2

PKTLEN

Let's see why.

The first field, PKTTYPE, is fine—it's a 1-byte field, which according to the rules could
be located anywhere. But the second and third fields
aren't fine. The second field, PKTCRC,
is a 4-byte object, but it's not located on a
4-byte boundary (the address is not evenly divisible by
4). The third field, PKTLEN, suffers
from a similar problem—it's a 2-byte field
that's not on a 2-byte boundary.

The ideal solution would be for the hardware
manufacturer to obey the same alignment rules that are
present on the target processor, but this isn't always
possible. For example, if the hardware presented a raw data
buffer at certain memory locations, the hardware would have
no idea how you wish to interpret the bytes present—it would simply manifest them in memory.

To access these fields, you'd make a set of manifest constants for their offsets:

Of course, if you're writing code that should be portable to
different-endian processors, you'll want to combine the
above tricks with the previous endian macros. Let's define
the hardware as big-endian. In this example, we've decided
that we're going to store everything that the program uses
in host order and do translations whenever we touch the
hardware:

Here's a simple way to remember which ENDIAN_*()
macro to use. Recall that the ENDIAN_*() macros
won't change the data on their respective platforms (i.e.
the LE macro will return the data unchanged on
a little-endian platform, and the BE macro will
return the data unchanged on a big-endian platform).
Therefore, to access the data (which we know has a
defined endianness), we effectively want to select
the same macro as the type of data. This way, if
the platform is the same as the type of data present, no
changes will occur (which is what we expect).