crc32

gingerologist
Posts: 8
Joined: Fri Nov 12, 2021 12:49 am

crc32

Postby gingerologist » Tue Aug 12, 2025 1:30 pm

根据官方资料,esp32和stm32h7的硬件crc32使用了同一个多项式。但是我实际测试发现,比如一个uint32_t类型的数组,需要把每个uint32_t数据先byteswap,然后再使用crc32_be api,两者才能算得一致的结果,而且esp32的初始值和结果还需要位反转(~),具体的,比如stm32上

Code: Select all

	static uint32_t chunk[5] =
	{ 0x12345678, 0x9ABCDEF0, 0x12345678, 0x00000000, 0xffffffff };

	printf("[0x00000000]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[3], 1));
	printf("[0xffffffff]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[4], 1));
	printf("[0x12345678]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[0], 1));
	printf("[0x9ABCDEF0]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[1], 1));
	printf("[0x12345678,0x9ABCDEF0]: 0x%08lx\r\n",
			HAL_CRC_Calculate(&hcrc, &chunk[0], 2));
	printf("[0x9ABCDEF0,0x12345678]: 0x%08lx\r\n",
			HAL_CRC_Calculate(&hcrc, &chunk[1], 2));

到了esp32-c3上代码要改成这样:

Code: Select all

    /* USER CODE BEGIN StartTestTask */
    uint32_t crc = 0xffffffff;

    // static uint32_t chunk[5] = {0x12345678, 0x9ABCDEF0, 0x12345678, 0x00000000, 0xffffffff};
    static uint32_t chunk[5] = {0x78563412, 0xF0DEBC9A, 0x78563412, 0x00000000, 0xffffffff};

    printf("=== crc test ===\r\n");

    // printf("[0x00000000]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[3], 1));
    ESP_LOGI("crc_test", "[0x00000000]: 0x%08lx\r\n", ~esp_rom_crc32_be(~crc, (const uint8_t *)&chunk[3], 4));
    ESP_LOGI("crc_test", "[0x00000000]: 0x%08lx\r\n", ~esp_rom_crc32_le(~crc, (const uint8_t *)&chunk[3], 4));

    // printf("[0xffffffff]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[4], 1));
    ESP_LOGI("crc_test", "[0xffffffff]: 0x%08lx\r\n", ~esp_rom_crc32_be(~crc, (const uint8_t *)&chunk[4], 4));
    ESP_LOGI("crc_test", "[0xffffffff]: 0x%08lx\r\n", ~esp_rom_crc32_le(~crc, (const uint8_t *)&chunk[4], 4));

    // printf("[0x12345678]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[0], 1));
    ESP_LOGI("crc_test", "[0x12345678]: 0x%08lx\r\n", ~esp_rom_crc32_be(~crc, (const uint8_t *)&chunk[0], 4));
    ESP_LOGI("crc_test", "[0x12345678]: 0x%08lx\r\n", ~esp_rom_crc32_le(~crc, (const uint8_t *)&chunk[0], 4));

    // printf("[0x9ABCDEF0]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[1], 1));
    ESP_LOGI("crc_test", "[0x9ABCDEF0]: 0x%08lx\r\n", ~esp_rom_crc32_be(~crc, (const uint8_t *)&chunk[1], 4));
    ESP_LOGI("crc_test", "[0x9ABCDEF0]: 0x%08lx\r\n", ~esp_rom_crc32_le(~crc, (const uint8_t *)&chunk[1], 4));

    // printf("[0x12345678,0x9ABCDEF0]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[0], 2));
    ESP_LOGI("crc_test", "[0x12345678,0x9ABCDEF0]: 0x%08lx\r\n", ~esp_rom_crc32_be(~crc, (const uint8_t *)&chunk[0], 8));
    ESP_LOGI("crc_test", "[0x12345678,0x9ABCDEF0]: 0x%08lx\r\n", ~esp_rom_crc32_le(~crc, (const uint8_t *)&chunk[0], 8));

    // printf("[0x9ABCDEF0,0x12345678]: 0x%08lx\r\n", HAL_CRC_Calculate(&hcrc, &chunk[1], 2));
    ESP_LOGI("crc_test", "[0x9ABCDEF0,0x12345678]: 0x%08lx\r\n", ~esp_rom_crc32_be(~crc, (const uint8_t *)&chunk[1], 8));
    ESP_LOGI("crc_test", "[0x9ABCDEF0,0x12345678]: 0x%08lx\r\n", ~esp_rom_crc32_le(~crc, (const uint8_t *)&chunk[1], 8));
其中BE版本的输出结果才和stm32一致。而如下这个软实现版本,则无论在stm32还是esp32上,结果都和stm32的crc api结果一致。

Code: Select all

static uint32_t SW_CRC_Calculate(uint32_t init, const uint32_t pBuffer[], uint32_t wordLength)
{
    uint32_t crc32 = init;
    for (int k = 0; k < wordLength; k++)
    {
        crc32 = crc32 ^ pBuffer[k];

        for (int i = 0; i < 32; i++)
        {
            if (crc32 & 0x80000000)
                crc32 = (crc32 << 1) ^ 0x04C11DB7;
            else
                crc32 = (crc32 << 1);
        }
    }

    return crc32;
}
请问stm32和esp32的硬件crc能不通过byteswap每个32bit word得到同样的结果吗?我需要在通讯中使用这个crc32校验数据包,不大可能考虑全部copy再byteswap的方式来实现这个校验。

Who is online

Users browsing this forum: No registered users and 3 guests