C Регистры маскирования битов

Прошло некоторое время с тех пор, как я программировал на C и не делал никаких битовых масок.

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

Например: $0x00AA всегда должен иметь формат 0b101XXX01, где X можно изменять, а все остальное должно оставаться постоянным. В настоящее время функция принимает адрес и значение и просто устанавливает это значение на этот адрес. Мне нужно изменить его, чтобы даже если функция была передана в 0b11111111 для регистра $0x00AA, она должна была быть установлена ​​​​на 0b10111101. Аналогично, от 0b00000000 до 0b10100001.


person confusedProgrammer    schedule 09.07.2015    source источник
comment
Для этого вы можете использовать побитовые операторы (|, &, ~), особенно версии оператора присваивания (|=, &=).   -  person Medinoc    schedule 09.07.2015
comment
Вы имеете в виду, что вам нужно побитовое И?   -  person user12205    schedule 09.07.2015
comment
Вам необходимо определить, что переданный адрес является одним из ваших защищенных адресов, и в этом случае применить маску к значению перед его установкой. Сколько у вас защищенных адресов и используются ли они где-то еще?   -  person Quentin    schedule 09.07.2015


Ответы (1)


Вы можете сначала замаскировать все, кроме изменяемых битов, с помощью побитового И, а затем добавить постоянные биты с помощью побитового ИЛИ.

void set_register(uint8_t value) {
    const uint8_t MUTABLE_BITS = 0x1C;  // 0b00011100 <- only mutable bits
    const uint8_t CONSTANT_BITS = 0xA1; // 0b10100001 <- constant 1-bits

    value &= MUTABLE_BITS; // remove any non-mutable bits
    value |= CONSTANT_BITS; // add the constant bits
    my_register = value;
}

Этот подход имеет сомнительную особенность жесткого кодирования значения постоянных битов (согласно имени «константа»). Другим подходом было бы установить только изменяемые биты и взять значения для остальных из самого регистра (побитовое И с дополнением маски изменяемых битов), например:

void set_register(uint8_t value) {
    const uint8_t MUTABLE_BITS = 0x1C;  // 0b00011100 <- only mutable bits

    value &= MUTABLE_BITS; // remove any non-mutable bits
    value |= my_register & ~MUTABLE_BITS; // take other bits from register
    my_register = value;
}

(Что касается требования сделать это для нескольких регистров с разными масками, я ожидаю, что их количество будет достаточно ограничено, чтобы вы могли просто устанавливать их один за другим. Если вам действительно нужна функция, которая принимает указатель и значение, затем вы должны сверить этот указатель с известными охраняемыми адресами и каким-то образом получить соответствующую маску. Варианты для этого варьируются от if/else до switch до двоичного поиска и какой-либо хэш-карты.)

person Arkku    schedule 09.07.2015