Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: RealView Compiler не слушается квалификатора __packed
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
sonycman
Компилятор RealView 4.0.0.524 из пакета MDK3.70. C++.

Что-то не слушается меня компилер, то ли я не так пишу, то ли багу нашёл.
Исходник:
Код
#define USB_STRING_DESCRIPTOR_TYPE             3
#define    MANUF_STRING    L"Sonycman Production"
#define    PROD_STRING        L"Sonycman Mass Storage Drive"
#define    SERIAL_STRING    L"123456789ABC"

typedef __packed struct
{
    byte    length;
    byte    descriptor_type;
    word    languageID;
} USB_STRING_ID_DESCRIPTOR;

typedef __packed struct
{
    byte    length;
    byte    descriptor_type;
    wchar_t    text[sizeof(MANUF_STRING)/2];
} USB_STRING1_DESCRIPTOR;

typedef __packed struct
{
    byte    length;
    byte    descriptor_type;
    wchar_t    text[sizeof(PROD_STRING)/2];
} USB_STRING2_DESCRIPTOR;

typedef __packed struct
{
    byte    length;
    byte    descriptor_type;
    wchar_t    text[sizeof(SERIAL_STRING)/2];
} USB_STRING3_DESCRIPTOR;

typedef __packed struct
{
    USB_STRING_ID_DESCRIPTOR    s0;
    USB_STRING1_DESCRIPTOR        s1;
    USB_STRING2_DESCRIPTOR        s2;
    USB_STRING3_DESCRIPTOR        s3;
} USB_STRING_DESCRIPTOR;

и инициализация:
Код
const    USB_STRING_DESCRIPTOR    CUSB::strings = {
    sizeof(USB_STRING_ID_DESCRIPTOR),
    USB_STRING_DESCRIPTOR_TYPE,
    0x409,                                //language ID
    sizeof(USB_STRING1_DESCRIPTOR),
    USB_STRING_DESCRIPTOR_TYPE,
    MANUF_STRING,
    sizeof(USB_STRING2_DESCRIPTOR),
    USB_STRING_DESCRIPTOR_TYPE,
    PROD_STRING,
    sizeof(USB_STRING3_DESCRIPTOR),
    USB_STRING_DESCRIPTOR_TYPE,
    SERIAL_STRING
};


Так вот, члену strings присваиваются такие данные:
0x080046f9: 04 03 09 04 2a 03 00 53 00 6f 00 6e 00...
Но откуда взялся в запакованной структуре явно пэддинг байт (выделен жирным)?!
forever failure
wchar_t text[sizeof(MANUF_STRING)/2]; /*<-- здесь точно требуется массив из двух байт ?*/
zltigo
А попробуйте простую кондовую #pragma pack(1) вместо этих многочисленных и совсем уж плохо переносимых __packed
sonycman
Цитата(forever failure @ Jun 24 2009, 20:41) *
wchar_t text[sizeof(MANUF_STRING)/2]; /*<-- здесь точно требуется массив из двух байт ?*/

Там массив из двухбайтовых слов - строка в юникоде.

Цитата(zltigo @ Jun 24 2009, 20:43) *
А попробуйте простую кондовую #pragma pack(1) вместо этих многочисленных и совсем уж плохо переносимых __packed

Щаз попробую smile.gif
А эта прагма будет относиться только к сразу следующей за ней структуре, или сразу до конца файла?

Эм, попробовал - без результата, лишний нулевой байт остаётся...

Хотя с прагмами прикольно - у меня SlickEdit не понимает (__packed), и теперь можно его убрать!
С другой стороны, прагма работает до конца файла, приходится ставить лишнюю pragma pack(), чтобы выравнивание вернулось к состоянию по умолчанию...

Проблема решается, если структуре strings добавить квалификатор align(2) - то есть выровнять её в памяти.
Тогда пэддинг не вставляется, и данные генерятся так, как надо.
Но это уже, имхо, костыль для обхода бага...
zltigo
Цитата(sonycman @ Jun 24 2009, 19:47) *
А эта прагма будет относиться только к сразу следующей за ней структуре, или сразу до конца файла?

До конца, или отменяющей прагмы.
defunct
Цитата(sonycman @ Jun 24 2009, 19:18) *
0x080046f9: 04 03 09 04 2a 03 00 53 00 6f 00 6e 00...
Но откуда взялся в запакованной структуре явно пэддинг байт (выделен жирным)?!

Оттуда же откуда и следующий за ним 0 и все остальные 0 через 1 - из wchar_t.
__packed вообще-то прекрасно работает в RVDS'е.

padd здесь ни один компилятор не вставит. Сами подумайте тип wchar - 2 байта.
Какого лешего его размещать с нечетного адреса? А в вашем примере если допустить что выделенный 00 это padd байт, то wchar располагается как раз по нечетному смещению "0x7".
aaarrr
Цитата(defunct @ Jun 24 2009, 22:09) *
Оттуда же откуда и следующий за ним 0 и все остальные 0 через 1 - из wchar_t.

Ничего подобного - сам стринг должен быть таким:
Код
53 00 6f 00 6e 00...


RVDS 2.2 создает корректную структуру (в плюсовом режиме правда не смотрел):
Код
0x0000a4c4  04 03 09 04 2A 03 53 00 6F 00 6E 00 79 00 63 00 ....*.S.o.n.y.c.
0x0000a4d4  6D 00 61 00 6E 00 20 00 50 00 72 00 6F 00 64 00 m.a.n. .P.r.o.d.
sonycman
Цитата(defunct @ Jun 24 2009, 22:09) *
Оттуда же откуда и следующий за ним 0 и все остальные 0 через 1 - из wchar_t.
__packed вообще-то прекрасно работает в RVDS'е.

padd здесь ни один компилятор не вставит. Сами подумайте тип wchar - 2 байта.
Какого лешего его размещать с нечетного адреса? А в вашем примере если допустить что выделенный 00 это padd байт, то wchar располагается как раз по нечетному смещению "0x7".

Ноль должен идти уже после 0х53, но никак не до!
В пакованной структуре wchar_t может начинаться с нечётного адреса - на то она и запакованная!
defunct
Цитата(sonycman @ Jun 24 2009, 21:21) *
Ноль должен идти уже после 0х53, но никак не до!
В пакованной структуре wchar_t может начинаться с нечётного адреса - на то она и запакованная!

В упакованной структуре padding'и отсутствуют как класс. Если предположить что что-то не так с упаковкой (компилер не понял слово __packed), тогда получается неувязочка с нечетным смещением.

Цитата
Ничего подобного - сам стринг должен быть таким:

может какой-то атрибут применен, который перевернул строку в bigendian.
Я лично считаю, что это не padd byte 100%. и упаковка здесь не при чем.
aaarrr
sonycman: а данные структуры где смотрите?

Цитата(defunct @ Jun 24 2009, 22:26) *
может какой-то атрибут применен, который перевернул строку в bigendian.

Знаете такой атрибут?
defunct
Цитата(sonycman @ Jun 24 2009, 21:21) *
Ноль должен идти уже после 0х53, но никак не до!

Ну так переверните его и посмотрите что получится.
swap16( ...->s1.text[ 0 ] );
aaarrr
Цитата(defunct @ Jun 24 2009, 22:31) *
Ну так переверните его и посмотрите что получится.
swap16( ...->s1.text[ 0 ] );

Напишите +2 по результатам отладки, ага.
defunct
Цитата(aaarrr @ Jun 24 2009, 21:32) *
Напишите +2 по результатам отладки, ага.

Ага, тогда думайте, что это padding дальше и пытайтесь пофиксить его как паддинг.
Мне то что.
aaarrr
Цитата(sonycman @ Jun 24 2009, 20:18) *
Компилятор RealView 4.0.0.524 из пакета MDK3.70. C++.

В не C++ режиме тоже все нормально.
sonycman
Цитата(defunct @ Jun 24 2009, 22:26) *
может какой-то атрибут применен, который перевернул строку в bigendian.
Я лично считаю, что это не padd byte 100%. и упаковка здесь не при чем.

Весь код перед вами в первом посте.
Тут не переворот, а лишний байт, так как вся структура имеет длину на 1 байт больше, чем должна быть.

Цитата(aaarrr @ Jun 24 2009, 22:28) *
sonycman: а данные структуры где смотрите?

Смотрю в отладчике, в режиме симулятора.
defunct
Цитата(sonycman @ Jun 24 2009, 23:42) *
Весь код перед вами в первом посте.
Тут не переворот, а лишний байт, так как вся структура имеет длину на 1 байт больше, чем должна быть.

Дак хохма в том что с кодом все ОК, aaarrr два раза рузультаты привел. И нет повода не доверять его результату.
Попробуйте так сказать с чистого листа, - создайте проект для другого проца и скомпильте тем же RVDS'ом.
Переверните первый "wchar" в s1, - хотя бы чтоб убедиться в том, что переворота строки нет, и что именно выделенный 0 там лишний..
sonycman
Пока что попробовал новый проект в простом Си - всё одно и то же.
Если структура располагается в памяти с нечётного адреса - появляется лишний нуль.
Если с чётного - всё нормально.

Сейчас попробую выбрать другой проц...

Сделал новый проект для SAM7S, чисто с этим кодом. Всё по-старому - располагаем структуру по нечётному адресу и получаем нечто...
rolleyes.gif
aaarrr
Цитата(sonycman @ Jun 25 2009, 00:59) *
Если структура располагается в памяти с нечётного адреса - появляется лишний нуль.

Угу, именно так. И это глюк.

Старенький RVDS работает нормально, а здесь остается действительно только вбивать костыли в виде __align(2), пока не исправят.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.