Danis 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба Привет, коллеги по цеху! Вот сижу, роюсь в периферийной библиотеке STM32. Интересует аппаратный расчет CRC16 на STM32. Кто нить это использовал? Сейчас я пока пользуюсь только программным расчетом CRC16. Использую следующие функции: // BYTE – unsigned char // WORD – 2байта (unsigned short) // ---------------- функция расчета СRC16 -------------------------------------------------- WORD GetCRC16(BYTE* Buffer, WORD Size) { return(GetCRC16Fragment(Buffer, Size, 0)); } //************************************************************ //---------------------------------------------------------------------------------------------------------- WORD GetCRC16Fragment(BYTE* Buffer, WORD Size, WORD PrevFragmentCRC) { WORD crc, i, j; crc = PrevFragmentCRC; for (i=0; i<Size; i++) { crc ^= Buffer << 8; for (j=0; j<8; j++) { if ((crc & 0x8000) != 0) crc = (crc << 1) ^ 0x1021; else crc <<= 1; } } return(crc); } //************************************************************************ Например, в одном из проектов я по SPI (DMA) принимаю из Ethernet контроллера буфер 1472 байта, это максимальный размер данных UDP пакета. Конечно же, чтоб проверить целостность пакета передаю его в функцию GetCRC16. Последние 2 байта пакета содержат его CRC16. Таким образом, при целостности пакета, функция GetCRC16 должна возвратить 0. Все это здорово работает, за минусом того, что на это дело тратиться 3.8 ms процессорного времени. Поэтому заинтересовался аппаратным расчетом CRC. В примерах из стандартной библиотеки нашел функцию: /** * @brief Computes the 32-bit CRC of a given buffer of data word(32-bit). * @param pBuffer: pointer to the buffer containing the data to be computed * @param BufferLength: length of the buffer to be computed * @retval 32-bit CRC */ uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength) { uint32_t index = 0; for(index = 0; index < BufferLength; index++) { CRC->DR = pBuffer[index]; } return (CRC->DR); } Но это как я понимаю CRC32. Можно ли на STM32 аппаратно вычислить CRC16 по полиному 1021? Кто нить пользовался? Насколько аппаратный расчет CRC быстрее считает чем программный? Хочу услышать Ваши мнения. В понедельник приду на работу, тогда уж на железе погоняю…. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Serj78 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба CRC - это вообще-то остаток от деления. В вашей функции оно сильно неэффективно. (сдвигами). Табличная реализация значительно эффективнее. (Есть замечательный документ "Ross N. Williams Элементарное руководство по CRC алгоритмам обнаружения ошибок Все, что Вы хотели бы знать о CRC алгоритмах, но боялись спросить, опасаясь, что ошибки Ваших знаний могут быть обнаружены" -погуглите. ) В даташите указано, что полином аппаратного блока CRC фиксированный : Uses CRC-32 (Ethernet) polynomial: 0x4C11DB7 – X32 + X26 + X23 + X22 + X16 + X12 + X11 + X10 +X8 + X7 + X5 + X4 + X2+ X +1 и изменить его нельзя, увы :( А было бы здорово, если бы для полинома был отдельный регистр... :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Danis 0 20 ноября, 2010 Опубликовано 20 ноября, 2010 · Жалоба CRC - это вообще-то остаток от деления. В вашей функции оно сильно неэффективно. (сдвигами). Табличная реализация значительно эффективнее. Пожалуйста, дайте Вашу табличную реализацию для CRC16. Хотелось бы в виде легко переносимой функции в стиле Си. Если это сэкономит время - это будет просто здорово. Даташит по STM32 относительно CRC прочитал, действительно фиксированный. Сейчас мне нужно написать функцию или нагуглть для подготовки этой CRC32. Придется отказаться от моей привычной CRC16 в STM32. ........ Вот нашел кое-что, но в стиле С++ с классом, там полином даже как у STM32 - unsigned long ulPolynomial = 0x04C11DB7, и табличная реализация. Чуть попозжа перепишу для Си и тут выложу. Погоняем и сравним...... CRC32.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Petr_I 0 21 ноября, 2010 Опубликовано 21 ноября, 2010 · Жалоба Пожалуйста, дайте Вашу табличную реализацию для CRC16. Хотелось бы в виде легко переносимой функции в стиле Си. Если это сэкономит время - это будет просто здорово. Даташит по STM32 относительно CRC прочитал, действительно фиксированный. Сейчас мне нужно написать функцию или нагуглть для подготовки этой CRC32. Придется отказаться от моей привычной CRC16 в STM32. Вот вариант CRC16 из описания MODBUS. Вообще то CRC16 есть несколько вариантов. Если не подойдет, ищите в RFC. CRC16.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Danis 0 22 ноября, 2010 Опубликовано 22 ноября, 2010 · Жалоба Чуть попозжа перепишу для Си и тут выложу. Погоняем и сравним...... Вот переписал на Си, считает правильно! Но STM32 аппаратно не будет также считать, одна приблуда есть, надо биты переставлять(реверс делать короче).... CRC32.rar Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Danis 0 22 ноября, 2010 Опубликовано 22 ноября, 2010 · Жалоба Вот вариант CRC16 из описания MODBUS. Petr_I Из Ваших исходников мне не понятно, по какому полиному считается CRC16. 1021? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
svl.soft 0 24 ноября, 2010 Опубликовано 24 ноября, 2010 · Жалоба Вот тут все подробно и понятно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 25 ноября, 2010 Опубликовано 25 ноября, 2010 · Жалоба Попробуйте такой код. Интересно, насколько он будет медленнее табличного учитывая наличие сдвигателя в ARM: uint_fast16_t void crc_xmodem(uint_fast16_t crc_prev, uint8_t byte) { uint_fast16_t Tmp = ((crc_prev >> 8) ^ byte) & 0xFF; Tmp ^= Tmp >> 4; Tmp ^= (crc_prev << 8) ^ (Tmp << 12) ^ (Tmp <<5); Tmp &= 0xFFFF; return Tmp; } Tmp &= 0xFFFF можно вынести и делать один раз после окончания обсчета всего массива. gcc 4.5.0 для ARM7 дает такой код: 1053b4: e5720001 ldrb r0, [r2, #-1]! 1053b8: e0200423 eor r0, r0, r3, lsr #8 1053bc: e20000ff and r0, r0, #255; 0xff Tmp ^= Tmp >> 4; 1053c0: e0200220 eor r0, r0, r0, lsr #4 Tmp ^= (Current << 8) ^ (Tmp << 12) ^ (Tmp <<5); 1053c4: e1803403 orr r3, r0, r3, lsl #8 1053c8: e0233600 eor r3, r3, r0, lsl #12 crc::xmodem CRC; while(--i); 1053cc: e1520001 cmp r2, r1 1053d0: e0233280 eor r3, r3, r0, lsl #5 1053d4: 1afffff6 bne 1053b4 <decoder::process(demodulator::bit_t)+0x44> 1053d8: e1b03803 lsls r3, r3, #16 Самому стало интересно, попробовал скомпилить табличный метод: 1053b4: e5720001 ldrb r0, [r2, #-1]! 1053b8: e203c0ff and ip, r3, #255; 0xff 1053bc: e02c0000 eor r0, ip, r0 1053c0: e59fc104 ldr ip, [pc, #260]; 1054cc Таблица 1053c4: e1a00080 lsl r0, r0, #1 1053c8: e19c00b0 ldrh r0, [ip, r0] crc::xmodem CRC; while(--i); 1053cc: e1520001 cmp r2, r1 1053d0: e0203423 eor r3, r0, r3, lsr #8 1053d4: 1afffff6 bne 1053b4 <decoder::process(demodulator::bit_t)+0x44> То есть те же 8 команд внутри цикла, но 3 из них ldr, против одной в первом варианте. Значит, такой способ должен на ARM7 считаться даже быстрее, чем табличный. Интересно, что покажет STM32? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Danis 0 25 ноября, 2010 Опубликовано 25 ноября, 2010 · Жалоба Погоняем и сравним...... Вот реализовал программную функцию расчета CRC32, с учетом алгоритма расчета STM32. Выше в посте я уже писал, что обычная софтовская функция CRC32 считает по полиному 0x04C11DB7 по другому, нежели аппаратно железка. Для корректного подсчета в нее нужно ввести перестановку битов. Файл - STM32_SOFT_CRC32.zip Эта не табличная реализация, медленная, но считает также как STM32 аппаратно. Табличную реализацию пока еще не написал, может кто напишет и выложит? А это аппаратная реализация подсчета CRC32 непосредственно в железке. Немного переделал функцию из периферийной библиотеки STM32, для удобства. Файл - STM32_HARD_CRC32.zip Считает очень быстро, в 5 раз быстрее чем табличная реализация подсчета классической CRC32. Буфет размером 1472 byte считает за 100 us, так что по моему, очень даже не плохо! STM32_SOFT_CRC32.zip STM32_HARD_CRC32.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 143 25 ноября, 2010 Опубликовано 25 ноября, 2010 · Жалоба Вот реализовал программную функцию расчета CRC32, с учетом алгоритма расчета STM32. Выше в посте я уже писал, что обычная софтовская функция CRC32 считает по полиному 0x04C11DB7 по другому, нежели аппаратно железка.А в первом сообщении вы спрашивали про CRC16... :07: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Danis 0 25 ноября, 2010 Опубликовано 25 ноября, 2010 · Жалоба А в первом сообщении вы спрашивали про CRC16... :07: Да так и было! я спрашивал про: "Интересует аппаратный расчет CRC16", но таковой расчет в STM32 не возможен. Не создавать же другую тему. Развил ее здесь, поэтому пришлось переключиться на CRC32. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 29 25 ноября, 2010 Опубликовано 25 ноября, 2010 · Жалоба CRC - это вообще-то остаток от деления. В вашей функции оно сильно неэффективно. (сдвигами). Табличная реализация значительно эффективнее. Смотря по какому критерию оценивать эффективность. (скорость/объём) Эта не табличная реализация, медленная, но считает также как STM32 аппаратно. Табличную реализацию пока еще не написал, может кто напишет и выложит? А в гугле и википедии вас забанили чтоли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Danis 0 25 ноября, 2010 Опубликовано 25 ноября, 2010 · Жалоба вас забанили чтоли? Вопрос не в том, что забанили или нет. Табличную реализацию CRC32 я выложил в теме выше. Но ее переделывать нужно под STM32, а времени на это нет. Если у Вас есть таковая функция или ссылка на нее, то поместите ее тут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
svl.soft 0 25 ноября, 2010 Опубликовано 25 ноября, 2010 · Жалоба ... Но ее переделывать нужно под STM32, а времени на это нет. Если у Вас есть таковая функция или ссылка на нее, то поместите ее тут. Что значит переделывать? Это же обычный Си. Я не совсем Вас понимаю, как в микроконтроллере, с использованием функции, аппаратно посчитать CRC? Ну это уже из темы ALTERA или XILINX. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 25 ноября, 2010 Опубликовано 25 ноября, 2010 · Жалоба Если я правильно понял, Danis хочет приспособить имеющийся в STM32 аппаратный модуль подсчёта crc32 (с жёстко заданным полиномом) для подсчёта crc32/crc16 с произвольным полиномом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться