Аппаратный CRC32 на stm32

CRC — распространённый алгоритм вычисления хэш сумм. Применяется для контроля целостности данных, во время их передачи, хранения… Очень удобно, что в stm32 есть встроенный аппаратный модуль для вычисления crc32, с которым при этом очень просто работать. Но есть и пара ложек дёгтя.

Аппаратный модуль CRC32 на STM32

Заметка по работе с аппаратным модулем crc32 на stm32 и его расчёт со стороны компьютера.

Ещё раз рассмотрим, где может быть полезен и/или необходим алгоритм подсчёта контрольной суммы.

  • При передачи данных. По UART, по ethernet, SPI, I2C… по любому интерфейсу, что бы контролировать целостность данных, т.к. во время передачи различные помехи, сбои оборудования, иные факторы, злоумышленники могут исказить или подменить данные. Хотя с целью защиты от злоумышленников нужно прибегнуть уже к шифрованию.
  • Точно так же и при хранении данных, в случае сбоя оборудования, слишком длительного хранения, вмешательства 3-тьих лиц, негативных воздействий на носитель информации или контроллер тоже могут привести к порче или модификации данных. Проверка контрольной суммы прошивки контроллера или хранимых данных поможет проверить их целостность и вовремя предпринять требуемые меры в случае не совпадения хэш кодов.

Задача для котороой мне понадобилась хэш сумма — проверка целостности при перепрошивки контроллера через Wi-Fi.

В контроллерах семейства stm32 есть аппаратный блок подсчёта контрольной суммы crc32 с полиномом 0x04C11DB7. Работа с этим блоком представлена одним регистром CRC->DR, в который мы можем отправлять пачки из 4-х байт для расчёта и читать данный регистр для получения текущей рассчитанной контрольной суммы. Для сброса в регистр CRC->CR нужно записать 1, при этом в конвертер запишется 0xFFFFFFFF. По умолчанию блок выключен, как и вся периферия контроллера, для его включения нужно подать на него тактирования. Работа с аппаратным модулем расчётом хэш суммы проста.

Работа с модулем crc32 с использованием Standard Peripheral Library.

unsigned long data,crc;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE); // включение тактирования модуля crc32
CRC_ResetDR(); // сброс 
CRC_CalcCRC(data); // отправить 4 байта
crc = CRC_GetCRC(); // получить контрольную сумму

Переменные:
data — данные
crc — рассчитанная контрольная сумма

Работа с модулем на уровне регистров.

unsigned long data,crc;
RCC->AHBENR |= RCC_AHBPeriph_CRC;  // включение тактирования модуля crc32
CRC->CR = 1; // сброс
CRC->DR = data; // отправить 4 байта
crc = CRC->DR; // получить контрольную сумму

Пример использования, для подсчёта контрольной суммы прошивки:

unsigned long flash_read(unsigned long address) //	Чтение из flash
	return (*(__IO unsigned long*) address);

CRC_ResetDR(); // сброс
for(i=0;i<size_file ;i+=4)
	CRC_CalcCRC(flash_read(0x08000000+i));
crc=CRC_GetCRC();

size_file — размер прошивки.

Но как ранее говорилось есть и минусы данного блока. Фиксированный полином, сброс устанавливает только значение 0xFFFFFFFF. Но самое плохое, что данный блок работает нестандартно, т.е. отлично от классического алгоритма расчёта crc32. Алгоритм производит побитную перестановку, как на входе, так и на выходе, плюс на выходе происходит ещё и инверсия. Но это можно решить добавив пару инструкций, которые есть у stm32.

CRC_CalcCRC(__REV(Data));
Data=__REV(CRC_GetCRC())^0xFFFFFFFF;

Вторая неприятность, в том, что большинство распространённых утилит для расчёта crc32 под windows (такие как Total Commander, WinRAR, WinZIP…) и большинство доступных алгоритмов в интернете считаю не «классический» crc32, а его разновидность crc32b.

Сравнение хэш сумм для входного значения 123456789:


crc32 181989fc
crc32b cbf43926
crc32 stm32 61706427

Сравнение хэш сум (на этом сайте алгоритм имеет название crc32b php).
Онлайн калькулятор crc32 и crc32b .

Выходит, что с одной стороны аппаратный модуль расчёта crc32 в stm32 есть, но большинство распространённых утилит для работы с ним не подходят.

Поиск решения привел на сайт, где выложена софтверная версия алгоритма для расчёта crc32, который его рассчитывает так же, как аппаратный модуль stm32. На сайте есть реализация под C и под Delphi. Перейти на сайт.

Для упрощения своей работы, на основе ране упомянутого алгоритма, была написана специальная небольшая утилита, которая производит расчёт crc32, так, как его считает stm32 для бинарных файлов (с расширением *.bin). Утилита получила название crc32_for_stm32.exe . Запуск производится с параметром, в котором указывается название файла с расширением *.bin, для которого нужно произвести расчёт контрольной суммы. После расчёта рядом появляется файл с тем же названием, но разрешением *.crc, который содержит рассчитанную контрольную сумму в шестнадцатеричном представлении.

Пример запуска утилиты из командной строки для файла project.bin

crc32_for_stm32 project

Данную утилиту можно подключить к IDE, для среды CooCox это можно сделать на вкладке User в настройках проекта.

${project.path}/project/debug/bin/crc32_for_stm32.exe project

Подключение к CooCox утилиты crc32_for_stm32

Подключение к CooCox утилиты crc32_for_stm32

В IAR есть встроенные средства, которые можно включить в настройках проекта.

Скачать утилиту расчета crc32

Программная реализация алгоритм для расчёта crc32 таким же способом, что и на stm32 была найден на сайте www.cnblogs.com/shangdawei/archive/2013/04/28/3049789.html

3 комментария »

Alex_EXE | 25.08.2016 | STM32 | 1 050 просмотров

3 комментария на « Аппаратный CRC32 на stm32»

  1. Алексей пишет 18.12.2016 в 13:30 #

    На F051 попробовал разные варианты вычисления CRC для числа 123456789 — реверс на выходе, реверс на входе. Перед каждой пробой сбрасывал модуль. Но ни один вариант не соответствует результату в статье 61706427 (что в hex, что в dec). Скачал утилиту, попробовал в ней — перевёл 123456789 в НЕХ, сохранил как bin. Но результат работы утилиты не соответствует ни результату на сайте, ни результату работы F051, при чём, пробовал разные порядки байт: старший в начале, старший в конце. В чём прикол?

  2. Alex_EXE пишет 18.12.2016 в 18:21 #

    Пример работы утилиты
    iPod Shuffle
    В примере 123456789 — это текстовая строка, следовательно в HEX имеем 31 32 33 34 35 36 37 38 39

  3. Алексей пишет 23.12.2016 в 13:14 #

    Спасибо, теперь понял свою проблему: я брал числом 123456789, а не строку. вот отличный онлайн-калькулятор http://www.sunshine2k.de/coding/javascript/crc/crc_js.html, который даёт результат как и на STM32 с любыми реверсами. Я из него взял таблицу остатков, так как только с ней всё заработало. Потом вот отсюда http://www.cnblogs.com/shangdawei/archive/2013/04/28/3049789.html взял функцию uint32_t stm32_sw_crc32_by_byte(uint32_t crc32, uint8_t pBuffer[], uint32_t NumOfByte), но она не работала с родной таблицей но пошла с таблицей из калькулятора. Может я что-то не понял, но сейчас всё работает чётко — и на ПК и на STM CRC считается одинаково.

Комментарии RSS

Оставьте отзыв