| ESP-IDF: вычисление CRC32 |
|
| Добавил(а) microsin |
|
В ESP-IDF вычисление CRC32 выполняется с помощью аппаратно-ускоренных функций, находящихся в ПЗУ (ROM) чипа. Основной способ — использовать функции из компонента esp_rom_crc.h, которые поддерживают различные стандарты CRC, включая CRC32 в little-endian и big-endian вариантах [1]. [Основные функции CRC32 в ESP-IDF] Самые важные функции для расчёта CRC32 объявлены в заголовочном файле esp_rom_crc.h: esp_rom_crc32_le(uint32_t crc, const uint8_t *buf, uint32_t len) — для little-endian режима. Обе функции используют стандартный для ESP32 полином CRC-32: 0x04c11db7. Особенности использования. Библиотека спроектирована так, чтобы поддерживать вычисление CRC для данных, разделённых на несколько буферов. В начале и в конце расчётов необходимо инвертировать начальное и конечное значения (с помощью оператора `~`). Это связано с тем, как функции реализованы в ПЗУ и описано в официальной документации. [Примеры расчёта CRC32] Ниже приведены примеры для нескольких распространённых стандартов CRC32. Полином для всех примеров — 0x04c11db7. Пример 1: CRC-32 (ISO/HDLC). Этот стандарт используется, например, в протоколах Ethernet, PKZIP, GZip. #include "esp_rom_crc.h" Пояснение: UINT32_MAX (или ~0UL) — это инвертированное начальное значение 0x00000000. Функция crc32_le используется, так как требуется отражение (refin/refout=true). Конечный результат инвертируется. Пример 2: CRC-32/BZIP2. Используется в архиваторах BZIP2. #include "esp_rom_crc.h" Пояснение: Так как отражение не требуется (refin/refout=false), используется crc32_be. Начальное значение также инвертируется. Пример 3: CRC-32/MPEG-2. Применяется в транспортных потоках MPEG-2. #include "esp_rom_crc.h" Пояснение: особенность этого стандарта в том, что конечный результат не инвертируется (xorout=0), поэтому мы инвертируем то, что возвращает функция crc32_be. Пример 4: расчёт по частям (для больших данных). Если данные поступают не целиком, расчёт можно выполнять итеративно. uint32_t calculate_crc32_iso_hdlc_parts(const uint8_t *part1, [Альтернативный метод: mz_crc32] В ПЗУ также доступна функция mz_crc32 из библиотеки сжатия Miniz. Она предоставляет интерфейс, совместимый с библиотекой zlib, и может быть удобна в некоторых случаях. Её наличие зависит от конкретной модели чипа. mz_crc32 — это функция из библиотеки сжатия Miniz, встроенной в ПЗУ многих чипов Espressif (ESP32, ESP32-S2/S3, ESP32-C3/C2/C6 и др.). Она предоставляет интерфейс, совместимый с популярной библиотекой zlib, и вычисляет CRC-32 с теми же параметрами, что и crc32_le (полином 0x04c11db7, с отражением входных/выходных данных). Проверка наличия: убедиться, что функция доступна для вашего чипа, можно по наличию макроса ESP_ROM_HAS_MZ_CRC32 (обычно определён в esp_rom_caps.h) . #if ESP_ROM_HAS_MZ_CRC32 Функция объявлена в заголовочном файле rom/miniz.h и имеет следующий прототип: mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); Она идеально подходит для расчёта CRC по частям, так как принимает промежуточное значение crc. Пример 1: базовый расчёт CRC для одного блока данных. В этом примере показан стандартный способ вычисления CRC-32, совместимый с большинством утилит (ZIP, GZip и др.). #include < stdio.h> Пример 2: расчёт CRC по частям (для больших данных). Это основной способ использования mz_crc32 — обновлять контрольную сумму по мере поступления данных. #include < stdio.h> Сравнение с esp_rom_crc32_le. Главное отличие mz_crc32 от esp_rom_crc32_le — в инициализации и финальной обработке. Функция mz_crc32 имитирует поведение zlib, где: - Начальное значение для первого вызова должно быть `0` (а не `~0`, как требуется стандартом). Таким образом, обе функции дают один и тот же результат для стандарта CRC-32 (ISO/HDLC), но требуют разной подготовки входных данных. [Дополнительные сведения] ● CRC в NVS (Non-Volatile Storage): система энергонезависимого хранения ESP-IDF (NVS) [2] использует CRC32 для проверки целостности своих записей. При чтении данных из NVS их контрольная сумма автоматически проверяется, и если она не совпадает, запись считается недействительной. ● Расширение функциональности: в сообществе ESP-IDF обсуждается возможность добавления более гибкого и стандартизированного API для различных алгоритмов CRC (CRC-8, CRC-16/Modbus и др.), что может упростить жизнь разработчикам в будущем. [Ссылки] 1. Порядок следования байт (endianness). |