Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Кросскомпиляторный код
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > GNU/OpenSource средства разработки
Злодей
Вот такой вот код,
Код
inline uint32_t crc32_add( uint32_t crc, uint8_t byte  )
{
    crc ^= byte;
    
    for (uint8_t i=0; i<8; i++)
    {
        if (crc & 1)
    {
        crc = (crc>>1) ^ CRC32_POLYNOME;
    }
    else
    {
        crc >>= 1;
    }
    }
    
    return crc;
}

скомпилирован для двух платформ: BorlandCC для ПК и GCC для AVR.... На разных платформах разные результаты выполнения. Какими словами уточнить код, чтобы компиляторы наконец договорились?

Ещё два момента: я пока не знаю, кто из них на данный момент правильно работает. В борланде подключен \\avr\\include\\inttypes.h из WinAVR.

Спасибо smile.gif
FormatCft
Цитата(Злодей @ Apr 30 2009, 13:41) *
Вот такой вот код,
Код
inline uint32_t crc32_add( uint32_t crc, uint8_t byte  )
{
    crc ^= byte;
    
    for (uint8_t i=0; i<8; i++)
    {
        if (crc & 1)
    {
        crc = (crc>>1) ^ CRC32_POLYNOME;
    }
    else
    {
        crc >>= 1;
    }
    }
    
    return crc;
}

скомпилирован для двух платформ: BorlandCC для ПК и GCC для AVR.... На разных платформах разные результаты выполнения. Какими словами уточнить код, чтобы компиляторы наконец договорились?
Я пока не знаю, кто из них на данный момент правильно работает. В борланде подключен \\avr\\include\\inttypes.h из WinAVR.
Спасибо smile.gif

Можно пошагово в отладчике пройтись и узнать где начинает отличаться. Действия простые и проблем быть не должно.
MrYuran
А результат всегда одинаковый в обоих случаях?
Код
  {
    crc ^= byte;

Вот, например, неочевидно, чему был равен crc до этой операции
Злодей
Цитата(MrYuran @ Apr 30 2009, 12:03) *
А результат всегда одинаковый в обоих случаях?
Код
  {
    crc ^= byte;

Вот, например, неочевидно, чему был равен crc до этой операции

Здесь всё в порядке. crc - аргумент фунции.
MrYuran
Цитата(Злодей @ Apr 30 2009, 12:09) *
Здесь всё в порядке. crc - аргумент фунции.

А, ну да... чё-то я парю...
Злодей
Вчера пытался компилировать в GCC без оптимизации так он отказывался... Ставил везде-везде volatile - не помогало. В AVR Studio видно, что осталось от кода:

Код
uintX_t crc32_add( uintX_t crc, uint8_t byte  )
{
    crc ^= byte;
    uint8_t i = 8;
    do
    {
        crc >>= 1;
    }
    while(--i);

    return crc;
}

Вот этот кусок отсутствует полностью. Типа младший бит всегда 0 w00t.gif Нашлиииии! А как починить?
Код
if (crc & 1)
{
    crc = (crc>>1) ^ CRC32_POLYNOME;
}



Спасибо FormatCft, направил меня на путь истинный smile.gif
MrYuran
Цитата(Злодей @ Apr 30 2009, 12:47) *
Вчера пытался компилировать в GCC без оптимизации так он отказывался...

Не может такого быть.
А он мотивировал?
_Pasha
Цитата(Злодей @ Apr 30 2009, 11:47) *
Вот этот кусок отсутствует полностью.

Йа Станиславский smile.gif Вы точно ходили, жмя F11 или смотрели *.lss или еще какую вредную шнягу ? biggrin.gif
Objdump доведет до коровьего бешенства.
Злодей
Помогите, пожалуйста исправить ошибку "left shift count >= width of type"
Код
uint32_t crc;
crc <<= 1U;



Вот такую сам вылечил
Код
uint32_t crc;
//if (crc & ( 1 << 31 ) ) //ошибка
if (crc & ((uint32_t)1 << 31) )


Цитата(_Pasha @ Apr 30 2009, 13:40) *
Йа Станиславский smile.gif Вы точно ходили, жмя F11 или смотрели *.lss или еще какую вредную шнягу ? biggrin.gif
Objdump доведет до коровьего бешенства.

Так и есть, спал 2 часа, потом стоматолог дррррр, а теперь ещё и дизассембить. Извините оффтоп.

Что же делать "warning: left shift count >= width"
Код
crc <<= 1U;
//uint32_t crc;
_Pasha
Цитата(Злодей @ Apr 30 2009, 12:41) *
Вот такую сам вылечил

Не-не-не-не..

Код
uint32_t crc;
if (crc & (1UL << 31) )
Злодей
Цитата(Злодей @ Apr 30 2009, 13:46) *
Помогите, пожалуйста исправить ошибку "left shift count >= width of type"
Код
uint32_t crc;
crc <<= 1U;


Простите, это уже шиза smile.gif
В следующей строчке в константе прятался макрос, там ошибка на которую указал
Цитата(_Pasha @ Apr 30 2009, 13:46) *
Не-не-не-не..

Код
uint32_t crc;
if (crc & (1UL << 31) )


Спасибо! Я теперь понял зачем нужны U и L smile.gif
_Pasha
Цитата(Злодей @ Apr 30 2009, 13:04) *
Спасибо! Я теперь понял зачем нужны U и L smile.gif


Пожалуйста. Тут с похожими граблями недавно пробегал кто-то, если указать (uint32_t)(1<<32), то он вначале 16-разрядную единицу сдвинет на 32 влево, а потом приведет к 32-разрядному. По этой причине я разлюбил пользоваться макросами типа _BV() - из-за скрытия наглядности
alx2
Цитата(Злодей @ Apr 30 2009, 12:41) *
Вот такой вот код,
.....
скомпилирован для двух платформ: BorlandCC для ПК и GCC для AVR.... На разных платформах разные результаты выполнения. Какими словами уточнить код, чтобы компиляторы наконец договорились?
В коде я никакого криминала не усмотрел...
Цитата(Злодей @ Apr 30 2009, 12:41) *
Ещё два момента: я пока не знаю, кто из них на данный момент правильно работает. В борланде подключен \\avr\\include\\inttypes.h из WinAVR.
=8-( ) А почему используется файл от другого компилятора? За размерность типов отвечает компилятор, поэтому файл stdint.h (в котором определены типы uintXX_t и который подключается из файла inttypes.h) должен браться только из комплекта компилятора, которым осуществляется компиляция.
mdmitry
Часто необходимо приведение типа внутри кода (это CRC8):

Код
char wk_crc8_block(const  char *datablock, const unsigned int count_byte)
{    

    register unsigned int count;
    char crc1, ch;
    
    crc1 = (char)CRC_WAKE_INIT;
    
    for(count = 0; count < count_byte; count++)
    {
        ch = (char)datablock[count];
    Do_Crc8(ch, &crc1);
    }
    crc1 = (char)crc1;        
    return(crc1);    
}


void Do_Crc8(char b, char *crc)
{
    int i;
    
    for (i = 0; i < 8; i++)
      {
           if (((b ^ *crc) & 1) != 0)
                 *crc = (char)(((*crc ^ 0x18) >> 1) | 0x80);
               else
                *crc = (char)((*crc >> 1) & ~0x80);
           b = (char)(b >> 1);
       }
}

Без явного приведения типа к (char) для AVR -все в порядке, а на PC и freescale MC56F8346 полный бред.
Компилятор любит использовать размер данные "родной" для платформы (AVR - 8 бит, Freescale - 16, PC - 32).
forever failure
Цитата(mdmitry @ Apr 30 2009, 19:05) *
Часто необходимо приведение типа внутри кода (это CRC8):

Код
char wk_crc8_block(const  char *datablock, const unsigned int count_byte)
{    

    register unsigned int count;
    char crc1, ch;
    
    crc1 = (char)CRC_WAKE_INIT;
    
    for(count = 0; count < count_byte; count++)
    {
        ch = (char)datablock[count];
    Do_Crc8(ch, &crc1);
    }
    crc1 = (char)crc1;        
    return(crc1);    
}


void Do_Crc8(char b, char *crc)
{
    int i;
    
    for (i = 0; i < 8; i++)
      {
           if (((b ^ *crc) & 1) != 0)
                 *crc = (char)(((*crc ^ 0x18) >> 1) | 0x80);
               else
                *crc = (char)((*crc >> 1) & ~0x80);
           b = (char)(b >> 1);
       }
}

Без явного приведения типа к (char) для AVR -все в порядке, а на PC и freescale MC56F8346 полный бред.
Компилятор любит использовать размер данные "родной" для платформы (AVR - 8 бит, Freescale - 16, PC - 32).

Тут проблема может быть в другом, и явное приведение типа вовсе ни при чём. По стандарту не оговаривается чётко, должен быть беззнаковым тип char или иметь знак. Поэтому поведение такого кода может изменятся даже для одного и того же целевого процессора, в зависимости от ключей компиляции, а уж при переходе от одной платформы к другой - и подавно. Вот и получается, что для AVR char может быть беззнаковым - и всё в порядке, а на PC и Freescale char имеет знак - и получается полный бред. В таких случаях и надо использовать стандартный восьмибитный беззнаковый тип - uint8_t (который в большинстве случаев, но опять же не всегда - unsigned char).


ЗЫ. А stdint.h надо брать тот, который идёт с компилятором, а не из чужой среды, т. е. для борланда - борландский, для AVR - avrовский.
mdmitry
Цитата(forever failure @ Apr 30 2009, 18:49) *
В таких случаях и надо использовать стандартный восьмибитный беззнаковый тип - uint8_t (который в большинстве случаев, но опять же не всегда - unsigned char).

Обучать uint8_t MSVC++ надо отдельно.

Конечно правильно использовать inttype.h, но не все компиляторы (например, Codewarrior for MS56F83xxx) имеют соответствующий заголовочный файл.
alx2
Цитата(Злодей @ Apr 30 2009, 12:41) *
На разных платформах разные результаты выполнения.
Чем все закончилось? Так и не удалось найти причину? Очень любопытно...
Злодей
Цитата(alx2 @ May 6 2009, 14:46) *
Чем все закончилось? Так и не удалось найти причину? Очень любопытно...


Ой как не хочется об этом вспоминать.... smile.gif

Проблема была в том, что когда пишешь вот так, это неправильно:
Код
uint32_t a;
uint32_t b;
/* ... */
a = b | ( 1 << 24 );

А когда единичке приписываешь UL всё становится хорошо и одинаково.
Код
uint32_t a;
uint32_t b;
/* ... */
a = b | ( 1UL << 24 );

Извините, растолковать что к чему не могу smile.gif
Сергей Борщ
Цитата(Злодей @ May 7 2009, 19:03) *
Извините, растолковать что к чему не могу smile.gif
Единица имеет тип int. Int на разных платформах имеет разный размер, иногда - меньше 24 бит.
alx2
Цитата(Злодей @ May 7 2009, 21:03) *
Проблема была в том, что когда пишешь вот так, это неправильно:
Код
uint32_t a;
uint32_t b;
/* ... */
a = b | ( 1 << 24 );

А когда единичке приписываешь UL всё становится хорошо и одинаково.
Вы не поняли. Я говорю не об этом, а о коде функции, приведенном в первом сообщении этой темы. Здесь-то как раз все понятно - результат выражения в скобках зависит от размера типа int. Но в исходном сообщении нет ничего подобного, там все операции производятся над типами фиксированного размера! Да и вообще никакого оператора << там нет, из операций сдвига там только (crc>>1) и (crc >>= 1), что, по-моему, совершенно переносимо, и должно давать одинаковый результат...
Злодей
Дело в том, что код у меня - индийский cranky.gif
Эти сдвиги были ещё и где-то в макросах:
Код
#define CRC32_POLYNOME ( 0x04C11DB7 | ( 1UL << 31 ) | 1UL  )
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.