#c #embedded #device-driver #microcontroller #bit-fields
#c #встроенный #драйвер устройства #микроконтроллер #битовые поля
Вопрос:
Мой вопрос заключается в том, как передать экземпляр битового поля по ссылке на функцию. Я выполнил это, как показано ниже, но когда я запускаю функцию DAC_set_gain_code, процессор выдает ошибку прерывания. Правильно ли то, что я делаю, в том, что касается передачи битового поля?
Я создал битовое поле (см. Ниже), которое представляет 24-битный регистр на микросхеме DAC, в который я хочу записать и который хранится в файле .h.
typedef struct {
uint8_t rdwr_u8: 1;
uint8_t not_used_u8: 3;
uint8_t address_u8: 4;
uint8_t reserved_u8: 8;
uint8_t data_u8: 8;
}GAIN_REG_st;
У меня есть функция, которая инициализирует битовое поле следующим образом:
void init(void)
{
GAIN_REG_st GAIN_x; //Create instance of bitfield
//other code here...
DAC_set_gain_code(channel_u8, gain_code_i8, amp;GAIN_x); //Pass address of bitfield
return;
}
Функция, которая фактически заполняет битовое поле, показана ниже:
void DAC_set_gain_code(uint8_t channel_u8, int8_t gain_code_i8, GAIN_REG_st *GAIN)
{
/* Populate ZERO_REG_st bitfield */
GAIN->rdwr_u8 = 0;
GAIN->not_used_u8 = 0;
if(channel_u8==0){
GAIN->address_u8 = GAIN_REGISTER_0;
}
else if(channel_u8==1){
GAIN->address_u8 = GAIN_REGISTER_1;
}
else if(channel_u8==2){
GAIN->address_u8 = GAIN_REGISTER_2;
}
else if(channel_u8==3){
GAIN->address_u8 = GAIN_REGISTER_3;
}
GAIN->data_u8 = gain_code_i8;
return;
}
Прототипом функции для hal_DAC_set_gain_code_uni является:
void DAC_set_gain_code(uint8_t channel_u8, int8_t gain_code_i8, GAIN_REG_st *GAIN);
Приветствуется любой совет.
Спасибо.
Комментарии:
1. то, что вы опубликовали, возможно, не может быть скомпилировано, или вы не показываете, что вы на самом деле используете (несоответствие имен функций, не отображаются необъявленные переменные и / или глобальные переменные и неиспользуемые параметры)
2. все еще не получается.
ZERO
не определено в том, что вы опубликовали, иGAIN
не используется вDAC_set_gain_code
.3. Извините за ошибки в сообщении. Теперь это должно совпадать с реальным кодом. Мой ГЛАВНЫЙ вопрос в том, правильно ли я передаю ссылку на битовое поле?
4. Мой код компилируется без ошибок, поэтому необъявленные переменные и несовпадения имен функций не являются проблемой.
5. ну, да, вы передаете указатель правильно (в C нет ссылок как таковых). Но опубликованный вами код по-прежнему отличается от того, что у вас есть (у GAIN нет имени элемента
data_u16
. Вы уверены, что ваша программа умирает в этой функции, а не немного позже нее?
Ответ №1:
Поскольку реальное использование этого кода заключается в записи в аппаратный регистр, такие проблемы, как заполнение и выравнивание / упорядочение полей, ИМЕЮТ значение.
Я подозреваю, что компилятор использует 32-разрядные целые числа, и эта структура дополняется до 32 бит, но в самом отлаживаемом коде GAIN_X не является локальной переменной, вы передаете 0XNNNNNNNN (или эквивалент) — и адрес находится не на «правильной» границе (вполне возможно, поскольку это 24-разрядный регистр). Компилятор предположит, что вы передаете указатель на реальный адрес GAIN_REG_st, а не на адрес, определяемый типом, и поэтому, возможно, сделал предположения о выравнивании.
Чтобы получить доступ к оборудованию напрямую из C / C , вам нужно знать, как компилятор обрабатывает подобные вещи, и убедиться, что вы тщательно обманываете компилятор.
Ответ №2:
Может быть, это какая-то проблема с выравниванием?
Может быть, вы можете поиграть с параметрами выравнивания вашего компилятора? Или попробуйте заполнить вашу структуру фиктивным символом uint8
в конце?
Комментарии:
1. Но приведений нет, поэтому это не может быть проблемой выравнивания
2. Да, может возникнуть проблема с выравниванием. Когда дело доходит до битовых полей, C позволяет компилятору выходить из строя и выравнивать совершенно произвольными способами. Вы не можете знать, как выровнено битовое поле, или есть ли в его середине биты / байты заполнения, если вы не прочитали подробно документацию по серверной части компилятора. Существует также последовательность, порядок битов и т.д. и т.п.: бесчисленное множество неопределенных или определяемых реализацией действий. Лучшее решение — вообще не использовать битовые поля.
3. Когда я создаю экземпляр битового поля
GAIN_REG_st GAIN_x
и передаю егоGAIN_x
по ссылке, разве это не тот случай, когда я просто передаю указатель на битовое поле? Таким образом, использование выравнивания не будет проблемой, поскольку я фактически не перемещаю битовое поле в памяти?4. Я не согласен с комментарием Лундина. Компилятор C должен быть в порядке с битовыми полями и передачей указателей на них. Комментарии Лундина могут быть применимы, если вы пытаетесь преобразовать битовые поля в / из других типов, таких как
unsigned char
массивы.5. @Craig Судя по характеру этого битового поля, оно будет использоваться за пределами «необработанного логического буфера». Итак, все упомянутые проблемы могут существовать, а могут и не существовать.