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

 
 
> Приём/передача незапакованной структуры для C2000, Программерская смекалка :)
sigmaN
сообщение Oct 26 2009, 12:59
Сообщение #1


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



Код
typedef uint32_t ba05_blockKey[BA05_BLOCKKEYSIZE];

//заголовок у обоих типов пакетов общий, поэтому опишем его один раз
struct ba05_net_pktHeader
{
    uint16_t    packetType    : 3;    //ID-пакет, BlockPacket или HeaderPacket
    uint16_t    connStageID    : 3;    //public_keys_interchange, random_sample_interchange, hash_interchange
    uint16_t    needACK        : 1;    //сообщает приёмнику, что в ответ на этот пакет нужно обязательно отправить ACK пакет
    uint16_t    ACK            : 1;    //Признак пакета подтверждения. Если ACK==1 - все остальные поля не используются(кроме crc8,естественно)    
    uint16_t    crc8         : 8;
};
//описание поля data для пакета IDPacket
struct ba05_net_IDPacket_data
{
    ba05_ID                public_ID;    
    ba05_ID                corp_ID;    
};
//поле data для Block-пакета описано в объявлении ba05_net_packet ниже
typedef struct
{
    struct ba05_net_pktHeader             header;
    union
    {
        struct ba05_net_IDPacket_data     asIDPacket;
        ba05_blockKey                asBlockPacket;
    }data;
}ba05_net_packet;

Прагмы, заставляющей компилятор запаковать структуру - нет.
Тип ba05_blockKey может изменяться в зависимости от настроек алгоритма. Т.е. вместо uint32_t там может появиться uint16_t или uint64_t, соответственно, выравнивание будет разным.
На данный момент, не сложно догадаться, после header идёт пустышка(1слово), длее идёт data.
Если бы структура передавалась всегда полностью - проблем бы не было. Но в зависимости от ситуации, передаётся либо только header, либо header + asIDPacket, либо целиком(header + asBlockPacket).
Функции отправки/приёма анализируют header.packetType и по нему определяют сколько байт нужно отправить/принять(а также обработать при пересчёте CRC).
И всё было-бы хорошо, если бы не тот факт, что из-за пустышек, применяемых для выравнивания, сумма sizeof всех полей получается меньше sizeof всей структуры.
Как я уже говорил, настройки могут меняться и нужно это дело как-то обработать универсальным способом.
На данный момент я сделал так:
Код
*/
*    Ниже, я постарался обработать эту ситуацию с помощью препроцессора и арифметики с указателями.
*    Суть в том, что вместо sizeof я применял разность адресов .data и .header
*    оператор взятия адреса(&) позволит нам уловить момент вставки компилятором пустышки
*    пример: <header size=1byte,address=0><пустышка size=1byte,address=1><data size=2,address=2>
*    если просто взять sizeof(header) + sizeof(data) байт и отправить - то мы отправим header полностью
*    пустышку полностью, а поле data будет передано не полностью(на sizeof(пустышка) байт меньше)
*    Но если я вместо sizeof(header) использую (&data -  &header) то пустышка будет учтена.
*/
enum {  HeaderPacketSize = sizeof(((ba05_net_packet *)0)->header) }; //header сам по себе никуда не выравнивается
//а дальше пришлось мудрить
#define BlockPacketSize ( ((int)&((ba05_net_packet *)0)->data.asBlockPacket - (int)&((ba05_net_packet *)0)->header) + sizeof(((ba05_net_packet *)0)->data.asBlockPacket) )
#define IDPacketSize ( ((int)&((ba05_net_packet *)0)->data.asIDPacket - (int)&((ba05_net_packet *)0)->header) + sizeof(((ba05_net_packet *)0)->data.asIDPacket) )

//теперь нам нужно правильно определить размер в байтах
#ifdef SIZEOF_IS_IN_WORDS
    enum {  HeaderPacketSize_bytes = HeaderPacketSize * 2    };
    #define BlockPacketSize_bytes ( BlockPacketSize * 2 )
    #define    IDPacketSize_bytes ( IDPacketSize * 2 )
#elif defined(SIZEOF_IS_IN_BYTES)
    enum {  HeaderPacketSize_bytes = HeaderPacketSize        };
    #define BlockPacketSize_bytes ( BlockPacketSize )
    #define    IDPacketSize_bytes ( IDPacketSize )
#endif

Работает. Но как-то мудрёно получается....
Прокомментируйте решение, пожалуйста. Что можно поменять? Как сделать проще/лучше?

P.S. SIZEOF_IS_IN_WORDS/SIZEOF_IS_IN_BYTES тут присутствуют для обеспечения портируемости. Дело в том, что мой компилятор возвращает sizeof в словах(по 2 байта). Побайтового доступа к памяти нет.
Однако, при работе с сетью нам нужны байты. На других архитектурах, где sizeof() ведет себя прилично - этой проблемы не будет. Поэтому я обрабатываю эту ситуацию отдельно.
А функции отправки/приёма просто могут использовать *_bytes и не беспокоиться не о чём smile.gif


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
sigmaN
сообщение Oct 26 2009, 18:06
Сообщение #2


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



думаю, что не совсем
Цитата
The DATA_ALIGN pragma aligns the symbol to an alignment boundary.
The alignment boundary is the maximum of the symbol's default alignment value or the value of the constant in bytes.
The constant must be a power of 2.
The syntax of the pragma in C is:
#pragma DATA_ALIGN ( symbol , constant );


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
rezident
сообщение Oct 26 2009, 18:14
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(sigmaN @ Oct 26 2009, 23:06) *
думаю, что не совсем
Ну дык все верно. В CCS для TMS320C2000 char же 16-и битный. laughing.gif
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 5th August 2025 - 16:58
Рейтинг@Mail.ru


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