Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Компилятор ниоса самодурствует?
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Системы на ПЛИС - System on a Programmable Chip (SoPC)
alexPec
Всем добрый день.

Возникла такая проблема. Прикручиваю готовый стек TCPIP к ниосу. Там есть структура:

Код
typedef struct _ARP_PACKET
{
    WORD        HardwareType;
    WORD        Protocol;
    BYTE        MACAddrLen;
    BYTE        ProtocolLen;
    WORD        Operation;
    MAC_ADDR    SenderMACAddr;
    IP_ADDR     SenderIPAddr;
    MAC_ADDR    TargetMACAddr;
    IP_ADDR     TargetIPAddr;
}  ARP_PACKET;

Здесь MAC_ADDR это:
Код
typedef struct _MAC_ADDR
{
    BYTE v[6];
} MAC_ADDR;

IP_ADDR это DWORD_VAL, а DWORD_VAL это:
Код
typedef union _DWORD_VAL
{
    DWORD Val;
    WORD w[2];
    BYTE v[4];
    struct
    {
        WORD LW;
        WORD HW;
    } word;
    struct
    {
        BYTE LB;
        BYTE HB;
        BYTE UB;
        BYTE MB;
    } byte;
} DWORD_VAL;


В коде подразумевается, что байты каждого поля идут по порядку друг за другом, без промежутков. В реальности выходит, что байты полей до SenderIPAddr располагаются в памяти как надо, по порядку, а вот поле SenderIPAddr располагается в памяти через 2 байта от SenderMACAddr и оказывается выровненным по 32-битной границе. Подозреваю, ниосу удобней стало расположить DWORD выровненным по 32-битной границе, а не разделять DWORD по двум адресам, и он пропустил 2 байта.

Вопрос:
1.Допускается ли такое (по правилам С, в коде из-за этого проблемы)?
2.Лечится ли как-нибудь? (указать бы ему явно, что брать байты надо по порядку, а не выравнивать DWORD по границе 32 бита)
_Артём_
Цитата(alexPec @ Dec 21 2012, 13:33) *
2.Лечится ли как-нибудь? (указать бы ему явно, что брать байты надо по порядку, а не выравнивать DWORD по границе 32 бита)

Упакуйте структуру.
Код
#pragma pack(1)
struct Test_t{
//...
};
Serhiy_UA
Писал свой усеченный TCP/IP стек для NiosII, все работало.
Использовал структуры, что в приложении. Для ARP на второй странице структура ETHERARP...
Сравните со своими....
alexPec
Спасибо Serhiy_UA и Артем!

Оба варианта лечат проблему, все работает!
alexPec
Возникла еще такая проблема: есть код вычисления контрольной суммы:
Код
unsigned short checksum(void *b, int len)
{
    unsigned short *buf = b, result;
    unsigned int sum=0;
    for ( sum = 0; len > 1; len -= 2 ) /* Sum all 16b words */
    {
        result=*buf;
        sum += *buf++;
    }
    if ( len == 1 )
    /* If any stray bytes, */
    sum += *(unsigned char*)buf;
    /* add to sum */
    sum = (sum >> 16) + (sum & 0xFFFF);
    /* Add the carry */
    sum += (sum >> 16);
    /* (again) */
    result = ~sum;
    /* Take the one's complement */
    return result;
    /* Return 16b value */
}


Так вот работает он корректно только когда адрес входного буфера четный. В случае нечетного адреса unsigned short выбирается из памяти неправильно, со смещением на 1 назад (в сторону меньшего адреса).
Как такое лечить, наверняка какой-то прагмой?
Или как-то ремапить его (буфер) перед подсчетом?
alexPec
Нашел: __attribute__ ((alligned (2)))
Выравнивает по границе слова.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.