|
|
  |
И снова про CRC, Что надо сказать IAR-у, чтобы он считал CRC как для пакетов MODBUS? |
|
|
|
Dec 12 2007, 15:17
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(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 прошивки?
|
|
|
|
|
Dec 12 2007, 16:28
|

Странник
   
Группа: Свой
Сообщений: 766
Регистрация: 29-08-05
Из: Екатеринбург
Пользователь №: 8 051

|
Цитата(rezident @ Dec 12 2007, 20:17)  Во-первых, не обязательно иметь таблицу для подсчета CRC16. Есть и безтабличныей алгоритм. Это понятно, не написал, что тогда вычисление контрольной суммы всего кода длится недопустимо долго (разбивать на несколько вызовов не предлагать, это уже сделано). Знаю, что есть вариант формирования таблицы в памяти, память есть, но хочется, чтобы была одна функция для подсчета CRC. Цитата Во-вторых, что именно вы пытались посчитать с помощью IAR? CRC прошивки? Да, CRC прошивки, всей flash-памяти.
--------------------
"Как много есть на свете вещей, которые мне не нужны!" Сократ
|
|
|
|
|
Dec 12 2007, 22:26
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Baser @ Dec 12 2007, 22:28)  Если дашь все параметры CRC modbus, могу попробовать помочь. Нужны: полином (прямой), направление сдвига, начальное значение CRC, конечные действия с CRC, парочка примеров правильной CRC для одного-двух байт. CRC16 ModBus вместе полиномом, таблицей и примером реализации на Си имеются в спецификации ModBus over serial line. Выше я уже привел пример алгоритма расчета CRC16 именно с тем полиномом, который используется в ModBus. Что же вам еще нужно-то? Помогайте  Цитата(spf @ Dec 12 2007, 21:28)  Да, CRC прошивки, всей flash-памяти. Именно всей Flash? А вы внимательно прочитали раздел хелпа IAR, где описано как и какие именно сегменты Flash включаются в подсчет CRC?
|
|
|
|
|
Dec 12 2007, 23:53
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(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 по таблицам...
|
|
|
|
|
Dec 13 2007, 03:51
|

Странник
   
Группа: Свой
Сообщений: 766
Регистрация: 29-08-05
Из: Екатеринбург
Пользователь №: 8 051

|
Цитата(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.
--------------------
"Как много есть на свете вещей, которые мне не нужны!" Сократ
|
|
|
|
|
Dec 13 2007, 10:36
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(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.
|
|
|
|
|
Dec 13 2007, 11:56
|

Странник
   
Группа: Свой
Сообщений: 766
Регистрация: 29-08-05
Из: Екатеринбург
Пользователь №: 8 051

|
Цитата(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: только не надо ёрничанья
--------------------
"Как много есть на свете вещей, которые мне не нужны!" Сократ
|
|
|
|
|
Dec 13 2007, 13:20
|

Просто Che
    
Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881

|
Цитата(spf @ Dec 13 2007, 13:56)  Попрошу не отдаляться от темы. У меня CRC лежит именно там, где мне это надо. Не об этом речь. Пример приведен из рабочего вариант для простого CRC16(CCITT), в нем нет ошибок. Я хотел уточнить только тот момент, что если у вас контрольная сумма находится внутри обкладываемой CRC области памяти, то ессно ничего не получится. А так можно хранить сумму в любой другой памяти. Конкретно по теме Я попробовал вариант суммы Модбаса, получается. Правда только при условии нулевого начального значения CRC. Проверьте такой вариант: Код -J2,crc=8005,m,Flash_CRC,INFO,,0=(CODE)4000-FFFF Если хочется считать с начальным значением CRC==0xFFFF, то ИАР выдает что-то непонятное.
|
|
|
|
|
Dec 13 2007, 13:28
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(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; } Прогнал на строке из нескольких байтов, вроде работает.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Oct 8 2012, 11:26
|
Участник

Группа: Участник
Сообщений: 33
Регистрация: 29-06-10
Пользователь №: 58 196

|
Цитата(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?
|
|
|
|
|
Oct 18 2012, 11:27
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 8-05-08
Пользователь №: 37 363

|
Цитата(Baser @ Dec 13 2007, 17:20)  Если хочется считать с начальным значением CRC==0xFFFF, то ИАР выдает что-то непонятное. Только сейчас решил этот вопрос Код -J2,crc=8005,m,,,,#0xFFFF=(CODE)0-(_..X_FLASH_END-2) Обратите внимание на решёточку (#) перед начальным значением. Без неё считает не так  В документации на линкер этот момент как-то завуалирован: Цитата #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. долго пытался понять, но безуспешно
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|