Перейти к содержанию
    

Описание структуры в IAR for ARM

Добрый день, коллеги!

 

Работаю в среде 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-байтовым, потому что при его изменении в последующие два байта пишутся нули.

 

Как мне заставить компилятор правильно размещать данные?

Изменено пользователем Василий Зыков

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#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()

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...

unsigned int DrumSpeed; // скорость вращения

...

склыдывается ощущение, что параметр DrumSpeed стал 4-байтовым, потому что при его изменении в последующие два байта пишутся нули.

А он у Вас какой? Тут АРМы обсуждают а не ПИКи.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#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()

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Используйте типы 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()

Изменено пользователем Шаманъ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...:

 

Так все правильно у Вас и получается: 2 байта на битовые поля и 16 байт на все остальное. Или я чего-то не догнал?

Изменено пользователем IgorKossak
бездумное цитирование

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не совсем.

у него же typedef, а не готовый объект.

При __packed указатель на этот тип имеет право быть невыровенным

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не совсем.

у него же typedef, а не готовый объект.

При __packed указатель на этот тип имеет право быть невыровенным

А вот интересно, если убрать __packed из определения типа и добавить его к объявлению указателя, всё будет работать так же?

typedef struct {
...
} FOO_BAR_t;

FOO_BAR_t __packed* ptr;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Документация по 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; 
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...