Как правильно читать и писать биты в регистры устройств?

Рейтинг: 0Ответов: 3Опубликовано: 13.02.2011

Ячейка памяти находится по адресу. В этой ячейке интересует первый бит. Я определяю структуру

struct HWRegister
{
    unsigned char _pad: 6;
    unsigned char bit1: 1;
    unsigned char bit0: 1;
};

и использую ее

struct HWRegister *hwr = (struct HWRegister *)0x12345678;

hwr.bit1 = 1;
hwr.bit1 = 0;

У меня профилактический вопрос: это правильных подход? Нет ли здесь чего-то такого, что сразу не бросается в глаза, а потом приведет к ошибкам?

Ответы

▲ 2Принят

An implementation may allocate any addressable storage unit large enough to hold a bit-field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.

стандарт C99, 6.7.2.1, абзац 10

Таким образом, в данном случае ваши поля точно окажутся в пределах одного байта. Другое дело, что размер структуры может быть больше байта, и не определено, будет ли bit0 старшим или младшим.

▲ 2

Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined.

ISO/IEC 14882:2003, 9.6

▲ 2

Если идет обращение к регистру именно устройства, то помимо проблем, связанных с упаковкой и выравниванием, нужно помнить, что перед записью бита в регистр, регистр целиком будет прочитан. А в аппаратуре встречаются регистры, биты которых обнуляются после чтения.

Кроме того, регистры устройств могут меняться независимо от выполнения основного тела программы, поэтому нужно добавить модификатор volatile перед объявлением.

volatile struct HWRegister *hwr;