匹配来自STM32F0和zlib的CRC32

eva*_*ing 4 c linux crc32 crc stm32

我正在研究运行Linux和STM32F0的计算机之间的通信链接.我想对我的数据包使用某种错误检测,因为STM32F0有CRC32 hw,我在Linux上有zlib和CRC32,我认为在我的项目中使用CRC32是个好主意.问题是我不会在不同平台上获得相同数据的CRC值.

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>

int
main(void)
{
  uint8_t byte0 = 0x00;
  uint32_t crc0 = crc32(0L, Z_NULL, 0);
  crc0 = crc32(crc0, &byte0, 1);
  printf("CRC32 value of %" PRIu8 " is: %08" PRIx32 "\n", byte0, crc0);
}
Run Code Online (Sandbox Code Playgroud)

输出CRC32 value of 0 is: d202ef8d与几个在线计算器的结果相匹配.

看来我在STM32上使用的任何设置都无法获得相同的CRC.我已经找到了一个关于CRC hw如何在ST的应用笔记中计算其值的流程图,但我无法弄清楚它是如何在zlib中完成的.

有谁知道它们是否兼容?

[编辑1]它们都使用相同的初始值和多项式.

[编辑2] STM32代码相对来说非常复杂,因为它使用的是hw.

...
/* Default values are used for init value and polynomial, see edit 1 */
CRC->CR |= CRC_CR_RESET;
CRC->DR = (uint8_t)0x00;
uint32_t crc = CRC->DR;
...
Run Code Online (Sandbox Code Playgroud)

小智 7

STM32Fx上的CRC32实现似乎不是许多在线CRC计算器和zip中使用的标准CRC32实现.

STM32实现了CRC32-MPEG2,与使用小端和最终翻转掩码的zip CRC32相比,它使用大端而没有最终翻转掩码.

我发现这个在线计算器支持CRC32-MPEG2.

如果您对其他CRC算法及其实现更感兴趣,请查看此链接.

PS:STM的HAL驱动程序支持字节,半字和字格式的输入,它们似乎在v1.3.1中适用于STM32F0x

  • 仅供参考:您可以使用`CRC_ReverseInputDataSelect(CRC_ReverseInputData_32bits);`CRC_ReverseOutputDataCmd(ENABLE);```stdperiph`库中的STM32F0来配置CRC32,我没有查看更新的`HAL`库.您只需要反转从硬件中读取的结果. (2认同)

Mar*_*ler 5

从文档中可以看出,您的STM32代码不仅无趣 - 它还不完整.从文档中,为了使用CRC硬件,您需要:

  1. 通过RCC外设使能CRC外设时钟.
  2. 通过配置初始CRC值寄存器(CRC_INIT)将CRC数据寄存器设置为初始CRC值.(a)
  3. 通过CRC控制寄存器(CRC_CR)中的REV_IN [1:0]和REV_OUT位分别设置I/O反向位顺序.(a)
  4. 通过CRC控制寄存器(CRC_CR)和CRC多项式寄存器(CRC_POL)中的POLYSIZE [1:0]位分别设置多项式大小和系数.(b)
  5. 通过CRC控制寄存器(CRC_CR)中的复位位复位CRC外设.
  6. 将数据设置为CRC数据寄存器.
  7. 读取CRC数据寄存器的内容.
  8. 禁用CRC外设时钟.

特别注意步骤2,3和4,它们定义了计算的CRC.他们说他们的例子有rev_in和rev_out假,但对于zlib crc,他们需要是真的.根据硬件的实现方式,多项式也可能需要反转(0xedb88320UL).初始CRC需要0xffffffff,并且最终CRC被反转以匹配zlib crc.

  • 想想我会从zlib本人的"上帝之父"那里得到答案,太棒了!CRC_INIT和Polynomial默认情况下与zlib相同.结果的rev_in,rev_out和最终反转让我在那里.谢谢! (3认同)