Аппаратный CRC32 на stm32
CRC — распространённый алгоритм вычисления хэш сумм. Применяется для контроля целостности данных, во время их передачи, хранения… Очень удобно, что в stm32 есть встроенный аппаратный модуль для вычисления crc32, с которым при этом очень просто работать. Но есть и пара ложек дёгтя.
Заметка по работе с аппаратным модулем 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. Запуск производится с параметром, в котором указывается название файла, для которого нужно произвести расчёт контрольной суммы. После расчёта рядом появляется файл с тем же названием, но добавленным разрешением *.crc, который содержит рассчитанную контрольную сумму в шестнадцатеричном представлении. Для корректного запуска утилиты из командных файлов (*.cmd, *.bat) рекомендуется прописывать полный путь до утилиты и обрабатываемого файла в двойных кавычках, если только запуск не производится в одном каталоге с обрабатываемым файлом.
Пример запуска утилиты из командной строки для файла project.bin
crc32_for_stm32 project.bin
С полным путём:
"c:\programm\crc_calk\crc32_for_stm32.exe" "c:\source\project\project.bin"
По завершению работы утилиты в папке появится файл project.bin.crc
Данную утилиту можно подключить к IDE, для среды CooCox это можно сделать на вкладке User в настройках проекта.
c:\programm\crc_calk\crc32_for_stm32.exe" "${project.path}\project \Debug\bin\project.bin"
или с прописью полного пути:
"c:\programm\crc_calk\crc32_for_stm32.exe" " c:\source\project\project \Debug\bin\project.bin"
Подключение к CooCox утилиты crc32_for_stm32
В IAR есть встроенные средства, которые можно включить в настройках проекта.
Скачать утилиту расчета crc32 v1.3
Обновление утилиты v1.3 от 2021.10.04:
- Теперь утилите можно скармливает файлы с любым расширением, а не только bin. Так же была решена проблема с неверным путём к рассчитываемому файлу.
Программная реализация алгоритм для расчёта crc32 таким же способом, что и на stm32 была найден на сайте www.cnblogs.com/shangdawei/archive/2013/04/28/3049789.html
Если оригинальный сайт с алгоритмом недоступен: stm32_crc32.c, stm32_crc32.pas .
Статья и программа обновлена 2021.10.04
Alex_EXE | 25.08.2016 | STM32 |
Алексей пишет 18.12.2016 в 13:30 #
На F051 попробовал разные варианты вычисления CRC для числа 123456789 — реверс на выходе, реверс на входе. Перед каждой пробой сбрасывал модуль. Но ни один вариант не соответствует результату в статье 61706427 (что в hex, что в dec). Скачал утилиту, попробовал в ней — перевёл 123456789 в НЕХ, сохранил как bin. Но результат работы утилиты не соответствует ни результату на сайте, ни результату работы F051, при чём, пробовал разные порядки байт: старший в начале, старший в конце. В чём прикол?
Alex_EXE пишет 18.12.2016 в 18:21 #
Пример работы утилиты
В примере 123456789 — это текстовая строка, следовательно в HEX имеем 31 32 33 34 35 36 37 38 39
Алексей пишет 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 считается одинаково.
Денис пишет 18.05.2017 в 23:04 #
В примере с работой на уровне регистров нужно заменить
RCC->AHBENR |= RCC_AHBPeriph_CRC;
на
RCC->AHBENR |= RCC_AHBENR_CRCEN;
т.к. первый вариант без SPL не скомпилируется.
Alex пишет 08.07.2017 в 12:34 #
Добрый день. Сайт с исходниками для C не доступен. Если есть возможность, не могли бы вы переслать исходный проект или выложить на этой странице?
Спасибо.
Владимир пишет 11.04.2018 в 16:49 #
Спасибо. Помогло. Искал реализацию на Delphi. По ссылке все скачал. Заработало.
Алексей пишет 01.12.2021 в 13:41 #
Нет утилиты crc32_for_stm32 по ссылке
Alex_EXE пишет 07.01.2022 в 03:33 #
Файл вернул.
Были проблемы с сайтом, сейчас исправляем.