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

Вот сижу, роюсь в периферийной библиотеке 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[i] << 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
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

и изменить его нельзя, увы sad.gif
А было бы здорово, если бы для полинома был отдельный регистр... smile.gif
Danis
Цитата(Serj78 @ Nov 20 2010, 21:39) *
CRC - это вообще-то остаток от деления. В вашей функции оно сильно неэффективно. (сдвигами). Табличная реализация значительно эффективнее.


Пожалуйста, дайте Вашу табличную реализацию для CRC16. Хотелось бы в виде легко переносимой функции в стиле Си. Если это сэкономит время - это будет просто здорово. Даташит по STM32 относительно CRC прочитал, действительно фиксированный. Сейчас мне нужно написать функцию или нагуглть для подготовки этой CRC32. Придется отказаться от моей привычной CRC16 в STM32.

........
Вот нашел кое-что, но в стиле С++ с классом, там полином даже как у STM32 - unsigned long ulPolynomial = 0x04C11DB7, и табличная реализация. Чуть попозжа перепишу для Си и тут выложу. Погоняем и сравним......
Petr_I
Цитата(Danis @ Nov 20 2010, 21:45) *
Пожалуйста, дайте Вашу табличную реализацию для CRC16. Хотелось бы в виде легко переносимой функции в стиле Си. Если это сэкономит время - это будет просто здорово. Даташит по STM32 относительно CRC прочитал, действительно фиксированный. Сейчас мне нужно написать функцию или нагуглть для подготовки этой CRC32. Придется отказаться от моей привычной CRC16 в STM32.


Вот вариант CRC16 из описания MODBUS.
Вообще то CRC16 есть несколько вариантов. Если не подойдет, ищите в RFC.


Danis
Цитата(Danis @ Nov 20 2010, 22:45) *
Чуть попозжа перепишу для Си и тут выложу. Погоняем и сравним......


Вот переписал на Си, считает правильно! Но STM32 аппаратно не будет также считать, одна приблуда есть, надо биты переставлять(реверс делать короче)....
Danis
Цитата(Petr_I @ Nov 21 2010, 23:24) *
Вот вариант CRC16 из описания MODBUS.

Petr_I Из Ваших исходников мне не понятно, по какому полиному считается CRC16. 1021?
svl
Вот тут все подробно и понятно.
Сергей Борщ
Попробуйте такой код. Интересно, насколько он будет медленнее табличного учитывая наличие сдвигателя в ARM:
CODE
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 дает такой код:
CODE
  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
Самому стало интересно, попробовал скомпилить табличный метод:
CODE
  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
Цитата(Danis @ Nov 20 2010, 21:45) *
Погоняем и сравним......



Вот реализовал программную функцию расчета CRC32, с учетом алгоритма расчета STM32. Выше в посте я уже писал, что обычная софтовская функция CRC32 считает по полиному 0x04C11DB7 по другому, нежели аппаратно железка. Для корректного подсчета в нее нужно ввести перестановку битов.

Файл - STM32_SOFT_CRC32.zip

Эта не табличная реализация, медленная, но считает также как STM32 аппаратно. Табличную реализацию пока еще не написал, может кто напишет и выложит?

А это аппаратная реализация подсчета CRC32 непосредственно в железке. Немного переделал функцию из периферийной библиотеки STM32, для удобства.

Файл - STM32_HARD_CRC32.zip

Считает очень быстро, в 5 раз быстрее чем табличная реализация подсчета классической CRC32.

Буфет размером 1472 byte считает за 100 us, так что по моему, очень даже не плохо!
Сергей Борщ
QUOTE (Danis @ Nov 25 2010, 07:56) *
Вот реализовал программную функцию расчета CRC32, с учетом алгоритма расчета STM32. Выше в посте я уже писал, что обычная софтовская функция CRC32 считает по полиному 0x04C11DB7 по другому, нежели аппаратно железка.
А в первом сообщении вы спрашивали про CRC16... 07.gif
Danis
Цитата(Сергей Борщ @ Nov 25 2010, 15:26) *
А в первом сообщении вы спрашивали про CRC16... 07.gif

biggrin.gif
Да так и было! я спрашивал про: "Интересует аппаратный расчет CRC16", но таковой расчет в STM32 не возможен. Не создавать же другую тему. Развил ее здесь, поэтому пришлось переключиться на CRC32.
MrYuran
Цитата(Serj78 @ Nov 20 2010, 21:39) *
CRC - это вообще-то остаток от деления. В вашей функции оно сильно неэффективно. (сдвигами). Табличная реализация значительно эффективнее.

Смотря по какому критерию оценивать эффективность.
(скорость/объём)

Цитата(Danis @ Nov 25 2010, 08:56) *
Эта не табличная реализация, медленная, но считает также как STM32 аппаратно. Табличную реализацию пока еще не написал, может кто напишет и выложит?

А в гугле и википедии вас забанили чтоли?
Danis
Цитата(MrYuran @ Nov 25 2010, 15:52) *
вас забанили чтоли?


Вопрос не в том, что забанили или нет. Табличную реализацию CRC32 я выложил в теме выше. Но ее переделывать нужно под STM32, а времени на это нет. Если у Вас есть таковая функция или ссылка на нее, то поместите ее тут.
svl
Цитата(Danis @ Nov 25 2010, 16:10) *
... Но ее переделывать нужно под STM32, а времени на это нет. Если у Вас есть таковая функция или ссылка на нее, то поместите ее тут.

Что значит переделывать? Это же обычный Си.
Я не совсем Вас понимаю, как в микроконтроллере, с использованием функции, аппаратно посчитать CRC? Ну это уже из темы ALTERA или XILINX.
AHTOXA
Если я правильно понял, Danis хочет приспособить имеющийся в STM32 аппаратный модуль подсчёта crc32 (с жёстко заданным полиномом) для подсчёта crc32/crc16 с произвольным полиномом.
Danis
Цитата(svl @ Nov 25 2010, 23:04) *
Что значит переделывать? Это же обычный Си.
Я не совсем Вас понимаю, как в микроконтроллере, с использованием функции, аппаратно посчитать CRC? Ну это уже из темы ALTERA или XILINX.


Маленько уточняю… В STM32 есть аппаратный модуль подсчета CRC32. Если в него передать некий буфер, то в результате он подсчитает CRC32.
Например, из ПК в STM32 передаем некий буфер, предположим 20 байт, в которых 16 байт это непосредственно сам информационный буфер, а последние четыре это CRC32 (рассчитывается в ПК). Дальше аппаратно считаем CRC32 в STM32 (для 16-ти байт) и сравниваем. Вот я и просил выложить табличную функцию расчета CRC32 на Си, которая будет возвращать результат такой же как и аппаратный модуль CRC32 STM32. Таковую функцию на Си я написал, но не табличную (выложил выше - STM32_SOFT_CRC32.zip).



Цитата(AHTOXA @ Nov 26 2010, 00:00) *
Если я правильно понял, Danis хочет приспособить имеющийся в STM32 аппаратный модуль подсчёта crc32 (с жёстко заданным полиномом) для подсчёта crc32/crc16 с произвольным полиномом.


нет, нет. Это не возможно! biggrin.gif
svl
Код
#include <stddef.h>
#include <stdint.h>
/*
  Name  : CRC-32
  Poly  : 0x04C11DB7    x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11
                       + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
  Init  : 0xFFFFFFFF
  Revert: true
  XorOut: 0xFFFFFFFF
  Check : 0xCBF43926 ("123456789")
  MaxLen: 268 435 455 байт (2 147 483 647 бит) - обнаружение
   одинарных, двойных, пакетных и всех нечетных ошибок
*/
const uint_least32_t Crc32Table[256] = {
    0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
    0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
    0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
    0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
    0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
    0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
    0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
    0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
    0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
    0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
    0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
    0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
    0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
    0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
    0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
    0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
    0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
    0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
    0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
    0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
    0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
    0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
    0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
    0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
    0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
    0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
    0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
    0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
    0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
    0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
    0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
    0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
    0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
    0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
    0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
    0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
    0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
    0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
    0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
    0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
    0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
    0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
    0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
    0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
    0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
    0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
    0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
    0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
    0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
    0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
    0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
    0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
    0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
    0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
    0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
    0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
    0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
    0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
    0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
    0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
    0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
    0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
    0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
    0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};

uint_least32_t Crc32(const unsigned char * buf, size_t len)
{
    uint_least32_t crc = 0xFFFFFFFF;
    while (len--)
        crc = (crc >> 8) ^ Crc32Table[(crc ^ *buf++) & 0xFF];
    return crc ^ 0xFFFFFFFF;
}


И маленький совет.
Если буфер данных загнать в подсчет CRC(любой) вместе с принятой контрольной суммой от отправителя, в вашем случае 20 байт, при совпадении СRC на выходе функции получите просто 0, тем самым дополнительно ничего пересчитывать не нужно.
ViKo
2 svl
Crc32Table нужно было внутрь функции вставить, была бы локальная таблица констант. Все равно больше нигде не нужна.

Danis
Цитата(svl @ Nov 26 2010, 22:31) *
........................
......................
uint_least32_t Crc32(const unsigned char * buf, size_t len)
{
uint_least32_t crc = 0xFFFFFFFF;
while (len--)
crc = (crc >> 8) ^ Crc32Table[(crc ^ *buf++) & 0xFF];
return crc ^ 0xFFFFFFFF;
}

svl! Спасибо за отзыв. Приятно когда человек реально хочет поспособствовать, а не отправляет в гугл или Википедию. Похоже, аппаратный модуль CRC32 в STM32 никто не использует, а зря, это ж хороший плюс в скорости расчета, в 5 раз быстрее табличного CRC32.

svl, Ваша функция:

uint_least32_t Crc32(const unsigned char * buf, size_t len);

считает CRC32 точно также, как считает та, что я скинул выше (файл CRC32.rar).
Но дело в том, что аппаратный модуль CRC у STM32 считает не так!

Например, передаем

unsigned char buff[4] = {0,0,0,0};

uint_least32_t My_CRC32 = Crc32( (const unsigned char*)(buff), 4 ) ;

получаем результат: 0x2144df1c.

Тот же буфет передаю в аппаратный модуль CRC32 у STM32 только виде 32 integer, т.к у него регистр CRC 32-х битный. Получается, передаю всего одну переменную = 0x00000000

получаем результат: 0xc704dd7b

Видите, результат разный!!!!

Вот почему: 0xc704dd7b если произвести перестановку
битов ( bit-reverse( 0xc704dd7b) = 0xdebb20e3),
и еще сделать так:
0xdebb20e3 ^ 0xffffffff = 0x2144df1c - вот только теперь получим сходство.

Функцию которая считает программно CRC32 с результатом расчетов таким же как и у аппаратного модуля STM32 я уже скидывал (STM32_SOFT_CRC32.zip), но она не табличная.



Цитата(svl @ Nov 26 2010, 22:31) *
И маленький совет.
Если буфер данных загнать в подсчет CRC(любой) вместе с принятой контрольной суммой от отправителя, в вашем случае 20 байт, при совпадении СRC на выходе функции получите просто 0, тем самым дополнительно ничего пересчитывать не нужно.


Сначала считаю CRC32 для 16-ти байт, потом приписываю ее в конце буфера так и сяк, о не выходит!

unsigned char buff[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,0,0,0};
uint_least32_t My_CRC32 = Crc32( (const unsigned char*)(buff), 16 ) ;
My_CRC32: 0xcecee288

unsigned char buff[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0x88,0xe2,0xce,0xce};
uint_least32_t My_CRC32 = Crc32( (const unsigned char*)(buff), 20 ) ;
My_CRC32: 0x2144df1c

unsigned char buff[20]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0xce,0xce,0xe2, 0x88};
uint_least32_t My_CRC32 = Crc32( (const unsigned char*)(buff), 20 ) ;
My_CRC32: 0x08e2e872
svl
Цитата(ViKo @ Nov 26 2010, 23:32) *
2 svl
Crc32Table нужно было внутрь функции вставить, была бы локальная таблица констант. Все равно больше нигде не нужна.


О да! И загоняли бы стек при каждом вызове функции подсчета CRC...
Объявление static const uint_least32_t Crc32Table[256] = {... // Размещение массива в памяти программ (flash)
Для каждого компилятора, объявления различны.
ReAl
Цитата(svl @ Nov 27 2010, 12:04) *
Объявление static const
Да, конечно и несомненно.
Для любого компилятора константный массив следует снабжать словом const.
Для любого компилятора при упрятывании никому, кроме данной функции, не нужной глобальной переменной внутрь функции следует снабжать эту переменную словом static.
Это что-то вроде минимальных правил хорошего тона.
И не зависит от того, во флеше это всё или флеш в системе только для того, чтобы BIOS на старте в DDR3 SDRAM переписать, а программа с диска зачитывается.
При размещении всей программы вместе с данными исключительно в ОЗУ всё равно стоит тут таблицу и const объявить, и внутрь функции затолкать. Со static, естественно.
А дальше уж в зависимости от. При едином адресном пространстве компилятор сам во флеш затолкает, в других случаях придётся ручками прописывать нужное нестандартное ключевое слово. Но это отдельно, дополнительно и не обязательно (если глобальной таблице такое слово не было нужно, то и статической локальной оно не нужно).
_Pasha
Цитата(svl @ Nov 27 2010, 13:04) *
О да! И загоняли бы стек при каждом вызове функции подсчета CRC...

С какого бодуна? cranky.gif При выключенной оптимизации?
sergeeff
Цитата(svl @ Nov 27 2010, 13:04) *
О да! И загоняли бы стек при каждом вызове функции подсчета CRC...
Объявление static const uint_least32_t Crc32Table[256] = {... // Размещение массива в памяти программ (flash)
Для каждого компилятора, объявления различны.


Переменные, объявленные как static внутри функции размещаются не в стеке.
svl
Цитата(sergeeff @ Nov 27 2010, 14:26) *
Переменные, объявленные как static внутри функции размещаются не в стеке.

Вот я это и хотел сказать.
ViKo
Цитата(svl @ Nov 27 2010, 13:41) *
Вот я это и хотел сказать.

Стало быть, согласны, что нужно было сделать static const и внутрь функции задвинуть?
Sergey_Aleksandrovi4
Цитата(Danis @ Nov 27 2010, 01:32) *
Например, передаем
unsigned char buff[4] = {0,0,0,0};
uint_least32_t My_CRC32 = Crc32( (const unsigned char*)(buff), 4 ) ;
получаем результат: 0x2144df1c.

Тот же буфет передаю в аппаратный модуль CRC32 у STM32 только виде 32 integer, т.к у него регистр CRC 32-х битный. Получается, передаю всего одну переменную = 0x00000000

получаем результат: 0xc704dd7b

Видите, результат разный!!!!

Вот почему: 0xc704dd7b если произвести перестановку
битов ( bit-reverse( 0xc704dd7b) = 0xdebb20e3),
и еще сделать так:
0xdebb20e3 ^ 0xffffffff = 0x2144df1c - вот только теперь получим сходство.


На последовательностях отличных от {0,0,0,0} и {255,255,255,255} всё-равно результаты разные.
Вот что удалось найти
https://my.st.com/public/STe2ecommunities/m...rrentviews=1996
Продублирую кодом
CODE

u32 revbit(u32 data)
{
asm("rbit r0,r0");
return data;
};

u32 CalcCRC32(u8 *buffer,u32 size)
{
u32 i, j;
u32 ui32;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC,ENABLE);

CRC->CR=1;

asm("NOP");asm("NOP");asm("NOP");//delay for hardware ready

i = size >> 2;

while(i--)
{
ui32=*((u32 *)buffer);

buffer += 4;

ui32=revbit(ui32);//reverse the bit order of input data

CRC->DR=ui32;
}

ui32=CRC->DR;

ui32=revbit(ui32);//reverse the bit order of output data

i = size & 3;

while(i--)
{
ui32 ^= (u32)*buffer++;

for(j=0; j<8; j++)
if (ui32 & 1)
ui32 = (ui32 >> 1) ^ 0xEDB88320;
else
ui32 >>= 1;
}

ui32^=0xffffffff;//xor with 0xffffffff

return ui32;//now the output is compatible with windows/winzip/winrar
};

Не вникал, что к чему, но метод работает. Быстрее классического табличного CRC32 алгоритма (аналогичному коду из википедии) в ~3 раза. И не нужен буфер 1 кБайт под таблицу.
vlad_new
В STM32 кривой аппаратный CRC. Я долго пытался понять какому стандарту он соответствует. Оказалось, что у них перевернут регистр сзаду на перед. Так что если нужно вычеслить CRC скажем для Ethrnet, то туда надо заганять перевернутые данные, а затем, после чтения их опять надо перевренуть ( все биты местами менять предется ). Потом мне сказали, что в какой то эррате это было прописано, правда я так и не нашел эту еррату.


Sergey_Aleksandrovi4
Да, если бы не необходимость менять порядок следования бит в каждой итерации (благо делается всего одной инструкцией), можно бы было прикрутить расчёт CRC к DMA (в теории). Но тем не менее работает всяко быстрее чисто программных решений.
yurmala
В коллекцию исходников:
Open Source утилитка расчета всевозможных контрольных сумм в основном табличным методом.
http://fsumfe.sourceforge.net/
Сами алгоритмы лежат в папке src\fsumfe\digest\algo\
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.