Перейти к содержанию
    

Ещё один метод расчёта CRC16

Только что, Forger сказал:

Братцы, выручайте )))

Вот кто связал avr и c#, к тому и обращайтесь :) Я тут причём? Нигде об этом лично я не упоминал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, Forger сказал:

По-моему я попал в "шестую палату" ..

Братцы, выручайте )))

Я уже понял, что скорее всего, это та очередная тема, которая закончится красными строчками модератора:biggrin: За сим, больше не слежу =)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я связал метод расчёта crc16 и применение его для avr8. На каком языке код написан не имеет особого значения. Важны лишь константы, приведённые в коде, и порядок их применения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Just now, Arlleex said:

Я уже понял, что скорее всего, это та очередная тема, которая закончится красными строчками модератора:biggrin: 

Без сомнений ))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Когда-то я реализовал расчёт crc16 на bash для тестирования связи по modbus из терминала Linux'а. Теперь можно упростить эту реализацию.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, uni сказал:

Без таблицы, без сдвигов (для 0x1021, c#):

Как это очень громоздко выглядит....имхо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, k155la3 сказал:

В большинстве микроконтроллеров присутствует аппаратный узел расчета CRC, в различных вариантах настроек/полиномов.

Даже если есть, то это не панацея, так как:

1) Этот узел может иметь жёстко зашитый полином(-ы), а нужен другой;

2) Не все такие узлы реентерабельны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 часов назад, jcxz сказал:

2) Не все такие узлы реентерабельны. 

Вот это самый большой недостаток аппаратных модулей CRC. Если надо считать CRC из разных потоков выполнения, то приходится мощно извращаться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

27 минут назад, AHTOXA сказал:

Если надо считать CRC из разных потоков выполнения, то приходится мощно извращаться.

Gatekeeper task?:smile: И никаких извращений.

Но, ИМХО, в многопоточной среде программный CRC-расчет, все-таки, рулит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, Arlleex сказал:

Gatekeeper task?:smile: И никаких извращений.

Не. Это не всегда поможет. Например: идёт приём блока данных (с подсчётом CRC "на лету"), и одновременно стартует передача блока данных (нужно подсчитать CRC). Добавьте сюда CRC для загрузки/сохранения конфигурации, CRC для проверки валидности не-инициализируемого блока в памяти, и ещё чего-нибудь :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 минут назад, AHTOXA сказал:

Не. Это не всегда поможет. Например...

Да, есть такое...

Вот буквально на днях надо было считать CRC как в основном потоке, так и в прерывании. Уже получился небольшой изврат:biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В подобных ситуациях поможет комплексный вариант: для блоков данных аппаратный CRC+DMA, для штучных байтовых - программный.

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

Если прикинуть самые сложные случаи и это будет укладываться в допустимые задержки к доступу к CRC в критичных задачах, то вполне годное решение )

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Собрал тестовый пример на ATmega16@16МГц. Таблица во флеш, полином 0x1021. Чуда не произошло. Моя реализация для тестовой строки "123456789" дала 24 мкс против 13,9 мкс у табличного метода. В общем, тело цикла с чтением слова из флеш считает быстрее, чем побайтовый xor с условиями.

Crc16.jpg

Может быть получится как-то по-другому записать эту последовательность проверок. Попробую оптимизировать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для полинома 0xA001 результат странный в тех же условиях: ATmega16 @ 16МГц. Тестовую программу прикрепил (pdf).

Время расчёта строки "123456789":

 

GetCrc16Cycle()  - 67.2 мкс
GetCrc16Table()  - 97.1 мкс
GetCrc16Simple() - 24.3 мкс <- наш случай

 

Может быть что-то не так понял. Собирал с ключом -Os.

crc16test.pdf

 

P.S. В общем, там от ключа оптимизации и вида табличного алгоритма быстродействие зависит. Нужно найти самую оптимальную комбинацию. В тактах считать пока лень, т.к. нужно минимум по коду и быстродействию сначала найти.

Изменено пользователем uni

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот теперь больше на правду похоже. Переписал немного: 

 

Ключ: -Os
GetCrc16Table()  - 14.6 мкс (кушает 512 байт флеша)
GetCrc16Simple() - 24.3 мкс <- наш случай
GetCrc16Cycle()  - 67.2 мкс 

 

Ключ: -O1
GetCrc16Table()  - 13.9 мкс (кушает 512 байт флеша)
GetCrc16Simple() - 23.3 мкс <- наш случай
GetCrc16Cycle()  - 57.5 мкс 

 

crc16test.pdf

Ассемблерный код функции. Не знаю можно ли тут что-то придумать.
 

GetCrc16Simple:
 30e:	2f ef       	ldi	r18, 0xFF	; 255
 310:	3f ef       	ldi	r19, 0xFF	; 255
 312:	fc 01       	movw	r30, r24
 314:	68 0f       	add	r22, r24
 316:	79 1f       	adc	r23, r25
 318:	e6 17       	cp	r30, r22
 31a:	f7 07       	cpc	r31, r23
 31c:	51 f1       	breq	.+84     	; 0x372 <_Z14GetCrc16SimplePhj+0x64>
 31e:	91 91       	ld	r25, Z+
 320:	92 27       	eor	r25, r18
 322:	23 2f       	mov	r18, r19
 324:	39 2f       	mov	r19, r25
 326:	90 ff       	sbrs	r25, 0
 328:	04 c0       	rjmp	.+8      	; 0x332 <_Z14GetCrc16SimplePhj+0x24>
 32a:	80 e4       	ldi	r24, 0x40	; 64
 32c:	28 27       	eor	r18, r24
 32e:	82 e0       	ldi	r24, 0x02	; 2
 330:	38 27       	eor	r19, r24
 332:	31 ff       	sbrs	r19, 1
 334:	03 c0       	rjmp	.+6      	; 0x33c <_Z14GetCrc16SimplePhj+0x2e>
 336:	20 58       	subi	r18, 0x80	; 128
 338:	84 e0       	ldi	r24, 0x04	; 4
 33a:	38 27       	eor	r19, r24
 33c:	32 ff       	sbrs	r19, 2
 33e:	02 c0       	rjmp	.+4      	; 0x344 <_Z14GetCrc16SimplePhj+0x36>
 340:	89 e0       	ldi	r24, 0x09	; 9
 342:	38 27       	eor	r19, r24
 344:	33 ff       	sbrs	r19, 3
 346:	02 c0       	rjmp	.+4      	; 0x34c <_Z14GetCrc16SimplePhj+0x3e>
 348:	82 e1       	ldi	r24, 0x12	; 18
 34a:	38 27       	eor	r19, r24
 34c:	34 ff       	sbrs	r19, 4
 34e:	02 c0       	rjmp	.+4      	; 0x354 <_Z14GetCrc16SimplePhj+0x46>
 350:	84 e2       	ldi	r24, 0x24	; 36
 352:	38 27       	eor	r19, r24
 354:	35 ff       	sbrs	r19, 5
 356:	02 c0       	rjmp	.+4      	; 0x35c <_Z14GetCrc16SimplePhj+0x4e>
 358:	88 e4       	ldi	r24, 0x48	; 72
 35a:	38 27       	eor	r19, r24
 35c:	36 ff       	sbrs	r19, 6
 35e:	02 c0       	rjmp	.+4      	; 0x364 <_Z14GetCrc16SimplePhj+0x56>
 360:	80 e9       	ldi	r24, 0x90	; 144
 362:	38 27       	eor	r19, r24
 364:	33 23       	and	r19, r19
 366:	c4 f6       	brge	.-80     	; 0x318 <_Z14GetCrc16SimplePhj+0xa>
 368:	81 e0       	ldi	r24, 0x01	; 1
 36a:	28 27       	eor	r18, r24
 36c:	80 e2       	ldi	r24, 0x20	; 32
 36e:	38 27       	eor	r19, r24
 370:	d3 cf       	rjmp	.-90     	; 0x318 <_Z14GetCrc16SimplePhj+0xa>
 372:	c9 01       	movw	r24, r18
 374:	08 95       	ret

 

Изменено пользователем uni

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...