|
|
  |
Приведение типа указателя на элемент структуры |
|
|
|
Oct 17 2012, 10:51
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Допустим, имеется структура из байтов. Хочу инициализировать сразу 2 байта 16-битовым числом, или сразу 4 байта 32-битовым числом. Привожу указатель к нужному типу. Код typedef struct { __IO uint8_t A; __IO uint8_t B; uint16_t RES; } DEV_t;
DEV_t Dev; DEV_t *pDev = &Dev;
pDev->A = 0x55; pDev->B = 0xAA; (uint16_t)pDev->A = 0x3333; (uint32_t)pDev->A = 0x01234567; Код работает. Но Keil выдает предупреждения: source\Exercises.c(117): warning: #1441-D: nonstandard cast on lvalue Есть ли способ написать так, чтобы Keil не возмущался?
|
|
|
|
|
Oct 17 2012, 11:36
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(AHTOXA @ Oct 17 2012, 14:27)  Но это хак, работоспособность которого зависит от выравнивания элементов структуры. Надо по крайней мере комментарий про это написать рядышком Для того и вводятся резервные места, ну, как в stm32xxx.h Код typedef struct { __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ __IO uint8_t IDR; /*!< CRC Independent data register, Address offset: 0x04 */ uint8_t RESERVED0; /*!< Reserved, 0x05 */ uint16_t RESERVED1; /*!< Reserved, 0x06 */ __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ } CRC_TypeDef; По такой аналогии и создавал. Правильное заполнение структуры будет обеспечено, а обращение возможно по любому (невыровненному) адресу. Cortex-M3 же.
|
|
|
|
|
Oct 17 2012, 12:43
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(_Артём_ @ Oct 17 2012, 15:58)  А на каких архитектурах при таком обращении возникнут проблемы (и какие)? На многих, отличных от 8 бит. Например, MSP430. По умолчанию выравнивание по границе слова. Выровненный char займет 2 байта, старший байт 16р инициализатора вместо второго чара улетит в пустоту Цитата(ViKo @ Oct 17 2012, 16:20)  я описываю в структуре регистры внешнего устройства, в частности, контроллера ЖКИ. Вот в таком случае аттрибут упаковки строго обязателен. Иначе такие чудеса могут начаться.. Пишешь байт в один регистр, а он улетает в соседний или через несколько Конечно, не ваш конкретный случай, но все же
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 17 2012, 13:10
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(MrYuran @ Oct 17 2012, 15:54)  А неважно. Выровняет по границе машинного слова (16/32/64) - и все ваши RESERVED превратятся в дополнительные 16/32/64р "дыры" Не выравняет.  Потому что имеется следующий код. Код typedef struct { __I uint8_t RCR; //<! Revision Code Register, 0x00 __I uint8_t DBSR; //<! Dislpay Buffer Size Register, 0x01 __I uint8_t CRR; //<! Configuration Readback Register, 0x02 } ReadOnlyConf_t; //<! Read-Only Configuration Registers
typedef struct { __IO uint8_t MCCR; //<! Memory Clock Configuration Register, 0x04 __IO uint8_t PCCR; //<! Pixel Clock Configuration Register, 0x05 } ClockConf_t; //<! Clock Configuration Registers ...
#define DPYCTRL_BASE ((uint32_t)0x6C000000) //<! Dysplay base address #define S1DREGS_BASE DPYCTRL_BASE //<! S1D13706 registers base
#define READONLYCONF_BASE S1DREGS_BASE #define CLOCKCONF_BASE S1DREGS_BASE + 0x04 #define LOOKUPTABLE_BASE S1DREGS_BASE + 0x08 ... #define READONLYCONF ((ReadOnlyConf_t *) READONLYCONF_BASE) #define CLOCKCONF ((ClockConf_t *) CLOCKCONF_BASE) #define LOOKUPTABLE ((LookUpTable_t *) LOKUPTABLE_BASE) ... А дальше - обращения по указателям...
|
|
|
|
|
Oct 17 2012, 15:18
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(ViKo @ Oct 17 2012, 14:36)  Для того и вводятся резервные места, ну, как в stm32xxx.h Не надо брать пример с индуистского кода. Правильный ответ(причем, всегда) Код typedef struct { __IO uint32_t DR; /*!< CRC Data register, Address offset: 0x00 */ union { __IO uint8_t reg8bit; /*!< CRC Independent data register, Address offset: 0x04 */ uint32_t IDR_space; } IDR; __IO uint32_t CR; /*!< CRC Control register, Address offset: 0x08 */ } CRC_TypeDef; Почему у них идеологически не так? Патамушо эти хедеры не для того, чтобы ими пользоваться!
|
|
|
|
|
Oct 17 2012, 16:21
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(_Артём_ @ Oct 17 2012, 18:44)  Интересно, а чем же пользоваться? Самому хидеры на процы делать? Я тут давеча психанул и наваял по означенному выше принципу. Ессно, только структуры, без всяких функций сомнительного сервиса. Но у проекта, который сейчас пилю, уже поезд ушел, тестинг откладывается. Странно, но LPC такой ненависти не вызывают. Очень странно...  Вообще, я там сильно повыделывался - дал битовым полям осмысленные имена... там по-хорошему надо двуязычие, тоже на основе union{}- с сохранением мнемоники и с сохранением смысла... этот момент разрулю - будет тыщи три строк. И вроде бы взять да и сделать базу в libreoffice base, чтоб генерило то,что надо... блин, лень забадала.
Сообщение отредактировал _Pasha - Oct 17 2012, 16:27
|
|
|
|
|
Oct 17 2012, 17:31
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(_Pasha @ Oct 17 2012, 18:18)  Не надо брать пример с индуистского кода. Правильный ответ(причем, всегда) ... Я тоже кинулся было править stm32f2xx.h, когда увидел, что не могу одной командой установить и сбросить биты в порту. Из-за Код ... __IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */ __IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */ // __IO uint32_t BSRR; // GPIO port bit set/reset: 0xRRRRSSSS, Address offset: 0x18 ... } GPIO_TypeDef; Причем, BSRRL отвечает за установку бита, а BSRRH - за сброс. Но при пользовании объединениями в имени регистра появляется дополнительное обозначение, которого не хочу. Поэтому приведение типа указателя для меня более приемлемо. А насчет библиотеки - функциями не пользуюсь. А насчет определения битов - #define меня устраивают. Главное, чтобы код не разбухал.
|
|
|
|
|
Oct 17 2012, 17:47
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
Итак, добавляю  есть две области в ARM968E-S в первой висит 16-битный супресс USB, во второй - NOR Flash Читается/пишется в первую область только по/из фиксированным адресам Во вторую - и так, и с инкрементом оптимизация компилятора в Time и O3 Шины. 1-я с супрессом - 16бит, 2-я - 32 бит Что-то фигню наблюдаю Первая область объявлена как Код #define FX2_FIFO2 (*(volatile unsigned int *)(FX2_BASE_ADDR + (0x00UL<<2))) #define FX2_FIFO4 (*(volatile unsigned int *)(FX2_BASE_ADDR + (0x02UL<<2))) вторая - также через volatile, но в своем диапазоне Доступ к памяти осцилл показывает и, судя по тестам, точно как и надо А вот данные - не пойми чего Для пересылки и сокращения доступа к той и другой области памяти попробовал сделать union с тремя полями - U16, U16 и U32 Например, чтение из первой области - в две U16 подряд, потом из U32 - в другую область запись Шаманство  Не работает
|
|
|
|
|
Oct 17 2012, 18:22
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(ViKo @ Oct 17 2012, 20:31)  Я тоже кинулся было править stm32f2xx.h, когда увидел, что не могу одной командой установить и сбросить биты в порту. Из-за[кусь] Поэтому приведение типа указателя для меня более приемлемо. Не пойму, кто заремил BSRR, милое дело © Код Inline void pin_set_by_msk(const GPIO_typedef *port, const uint16_t msk, const bool state) { port->BSRR = state?(msk):(msk<<16); } компиляется в минимум,- жаль, редко, когда в две-это при интенсивных операциях -инструкции
Сообщение отредактировал _Pasha - Oct 17 2012, 18:24
|
|
|
|
|
Oct 17 2012, 18:33
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(_Pasha @ Oct 17 2012, 21:22)  Не пойму, кто заремил BSRR, милое дело © Я же и закомментировал. Сам приписал, сам убрал. Когда возникла дилемма - или писать всегда по 32 бита, или писать, когда надо, по 16-битов. В-общем, надо было иметь и ту, и другую возможность. А union ... уже говорил ... А *(uint32_t *) &GPIOB.BSRRL - то шо надо!
|
|
|
|
|
Oct 17 2012, 18:35
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(_Pasha @ Oct 18 2012, 00:22)  Не пойму, кто заремил BSRR, милое дело © Дык, индусы, кто ж ещё  Причём битовые маски оставили как для 32-битного BSRR. (Это для F2xx.) Я всё же такого не стерпел, и переписал это определение. _Pasha, так в каком случае индуистский подход с ручными отступами в структурах может привести к неправильному результату? Или здесь речь чисто об эстетике?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Oct 17 2012, 18:50
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(AHTOXA @ Oct 17 2012, 21:35)  _Pasha, так в каком случае индуистский подход с ручными отступами в структурах может привести к неправильному результату? Или здесь речь чисто об эстетике?  Вообще-то подозрения в выравнивании - не мои. Если MrYuran сталкивался, думаю, он поделится. Хотя, странно -fpack-struct=8 должен бы, как представляется... Я только выразил недоумение по поводу головоломок там, где их быть не должно, при передвижении на круглых колесах, тсз.
Сообщение отредактировал _Pasha - Oct 17 2012, 18:52
|
|
|
|
|
Oct 17 2012, 18:59
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(_Pasha @ Oct 18 2012, 00:50)  Вообще-то подозрения в выравнивании - не мои. Если MrYuran сталкивался, думаю, он поделится. А в чём тогда "правильность" кода с union-ами? Цитата(_Pasha @ Oct 18 2012, 00:50)  Хотя, странно -fpack-struct=8 должен бы, как представляется... Как я понял, -fpack-struct[=x] может только сильнее упаковать структуру. Проредить её может __attribute__ ((aligned (x))). Но его нужно явно указывать для члена структуры, случайно так не сделать.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Oct 17 2012, 19:17
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(AHTOXA @ Oct 17 2012, 21:59)  А в чём тогда "правильность" кода с union-ами? В данном случае - чисто йуридически Цитата warning: #1441-D: nonstandard cast on lvalue Где оно выползет боком - фантазии не хватает представить. Для АРМов сумасшедшие компиляторы а-ля CodeVision для АВРок - существуют? Если бы были - там бы и повылезло.
Сообщение отредактировал _Pasha - Oct 17 2012, 19:20
|
|
|
|
|
Oct 17 2012, 20:22
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 22-04-10
Пользователь №: 56 826

|
Цитата(_Pasha @ Oct 17 2012, 20:21)  Я тут давеча психанул и наваял по означенному выше принципу. Ессно, только структуры, без всяких функций сомнительного сервиса. Но у проекта, который сейчас пилю, уже поезд ушел, тестинг откладывается. Простите а вот под какой контроллер вы так сделали?
|
|
|
|
|
Oct 17 2012, 20:53
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 22-04-10
Пользователь №: 56 826

|
Цитата(_Pasha @ Oct 18 2012, 00:39)  STM32f100 Но, сделал - и пожалел. Надо сразу базу данных заводить и оттуда генерить. Писанина - плохой стиль. А разве производитель CMSIS ные либы со структурами не создаёт для регистров данного контроллера или у Вас свои какие-то структуры?
|
|
|
|
|
Oct 18 2012, 03:39
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(_Pasha @ Oct 18 2012, 01:17)  В данном случае - чисто йуридически Да нет же, я не об этом!  Там ViKo просто не то не к тому привёл. Я вот о чём. Чем ваш вариант Код typedef struct { __IO uint32_t DR; union { __IO uint8_t reg8bit; uint32_t IDR_space; } IDR; __IO uint32_t CR; } CRC_TypeDef; лучше индуистского варианта Код typedef struct { __IO uint32_t DR; __IO uint8_t reg8bit; __IO uint8_t spacer; __IO uint16_t spacer2; __IO uint32_t CR; } CRC_TypeDef; ?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Oct 18 2012, 05:12
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(_Pasha @ Oct 17 2012, 22:50)  Вообще-то подозрения в выравнивании - не мои. Если MrYuran сталкивался, думаю, он поделится. Сталкивался, не то слово. MSPGCC образца 2008 года и iostructures.h Причем, там явно было указано __attribute__ (("packed")) под каждой структурой, однако ж.. После серии необъяснимых чудес пришлось лезть в листинг и сверять адреса регистров. Помогло только -fpack-struct, когда все структуры принудительно упаковывались. После того все переписал на макросы Волкова. Конечно, не так красиво, зато работает железно. Хотя, сейчас поглядел... Код #if defined(__MSP430_HAS_PORT0__) struct port0_t { ioregister_t in; /* Input */ ioregister_t out; /* Output */ ioregister_t dir; /* Direction */ ioregister_t ifg; /* Interrupt Flag */ ioregister_t ies; /* Interrupt Edge Select */ ioregister_t ie; /* Interrupt Enable */ };
__MSP430_EXTERN__ struct port0_t port0 asm("0x0010"); #endif Здесь почему-то упаковки нет.. Странно.. Это в корне меняет дело, а я на компилятор грешил. Но суть то этого не меняется. Автоматически выровненная структура "прореживается" и все адреса сползают.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 18 2012, 06:14
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(MrYuran @ Oct 18 2012, 11:12)  Это в корне меняет дело ... Но суть то этого не меняется. Жжоте Тем не менее. test.c: Код typedef struct { unsigned char a; unsigned char b; }str;
char zzz[1 - 2*(sizeof(str) != 2)]; gcc -c test.c - порядок. avr-gcc -c test.c - порядок. arm-kgp-gcc -c test.c - порядок. arm-none-eabi-gcc -c test.c - порядок. msp430-gcc -c test.c - порядок. Что надо сделать, чтобы "проредило"?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Oct 18 2012, 06:25
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(AHTOXA @ Oct 18 2012, 10:14)  Что надо сделать, чтобы "проредило"? Я не знаю, что надо сделать, но точно знаю теперь, чего не надо.. Не надо использовать такие структуры без принудительной упаковки, во избежание. Мне совершенно было не смешно, когда port1.out.pin3 = 1 махал битами в регистре dir вместо out (а это ещё надо было найти)
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Oct 18 2012, 07:49
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(MrYuran @ Oct 18 2012, 12:25)  Я не знаю, что надо сделать, но точно знаю теперь, чего не надо.. Не надо использовать такие структуры без принудительной упаковки, во избежание. Мне совершенно было не смешно, когда port1.out.pin3 = 1 махал битами в регистре dir вместо out (а это ещё надо было найти) Скорее всего был локальный глюк какой-то конкретной версии mspgcc. Хотя принудительная упаковка - дело несложное, можно и её добавить, для пущей уверенности. Цитата(Палыч @ Oct 18 2012, 12:55)  Вставить #pragma pack(n) или указать транслятору -fpack-struct=n cо значением n отличным от 1. К сожалению, в документации на gcc нигде нет упоминания: какое значение n (величина выравнивания) принято "по-умолчанию"... Нет, ничего из этого не увеличивает размер структуры. Проверил и с #pragma pack(x), и с -fpack-struct=x (x={4,8,16,32}), и с ними обоими одновременно. До кучи проверил __attribute__ ((packed)) и __attribute__ ((aligned (x))) для типа. Размер структуры равен 2, как я не извращался  Единственный вариант, который изменил размер, был вот такой: Код typedef struct { unsigned char a __attribute__ ((aligned (8))); unsigned char b __attribute__ ((aligned (8))); }str; Но этот вариант не страшен, потому что явно указывать alignment там, где он не нужен, мы не будем. Цитата(_Pasha @ Oct 18 2012, 13:44)  Дык я это "не то не к тому" унаследовал, пытаясь сказать, что сабжевое приведение - лишняя суета и потенциальный источник проблем. А, вон оно что! Теперь понял
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Oct 18 2012, 08:23
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Вообще то компиляторы упаковывают структуры не от их [компилятора] большого желания, а от требования выполнить ограничения по выравниванию для полей этих самых структур. Так что, если у вас в структуре нет полей с требованиями по выравниванию (например у вас там все char) - то ничего выравниваться и не будет. А вот если есть - то перед этим полем может появится дыра, и вся структура в целом получит ограничение по выравниванию, как для этого поля (что в свою очередь может добавить дыру и в конце структуры) Например (предполагаю требования по выравниванию на размер поля): Код struct { int8_t f8; int16_t f16; int32_t f32; int8_t f8_2; }; // Превратится в struct { int8_t f8; int :8; // Выравнивание для f16 на границу 2х байтов int16_t f16; int :16; // Выравнивание для f32 на границу 4х байтов int32_t f32; int8_t f8_2; int :24; // Выравнивание размера всей структуры, как требует поле f32 };
|
|
|
|
|
Oct 18 2012, 08:45
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Палыч @ Oct 18 2012, 14:16)  А теперь попробуйте проверить на такой структуре: Да, но речь шла о структурах, уже имеющих вручную сформированные отступы, типа такой: Код typedef struct { uint8_t a; uint8_t padder1; // - отступ uint16_t b; uint16_t padder2; // - отступ uint32_t c; }str; Такие структуры используются, в частности, в заголовочных файлах от ST для описания периферии процессоров STM32. И меня интересует вопрос, могут ли такие структуры при каких-либо условиях перестать соответствовать описываемой ими периферии. Пока получается, что всё нормально, соответствуют при любых ключах компиляции. (Ну, кроме непонятного случая, описанного MrYuran-ом)
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Oct 18 2012, 12:23
|

Профессионал
    
Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877

|
Цитата(Палыч @ Oct 18 2012, 10:55)  Вставить #pragma pack(n) или указать транслятору -fpack-struct=n cо значением n отличным от 1. Раз тут пошли "страшные истории"... pragma pack(n) надо обязательно закрывать pragma pack() При включении заголовка с незакрытой прагмой такие интересные косяки проявляются - все структуры в одном модуле сами собой "упаковываются", а в другом - остаются неупакованными, в зависимости от последовательности #include. Пример для наглядности: Код a.h: #pragma pack (1)
b.h typedef struct .... b_struct;
a.c #include "a.h" #include "b.h" b_struct A;
b.h #include "b.h" b_struct B; Так вот, A и B получились РАЗНЫЕ, хотя этого вряд-ли кто-то добивался :-) Короче, плохая это прагма, не ленитесь писать атрибуты для каждой структуры.
--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
|
|
|
|
|
Oct 18 2012, 14:47
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(AHTOXA @ Oct 18 2012, 11:45)  Пока получается, что всё нормально, соответствуют при любых ключах компиляции. (Ну, кроме непонятного случая, описанного MrYuran-ом) Там, я так понял, ещё битовые поля были в подструктурах ioregister_t. Что-то могло и на этом набежать. Скажем, Код typedef { unsigned f : 1; } flag_t;
typedef { flag_t a; flag_t b; } flags2_t; структура flags2_t займёт 2*sizeof(unsigned), а не один байт. Причём никакие pack не помогут.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Oct 18 2012, 15:51
|
Гуру
     
Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954

|
Цитата(esaulenka @ Oct 18 2012, 19:23)  Короче, плохая это прагма, не ленитесь писать атрибуты для каждой структуры а если есть некая структура Код typedef struct{ u8 b; u32 c; u8 d; u16 a; } t_struct_A; и указатель Код t_struct_A * p; который еще потом может вдруг оказаться совсем невыровненным, ну там преамбула например частично потерялась: Код u8 buff[100500]; p = &buff[17]; в каком именно месте и какие прагмы должны стоять чтобы p->c = 0xABCD1234; нормально работало всегда и везде? или так лучше вообще не делать, а данные просто макросами по байтам по смещениям вытаскивать чтобы ни от платформы ни от компилятора не зависеть?
|
|
|
|
|
Oct 19 2012, 04:41
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(AHTOXA @ Oct 18 2012, 19:20)  Можно безбоязненно пользоваться структурами от ST? Если программируем аппаратные средства микроконтроллеров STM32xxx, то используются не структуры, а указатели на типы структур, расположенные по фиксированным адресам. Если просто пользуемся структурами, подобными предложенным ST, то не все ли равно, как упакованы данные? Куда записали, оттуда и прочитаем.
|
|
|
|
|
Oct 19 2012, 09:27
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(AHTOXA @ Oct 19 2012, 10:31)  Так вот я и выясняю, не может ли она после этого разъехаться ещё больше  Представьте, что есть ключ компилятора, который каждый байт в структуре выравнивает на границу слова. С таким ключом всё наше растягивание пойдёт насмарку. Самое простое - не морочить, а заложить где-то assert, только вот что лучше проверять: небось, sizeof какой-то тестовой структуры, не обязательно прям-таки осмысленной и привязанной к реальным портам, но с использованием всех индуистских _IO32 и прочая.
|
|
|
|
|
Oct 19 2012, 09:32
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
К счастью, в железе STM32 адреса устройств уже распределены так, что "упаковываются" в структурах согласно своему естественному размеру, int16_t по границам полуслова, int32_t по границам слова. Во всяком случае, я не заметил, чтобы где-то в stm32fxx.h было не так. Поэтому, если не насиловать компилятор прагмами pack(n), ничто расползаться не должно. А __packed может только утоптать структуру, но не раздвинуть ее. А от этого мы уже защитились RESERVED. Так, вроде?
|
|
|
|
|
Oct 19 2012, 09:57
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(ViKo @ Oct 19 2012, 12:32)  К счастью, в железе STM32 [...] В принципе, тут зацепились мы за платформенно-независимый вопрос. Цитата Поэтому, если не насиловать компилятор прагмами pack(n) ... а также приведением типов указателей на элемент структуры  ...
|
|
|
|
|
Oct 26 2012, 20:10
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
Цитата(ViKo @ Oct 17 2012, 09:51)  Допустим, имеется структура из байтов. Хочу инициализировать сразу 2 байта 16-битовым числом, или сразу 4 байта 32-битовым числом. Привожу указатель к нужному типу Похоже, при формировании структуры си-компилятор находит элемент с максимальной длиной и выделяет каждому элементу структуры размер памяти, равный максимальной длине. По крайней мере, для кейловского компилятора я это доказал. Выделил структуру typedef struct { unsigned long VARA; unsigned char VARB; unsigned int VARC; } CRCSTRUCT; CRCSTRUCT STRD; и в дибаггере стал туда писать побайтно, начиная с VARА. В VARА записалось 4 байта, как и ожидалось, в VARВ записался один байт, остальные три писались в никуда и не отображались, в VARC записалось два байта, остальные записались в никуда. Так что дырки в структурах всегда будут, если структура содержит элементы разной длины.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Nov 9 2012, 18:48
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Есть Грабля! CODE typedef struct { char id[2]; uint32_t size; char reserved[4]; uint32_t offset; uint32_t bmp_infolen; uint32_t width; uint32_t height; uint16_t planes;//number of uint16_t bits_per_pix; uint32_t compress_type; uint32_t picture_size; uint32_t Hresolution; uint32_t Vresolution; uint32_t used_colors; uint32_t important_colors; } bmp_header_t; Компилим Код gcc версия 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) с дефолтными настройками code::blocks (уверяю, там ничего страшного нету, выравнивание нигде принудительно не включено) Пишет после bmp_header.id два нулевых байта, также при выводе его размера показывает 56 байт супротив 54-х. В общем, подарок для АНТОХИ.  ЗЫ причем, сгенеренный и исходный BMP отличаются ровно на этих 2 байта PPS добавили #pragma pack(1) - получили всё, что надо. 54 байта. Оттакот! ppps Что-то пользоваться таким ГЦЦ расхотелось...
Сообщение отредактировал _Pasha - Nov 9 2012, 19:11
|
|
|
|
|
Nov 9 2012, 19:29
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (_Pasha @ Nov 9 2012, 20:48)  CODE typedef struct { char id[2]; uint32_t size; И что же вы ожидали (надеюсь, это был не AVR или MSP430)?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 20 2013, 09:45
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Всплыл вопрос, кажется, подойдет в эту тему. Создаю суперструктуру из нескольких разных структур. В каждой из структур переменные разного размера кидаю, как попало. Не знаю, создаются дыры или нет, но пока использовал структуры по-отдельности, проблем не было. Keil знает, куда положил, и откуда брать. Для Cortex-M нет проблем. В суперструктуре должно быть аналогично.
Теперь хочу копировать суперструктуру в другую, такую же (backup). Хочу делать это 32-битовыми пересылками. Кроме того, хочу вычислять аппаратно CRC суперструктуры, туда тоже нужно посылать 32-битовые слова. Задаю указателю на uint32 адрес суперструктуры (uint32_t *)&Ctrl. Вычисляю ее размер в словах (!) size(Ctrl_t) / 4. И так собираюсь использовать.
Вопросы: 1. Что гарантирует, что вся суперструктура разместится по выровненному до слова адресу? Что будет, если первый элемент - 8-битовый? 2. Как задать, чтобы ее размер был равен целому числу слов? Пока напихал несколько пустых байтов, каждая мелкая структура - по 2-4-8 байтов, общее количество 44 байта (но, может, есть и дыры двухбайтовые?). В конце суперструктуры задаю 32-битовую CRC, это гарантирует выравнивание по словам, и целое число слов?
|
|
|
|
|
Dec 20 2013, 11:05
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551

|
QUOTE (ViKo @ Dec 20 2013, 11:45)  2. Как задать, чтобы ее размер был равен целому числу слов? Я точно не вспомню, но делал что то типа такого: Помещал "супер структуру" + массив байт в "супер-супер структуру" Размерность массива байт задавал как остаток от деления sizeof("супер структура") на 4. Единственное, что не могу вспомнить, как обходил ситуацию с нулевым размером массива байт.
|
|
|
|
|
Dec 20 2013, 11:08
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Запустил компиляцию с опцией --remarks. Вижу: enum занимают по 32 бита! Неоправданная роскошь. К структуре с enum и 3-мя uint_16 добавилось... видимо 2 байта в конце. По структуре Ctrl никаких замечаний не увидел. Добавил uint8_t в конец Ctrl. Получил замечание, что добавило padding. Делаю вывод - ничего не бойся, не проси...  Сам Кейл придет и принесет.
|
|
|
|
|
Dec 20 2013, 11:14
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 24-11-07
Пользователь №: 32 633

|
Цитата(ViKo @ Dec 20 2013, 15:08)  enum занимают по 32 бита! Неоправданная роскошь. Каждый из элементов enum - это int. Так что если машинное слово 32-х разрядное, то всё верно.
--------------------
Если друг оказался вдруг и не друг и не враг, а - JTAG.
|
|
|
|
|
Dec 20 2013, 11:44
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(PheeL @ Dec 20 2013, 14:14)  Каждый из элементов enum - это int. Так что если машинное слово 32-х разрядное, то всё верно. Да, верно. Просто я об этом не задумывался. Да оно и нашлось всего в одном месте. Там и не сам enum стоял, а производный тип - typedef enum {...} ... Заменю на uint16_t и сэкономлю 4 байта! Что любопытно. Имею в структуре 2 байта, в первом - битовые поля, во втором - uint8_t (вообще, reserv, для выше сказанного выравнивания). Так вот, такую 2-байтовую структуру Keil размещает в суперструктуре, не выравнивая по 2-байтовой границе. Как и написано по вышеприведенной ссылке, структура выравнивается по границе ее наибольшего члена.
|
|
|
|
|
Dec 24 2013, 09:55
|
Гуру
     
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847

|
Цитата(ViKo @ Dec 20 2013, 13:45)  1. Что гарантирует, что вся суперструктура разместится по выровненному до слова адресу? Компилятор гарантирует, что любое поле структуры (в том числе и поля вложенных структур) будет выровнено на его размер. Так же гарантируется, что это будет так и для массива структур. Отсюда автоматически следует, что сама структура всегда будет выровнена по ее полю с максимальным размером, и размер структуры тоже будет кратен размеру этого поля. Цитата Что будет, если первый элемент - 8-битовый? Не важно, какой первый. Главное, что бы внутри был хотя бы один int Цитата В конце суперструктуры задаю 32-битовую CRC, это гарантирует выравнивание по словам, и целое число слов? Да
|
|
|
|
|
Dec 24 2013, 16:06
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(ViKo @ Dec 20 2013, 11:45)  В конце суперструктуры задаю 32-битовую CRC, это гарантирует выравнивание по словам, и целое число слов? Как уже было сказано - да, гарантирует. Но все "дырки", оставшиеся от выравнивания полей, могут быть заполнены совершенно произвольным мусором. Учтите это при расчете CRC. Т.е. либо перед заполнением полей структуры обнуляйте выделенную под нее память при помощи memset, либо считайте CRC конкретных полей, а не всей памяти струткуры, либо размещайте поля так, чтобы не между ними не образовывалось "дырок".
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 24 2013, 18:52
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Сергей Борщ @ Dec 24 2013, 22:06)  Но все "дырки", оставшиеся от выравнивания полей, могут быть заполнены совершенно произвольным мусором. Учтите это при расчете CRC. Да, как-то я напоролся на такое. Была структура, в конце структуры crc16. При инициализации проверялось crc, и, в случае несовпадения, значениям структуры присваивались значения по умолчанию. Всё это прекрасно работало, до тех пор, пока я не поменял размер одного члена структуры с uint8_t на uint16_t. После этой замены моя программа стала дурить. Оказалось, что при смене размера члена общий размер структуры не изменился, crc16 тоже совпал. А вот значение этого члена получилось недопустимо большое (за счёт добавленного байта).
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|