ArcherVZ 0 25 апреля, 2017 Опубликовано 25 апреля, 2017 (изменено) · Жалоба Добрый день, коллеги! Работаю в среде IAR for ARM 7.5 - программа под микроконтроллер STM32F103 На этот раз я столкнулся с такой проблемой: есть описание некоторой структуры typedef __packed struct { unsigned int Type:4; // код типа операции unsigned int Pause:1; // разрешение паузы до выполнения шага unsigned int DrainGate1:1; // разрешение клапана 1 unsigned int DrainGate2:1; // разрешение клапана 2 unsigned int ReservedBits:9; // зарезервированные биты unsigned int DrumSpeed; // скорость вращения unsigned char Time; // время вращения unsigned char Reserved[11]; // зарезервированные байты } WPC_SPIN_t; я ожидаю получить размер структуры 16 байт и следующее размещение данных: xx xx sl sh tt xx xx xx xx xx xx xx xx xx xx xx где xx - просто байт sl - младший байт скорости sh - старший байт скорости tt - время вращения На деле же я получаю размер структуры 18 байт и размещение байт, как показано ниже: xx xx sl sh 00 xx tt xx xx xx xx xx xx xx xx xx т.е. байт с временем перемещается на две позиции... а вместо него пишутся нули склыдывается ощущение, что параметр DrumSpeed стал 4-байтовым, потому что при его изменении в последующие два байта пишутся нули. Как мне заставить компилятор правильно размещать данные? Изменено 25 апреля, 2017 пользователем Василий Зыков Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 25 апреля, 2017 Опубликовано 25 апреля, 2017 · Жалоба #pragma pack(1) typedef struct { unsigned int Type:4; // код типа операции unsigned int Pause:1; // разрешение паузы до выполнения шага unsigned int DrainGate1:1; // разрешение клапана 1 unsigned int DrainGate2:1; // разрешение клапана 2 unsigned int ReservedBits:9; // зарезервированные биты unsigned int DrumSpeed; // скорость вращения unsigned char Time; // время вращения unsigned char Reserved[11]; // зарезервированные байты } WPC_SPIN_t; #pragma pack() Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alechek 0 25 апреля, 2017 Опубликовано 25 апреля, 2017 · Жалоба ... unsigned int DrumSpeed; // скорость вращения ... склыдывается ощущение, что параметр DrumSpeed стал 4-байтовым, потому что при его изменении в последующие два байта пишутся нули. А он у Вас какой? Тут АРМы обсуждают а не ПИКи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 25 апреля, 2017 Опубликовано 25 апреля, 2017 · Жалоба Вот так? unsigned int DrumSpeed : 16; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
prottoss 0 25 апреля, 2017 Опубликовано 25 апреля, 2017 · Жалоба #pragma pack(1) typedef struct { unsigned int Type:4; // код типа операции unsigned int Pause:1; // разрешение паузы до выполнения шага unsigned int DrainGate1:1; // разрешение клапана 1 unsigned int DrainGate2:1; // разрешение клапана 2 unsigned int ReservedBits:9; // зарезервированные биты unsigned int DrumSpeed; // скорость вращения unsigned char Time; // время вращения unsigned char Reserved[11]; // зарезервированные байты } WPC_SPIN_t; #pragma pack() Ой. не верно. Извиняюсь. Битовые поля у Вас запакуются в 32-бит переменную. DrumSpeed тоже будет 32-бит. Нужно вот так: #pragma pack(1) typedef struct { unsigned short Type:4; // код типа операции unsigned short Pause:1; // разрешение паузы до выполнения шага unsigned short DrainGate1:1; // разрешение клапана 1 unsigned short DrainGate2:1; // разрешение клапана 2 unsigned short ReservedBits:9; // зарезервированные биты unsigned short DrumSpeed; // скорость вращения unsigned char Time; // время вращения unsigned char Reserved[11]; // зарезервированные байты } WPC_SPIN_t; #pragma pack() Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Шаманъ 1 25 апреля, 2017 Опубликовано 25 апреля, 2017 (изменено) · Жалоба Используйте типы uint8_t, uint16_t, uint32_t и другие из <stdint.h>, если Вам нужно задать конкретный размер поля, ну и про упакованные структуры тоже не стоит забывать. Как-то так: #pragma pack(1) typedef struct { uint16_t Type:4, // код типа операции Pause:1, // разрешение паузы до выполнения шага DrainGate1:1, // разрешение клапана 1 DrainGate2:1, // разрешение клапана 2 ReservedBits:9; // зарезервированные биты uint16_t DrumSpeed; // скорость вращения uint8_t Time; // время вращения uint8_t Reserved[11]; // зарезервированные байты } WPC_SPIN_t; #pragma pack() Изменено 25 апреля, 2017 пользователем Шаманъ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Axel 1 26 апреля, 2017 Опубликовано 26 апреля, 2017 (изменено) · Жалоба ...: Так все правильно у Вас и получается: 2 байта на битовые поля и 16 байт на все остальное. Или я чего-то не догнал? Изменено 26 апреля, 2017 пользователем IgorKossak бездумное цитирование Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ArcherVZ 0 26 апреля, 2017 Опубликовано 26 апреля, 2017 · Жалоба Спасибо вам! Я внес исправления, и все стало как надо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 26 апреля, 2017 Опубликовано 26 апреля, 2017 · Жалоба Кстати, я не понял, зачем там __packed. Вроде бы и без этого получится то же самое. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alechek 0 26 апреля, 2017 Опубликовано 26 апреля, 2017 · Жалоба Не совсем. у него же typedef, а не готовый объект. При __packed указатель на этот тип имеет право быть невыровенным Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 26 апреля, 2017 Опубликовано 26 апреля, 2017 · Жалоба Не совсем. у него же typedef, а не готовый объект. При __packed указатель на этот тип имеет право быть невыровенным А вот интересно, если убрать __packed из определения типа и добавить его к объявлению указателя, всё будет работать так же? typedef struct { ... } FOO_BAR_t; FOO_BAR_t __packed* ptr; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Alechek 0 26 апреля, 2017 Опубликовано 26 апреля, 2017 · Жалоба Документация по IAR дает однозначный ответ: IAR C/C++ Development Guide Compiling and Linking for ARM Example /* No pad bytes in X: */ __packed struct X { char ch; int i; }; /* __packed is optional here: */ struct X * xp; /* NOTE: no __packed: */ struct Y { char ch; int i; }; /* ERROR: Y not defined with __packed: */ __packed struct Y * yp; /* Member 'i' has alignment 1: */ struct Z { char ch; __packed int i; }; void Foo(struct X * xp) { /* Error:"int *" -> "int __packed *" not allowed: */ int * p1 = xp->1; /* OK: */ int __packed * p2 = &xp->i; /* OK, char not affected */ char * p3 = &xp->ch; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться