реклама на сайте
подробности

 
 
> Описание структуры в IAR for ARM, проблема в получении нужного результата
Василий Зыков
сообщение Apr 25 2017, 12:53
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 11-11-06
Из: Екатеринбург
Пользователь №: 22 191



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

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

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

Сообщение отредактировал Василий Зыков - Apr 25 2017, 12:55
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 11)
prottoss
сообщение Apr 25 2017, 13:07
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Код
#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()




--------------------
Go to the top of the page
 
+Quote Post
Alechek
сообщение Apr 25 2017, 13:10
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Цитата(Василий Зыков @ Apr 25 2017, 17:53) *
...
unsigned int DrumSpeed; // скорость вращения
...
склыдывается ощущение, что параметр DrumSpeed стал 4-байтовым, потому что при его изменении в последующие два байта пишутся нули.

А он у Вас какой? Тут АРМы обсуждают а не ПИКи.
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 25 2017, 13:10
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Вот так?
Код
unsigned int DrumSpeed : 16;

Go to the top of the page
 
+Quote Post
prottoss
сообщение Apr 25 2017, 13:11
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(prottoss @ Apr 25 2017, 19:07) *
Код
#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()



--------------------
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Apr 25 2017, 18:51
Сообщение #6


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



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


Сообщение отредактировал Шаманъ - Apr 25 2017, 18:55
Go to the top of the page
 
+Quote Post
Axel
сообщение Apr 26 2017, 04:16
Сообщение #7


Местный
***

Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188



Цитата(Василий Зыков @ Apr 25 2017, 15:53) *
...:


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

Сообщение отредактировал IgorKossak - Apr 26 2017, 07:19
Причина редактирования: бездумное цитирование
Go to the top of the page
 
+Quote Post
Василий Зыков
сообщение Apr 26 2017, 04:33
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 11-11-06
Из: Екатеринбург
Пользователь №: 22 191



Спасибо вам! Я внес исправления, и все стало как надо!
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 26 2017, 07:11
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Кстати, я не понял, зачем там __packed. Вроде бы и без этого получится то же самое.
Go to the top of the page
 
+Quote Post
Alechek
сообщение Apr 26 2017, 09:38
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Не совсем.
у него же typedef, а не готовый объект.
При __packed указатель на этот тип имеет право быть невыровенным
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 26 2017, 11:37
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Alechek @ Apr 26 2017, 12:38) *
Не совсем.
у него же typedef, а не готовый объект.
При __packed указатель на этот тип имеет право быть невыровенным

А вот интересно, если убрать __packed из определения типа и добавить его к объявлению указателя, всё будет работать так же?
Код
typedef struct {
...
} FOO_BAR_t;

FOO_BAR_t __packed* ptr;
Go to the top of the page
 
+Quote Post
Alechek
сообщение Apr 26 2017, 16:10
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Документация по 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;
}
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 01:56
Рейтинг@Mail.ru


Страница сгенерированна за 0.01472 секунд с 7
ELECTRONIX ©2004-2016