Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: И снова про CRC
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
spf
Привет!

Как работает пример получения CRC кода понятно, все работает.

В боевом коде программы имеются функции по работе с пакетами Modbus (вычисление CRC).
Заставить IAR посчитать CRC так же, как считает проверенная функция вычисления CRC для Modbus
не удалось. Может кто-то это прошел?

Не хотелось бы иметь две таблицы для расчета CRC.

PS: IAR 3.42 (MSP430)
rezident
Цитата(spf @ Dec 12 2007, 12:05) *
Привет!

Как работает пример получения CRC кода понятно, все работает.

В боевом коде программы имеются функции по работе с пакетами Modbus (вычисление CRC).
Заставить IAR посчитать CRC так же, как считает проверенная функция вычисления CRC для Modbus
не удалось. Может кто-то это прошел?

Не хотелось бы иметь две таблицы для расчета CRC.

PS: IAR 3.42 (MSP430)

Во-первых, не обязательно иметь таблицу для подсчета CRC16. Есть и безтабличныей алгоритм.
Код
//==============================================//
// Функция подсчета СRC16 по алгоритму          //
//----------------------------------------------//
//аргументы: указатель на буфер,                //
//           размер буфера,                     //
//           стартовое значение СRC16           //
//возвращает:подсчитанное значение СRC16        //
//----------------------------------------------//
//ВНИМАНИЕ! Стартовому значению CRC16 необходимо//
//          присвоить значение 0xFFFF,          //
//          размер массива для подсчета CRC16   //
//          не более 65535 байт                 //
//==============================================//
#ifndef _POLINOME_CRC16_
  #define _POLINOME_CRC16_  0xA001
#endif

xWord f_CRC16Calc(xByte *buf, xWord sizeBuf, xWord crc)
{ xWord i, j;
  for(i=0;i<sizeBuf;i++)
  { crc=crc^buf[i];
    for (j=0;j<8;j++)
    { if ((crc&0x0001)!=0x0000) crc=(crc>>1)^_POLINOME_CRC16_;
      else crc>>=1;
    }
  }
  return (crc);
}

Во-вторых, что именно вы пытались посчитать с помощью IAR? CRC прошивки?
spf
Цитата(rezident @ Dec 12 2007, 20:17) *
Во-первых, не обязательно иметь таблицу для подсчета CRC16. Есть и безтабличныей алгоритм.

Это понятно, не написал, что тогда вычисление контрольной суммы всего кода длится недопустимо долго (разбивать на несколько вызовов не предлагать, это уже сделано). Знаю, что есть вариант формирования таблицы в памяти, память есть, но хочется, чтобы была одна функция для подсчета CRC.

Цитата
Во-вторых, что именно вы пытались посчитать с помощью IAR? CRC прошивки?

Да, CRC прошивки, всей flash-памяти.
Baser
Если дашь все параметры CRC modbus, могу попробовать помочь.
Нужны:
полином (прямой), направление сдвига, начальное значение CRC, конечные действия с CRC, парочка примеров правильной CRC для одного-двух байт.

Сейчас как раз разбираюсь с ИАРом и его CRC:
здесь
rezident
Цитата(Baser @ Dec 12 2007, 22:28) *
Если дашь все параметры CRC modbus, могу попробовать помочь.
Нужны:
полином (прямой), направление сдвига, начальное значение CRC, конечные действия с CRC, парочка примеров правильной CRC для одного-двух байт.

CRC16 ModBus вместе полиномом, таблицей и примером реализации на Си имеются в спецификации ModBus over serial line.
Выше я уже привел пример алгоритма расчета CRC16 именно с тем полиномом, который используется в ModBus. Что же вам еще нужно-то? Помогайте wink.gif


Цитата(spf @ Dec 12 2007, 21:28) *
Да, CRC прошивки, всей flash-памяти.

Именно всей Flash? А вы внимательно прочитали раздел хелпа IAR, где описано как и какие именно сегменты Flash включаются в подсчет CRC?
singlskv
Цитата(spf @ Dec 12 2007, 10:05) *
Не хотелось бы иметь две таблицы для расчета CRC.

PS: IAR 3.42 (MSP430)

Для вычисления CRC16 модбас есть простой/быстрый/линейный вариант,
код для AVR из avr-libc
Код
static __inline__ uint16_t
_crc16_update(uint16_t __crc, uint8_t __data)
{
    uint8_t __tmp;
    uint16_t __ret;

    __asm__ __volatile__ (
        "eor %A0,%2" "\n\t"
        "mov %1,%A0" "\n\t"
        "swap %1" "\n\t"
        "eor %1,%A0" "\n\t"
        "mov __tmp_reg__,%1" "\n\t"
        "lsr %1" "\n\t"
        "lsr %1" "\n\t"
        "eor %1,__tmp_reg__" "\n\t"
        "mov __tmp_reg__,%1" "\n\t"
        "lsr %1" "\n\t"
        "eor %1,__tmp_reg__" "\n\t"
        "andi %1,0x07" "\n\t"
        "mov __tmp_reg__,%A0" "\n\t"
        "mov %A0,%B0" "\n\t"
        "lsr %1" "\n\t"
        "ror __tmp_reg__" "\n\t"
        "ror %1" "\n\t"
        "mov %B0,__tmp_reg__" "\n\t"
        "eor %A0,%1" "\n\t"
        "lsr __tmp_reg__" "\n\t"
        "ror %1" "\n\t"
        "eor %B0,__tmp_reg__" "\n\t"
        "eor %A0,%1"
        : "=r" (__ret), "=d" (__tmp)
        : "r" (__data), "0" (__crc)
        : "r0"
    );
    return __ret;
}

Просто передалайте его под MSP430 ....
Скорость его работы сравнима с вычислением CRC по таблицам...
spf
Цитата(rezident @ Dec 13 2007, 03:26) *
Именно всей Flash? А вы внимательно прочитали раздел хелпа IAR, где описано как и какие именно сегменты Flash включаются в подсчет CRC?

Именно всей Flash. Читал. Более того -- все работает и в симуляторах и в железе.
В коде пишем (F1611)
Код
   extern unsigned short Flash_CRC;
   sum = crc16_ccitt(0,(unsigned char *)0x4000, 0xFFFF-0x4000+1);
   if(sum != Flash_CRC)

Линкеру говорим:
Код
-Hff
-J2,crc16,,Flash_CRC,INFO=(CODE)4000-ffff

В мапе получаем:
Код
Symbol     Checksum  Memory  Start  End   Initial value
------     --------  ------  -----  ---   -------------
Flash_CRC    0x60d3   CODE   4000 - FFFF         0x0


Цитата(singlskv @ Dec 13 2007, 04:53) *
Просто передалайте его под MSP430 ....
Скорость его работы сравнима с вычислением CRC по таблицам...

И этот вариант я знаю, мне хочется другое - заставить IAR посчитать CRC так же, как считается в MODBUS.
Baser
Цитата(spf @ Dec 13 2007, 05:51) *
Линкеру говорим:

-Hff
-J2,crc16,,Flash_CRC,INFO=(CODE)4000-ffff

Линкер должен считать crc не всей памяти, а от её начала до месторасположения CRC.
То есть сегмент INFO у вас должен находится в конце памяти:
Код
-Z(CODE)INFO#FFFF

а строка вычисления CRC совсем другая, там куча ошибок. Примерно так:
Код
-J2,crc=A001,m,Flash_CRC,INFO,,FFFF=(CODE)4000-FFFD

да и то я сомневаюсь, что получится, посколько там есть еще какая то лажа, с которой я ещё не разобрался. Дайте пример CRC: несколько байт и верную сумму, тогда когда доберусь до работы, попробую.

Цитата(rezident @ Dec 13 2007, 00:26) *
CRC16 ModBus вместе полиномом, таблицей и примером реализации на Си имеются в спецификации ModBus over serial line.
Выше я уже привел пример алгоритма расчета CRC16 именно с тем полиномом, который используется в ModBus. Что же вам еще нужно-то? Помогайте

А вы бы товарищ, лучше бы дали несколько конкретных цифр вместо ёрничанья. Или все должны знать алгоритм расчета CRC Modbus? В том что вы дали не ни слова о Modbus.
spf
Цитата(Baser @ Dec 13 2007, 15:36) *
Линкер должен считать crc не всей памяти, а от её начала до месторасположения CRC.

Попрошу не отдаляться от темы.
У меня CRC лежит именно там, где мне это надо. Не об этом речь. Пример приведен из рабочего вариант для простого CRC16(CCITT), в нем нет ошибок.


Что только не предлагают, но все не по теме...

Вот пример кода для расчета CRC для MODBUS
Код
unsigned int Crc16AddBlock(unsigned int cur_crc, unsigned char *p_data, unsigned int data_len)
{
        do
        {
            unsigned int   i = 8;    

            cur_crc = cur_crc ^ *p_data++;

            do
            {
                if (0x0001 & cur_crc)
                {
                    cur_crc >>= 1;    
                    cur_crc  ^=  0xA001;
                }
                else                          
                {
                    cur_crc >>= 1;      
                }
            }
            while (--i);
        }
        while (--data_len);
    return  cur_crc;
}


PS: только не надо ёрничанья
Baser
Цитата(spf @ Dec 13 2007, 13:56) *
Попрошу не отдаляться от темы.
У меня CRC лежит именно там, где мне это надо. Не об этом речь. Пример приведен из рабочего вариант для простого CRC16(CCITT), в нем нет ошибок.

Я хотел уточнить только тот момент, что если у вас контрольная сумма находится внутри обкладываемой CRC области памяти, то ессно ничего не получится. А так можно хранить сумму в любой другой памяти.

Конкретно по теме smile.gif
Я попробовал вариант суммы Модбаса, получается. Правда только при условии нулевого начального значения CRC. Проверьте такой вариант:
Код
-J2,crc=8005,m,Flash_CRC,INFO,,0=(CODE)4000-FFFF

Если хочется считать с начальным значением CRC==0xFFFF, то ИАР выдает что-то непонятное.
Сергей Борщ
Цитата(spf @ Dec 13 2007, 13:56) *
Попрошу не отдаляться от темы.
Прошу извинить. Вот еще один вариант быстрого вычисления, хотя кажется у singlskv вариант быстрее:
Код
uint16_t CRC_MODBUS(uint16_t crc, uint8_t byte)
{
    byte ^= crc;
    crc = crc >> 8;

    if(byte & (1 << 0)) crc ^= 0xC0C1;
    if(byte & (1 << 1)) crc ^= 0xC181;
    if(byte & (1 << 2)) crc ^= 0xC301;
    if(byte & (1 << 3)) crc ^= 0xC601;
    if(byte & (1 << 4)) crc ^= 0xCC01;
    if(byte & (1 << 5)) crc ^= 0xD801;
    if(byte & (1 << 6)) crc ^= 0xF001;
    if(byte & (1 << 7)) crc ^= 0xA001;
    return crc;
}
Прогнал на строке из нескольких байтов, вроде работает.
eisufu
Цитата(spf @ Dec 13 2007, 09:51) *
Именно всей Flash. Читал. Более того -- все работает и в симуляторах и в железе.
В коде пишем (F1611)
Код
   extern unsigned short Flash_CRC;
   sum = crc16_ccitt(0,(unsigned char *)0x4000, 0xFFFF-0x4000+1);
   if(sum != Flash_CRC)

Линкеру говорим:
Код
-Hff
-J2,crc16,,Flash_CRC,INFO=(CODE)4000-ffff

В мапе получаем:
Код
Symbol     Checksum  Memory  Start  End   Initial value
------     --------  ------  -----  ---   -------------
Flash_CRC    0x60d3   CODE   4000 - FFFF         0x0



И этот вариант я знаю, мне хочется другое - заставить IAR посчитать CRC так же, как считается в MODBUS.

Очень интересно какие результаты?
Не могли бы вы состряпать минимальный проект для IAR, MSP430F1611?
Арк К
Цитата(Baser @ Dec 13 2007, 17:20) *
Если хочется считать с начальным значением CRC==0xFFFF, то ИАР выдает что-то непонятное.

Только сейчас решил этот вопрос
Код
-J2,crc=8005,m,,,,#0xFFFF=(CODE)0-(_..X_FLASH_END-2)

Обратите внимание на решёточку (#) перед начальным значением. Без неё считает не так wacko.gif В документации на линкер этот момент как-то завуалирован:
Цитата
#specifies that val is a bytewise initial value. #0x1D0F is an example of a bytewise
initial value. Bytewise initial values are used if the verification step uses the
byte-by-byte algorithm with non-zero initial values. See Bytewise initial values, page
39.

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