Jump to content
    

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

 

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

Edited by Василий Зыков

Share this post


Link to post
Share on other sites

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

 

 

Share this post


Link to post
Share on other sites

...

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

...

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

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

 

Share this post


Link to post
Share on other sites

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

 

Share this post


Link to post
Share on other sites

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

Edited by Шаманъ

Share this post


Link to post
Share on other sites

...:

 

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

Edited by IgorKossak
бездумное цитирование

Share this post


Link to post
Share on other sites

Спасибо вам! Я внес исправления, и все стало как надо!

Share this post


Link to post
Share on other sites

Кстати, я не понял, зачем там __packed. Вроде бы и без этого получится то же самое.

Share this post


Link to post
Share on other sites

Не совсем.

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

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

Share this post


Link to post
Share on other sites

Не совсем.

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

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

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

typedef struct {
...
} FOO_BAR_t;

FOO_BAR_t __packed* ptr;

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...