Я прочитал некоторые из предыдущих вопросов и связанных с ними ответов относительно битовых структур. Подавляющее большинство состоит в том, что выравнивание и упаковка битов зависят от компилятора.
В настоящее время я адаптирую часть кода Maxim / Mbed для микросхемы ЭКГ MAX30003. Этот чип имеет внутренние 32-битные регистры, доступ к которым осуществляется через SPI. Я адаптирую код к платформе "esp-idf ESP32 Arduino". Разработка ведется с использованием IDE VSCODE (windows10).
Максим использует следующую структуру для доступа к а) 32 битам как uint32_t и б) внутренним битам как отдельным битовым маскам. Подпрограмма max30001_reg_read () считывает все биты из внутреннего регистра в член структуры uint32_t ' .all '. Точно так же процедура max30001_reg_write () передает все биты из « .all » в регистр устройства. Битовые поля устанавливаются / очищаются с использованием членов ' .bit.nnnn '. Я не видел в исходном коде атрибутов __ __ ((упаковано)) или # pragma pack (n) .
Он правильно портирован и устанавливает правильные битовые поля. Таких регистров примерно 20.
Мой вопрос: это просто удачный случай или в этих двух компиляторах есть что-то, что правильно выравнивает битовые поля?
/**
* @brief CNFG_GEN (0x10)
*/
union max30001_cnfg_gen_reg {
uint32_t all;
struct {
uint32_t rbiasn : 1;
uint32_t rbiasp : 1;
uint32_t rbiasv : 2;
uint32_t en_rbias : 2;
uint32_t vth : 2;
uint32_t imag : 3;
uint32_t ipol : 1;
uint32_t en_dcloff : 2;
uint32_t en_bloff : 2;
uint32_t reserved1 : 1;
uint32_t en_pace : 1;
uint32_t en_bioz : 1;
uint32_t en_ecg : 1;
uint32_t fmstr : 2;
uint32_t en_ulp_lon : 2;
uint32_t reserved : 8;
} bit;
} max30001_cnfg_gen;
int MAX30001::max30001_Rbias_FMSTR_Init(uint8_t En_rbias, uint8_t Rbiasv,
uint8_t Rbiasp, uint8_t Rbiasn,
uint8_t Fmstr) {
if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
return -1;
}
max30001_cnfg_gen.bit.en_rbias = En_rbias;
max30001_cnfg_gen.bit.rbiasv = Rbiasv;
max30001_cnfg_gen.bit.rbiasp = Rbiasp;
max30001_cnfg_gen.bit.rbiasn = Rbiasn;
max30001_cnfg_gen.bit.fmstr = Fmstr;
if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
return -1;
}
return 0;
}