简体   繁体   English

匹配来自STM32F0和zlib的CRC32

[英]Matching CRC32 from STM32F0 and zlib

I'm working on a communication link between a computer running Linux and a STM32F0. 我正在研究运行Linux和STM32F0的计算机之间的通信链接。 I want to use some kind of error detection for my packets and since the STM32F0 has CRC32 hw and I have zlib with CRC32 on Linux I thought it would be a good idea to use CRC32 for my project. 我想对我的数据包使用某种错误检测,因为STM32F0有CRC32 hw,我在Linux上有zlib和CRC32,我认为在我的项目中使用CRC32是个好主意。 The problem is that I won't get the same CRC value for the same data on the different platforms. 问题是我不会在不同平台上获得相同数据的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);
}

outputs CRC32 value of 0 is: d202ef8d which matches the result on several online calculators. 输出CRC32 value of 0 is: d202ef8d ,它匹配几个在线计算器的结果。

It seems though that whatever settings I use on the STM32 I can't get the same CRC. 看来我在STM32上使用的任何设置都无法获得相同的CRC。 I have found a flowchart on how the CRC hw calculates its value in an application note from ST but I can't figure out how it's done in zlib. 我已经找到了一个关于CRC hw如何在ST的应用笔记中计算其值的流程图,但我无法弄清楚它是如何在zlib中完成的。

Does anyone know if they are compatible? 有谁知道它们是否兼容?

[edit 1] They both uses the same init value and polynomial. [编辑1]它们都使用相同的初始值和多项式。

[edit 2] The STM32 code is relatively uninteresging since it's using the hw. [编辑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;
...

The CRC32 implementation on STM32Fx seems to be not the standard CRC32 implementation you find on many online CRC calculators and the one used in zip. STM32Fx上的CRC32实现似乎不是许多在线CRC计算器和zip中使用的标准CRC32实现。

STM32 implements CRC32-MPEG2 which uses big endian and no final flip mask compared to the zip CRC32 which uses little endian and a final flip mask. STM32实现了CRC32-MPEG2,与使用小端和最终翻转掩码的zip CRC32相比,它使用大端而没有最终翻转掩码。

I found this online calculator which supports CRC32-MPEG2. 我发现这个在线计算器支持CRC32-MPEG2。

If you are more interested on other CRC algorithms and their implementation, look at this link . 如果您对其他CRC算法及其实现更感兴趣,请查看此链接

PS: The HAL driver from STM supports input in byte, half word and word formats and they seem to work fine for STM32F0x in v1.3.1 PS:STM的HAL驱动程序支持字节,半字和字格式的输入,它们似乎在v1.3.1中适用于STM32F0x

From the documentation, it appears that your STM32 code is not just uninteresting — it is rather incomplete. 从文档中可以看出,您的STM32代码不仅无趣 - 它还不完整。 From the documentation, in order to use the CRC hardware you need to: 从文档中,为了使用CRC硬件,您需要:

  1. Enable the CRC peripheral clock via the RCC peripheral. 通过RCC外设使能CRC外设时钟。
  2. Set the CRC Data Register to the initial CRC value by configuring the Initial CRC value register (CRC_INIT).(a) 通过配置初始CRC值寄存器(CRC_INIT)将CRC数据寄存器设置为初始CRC值。(a)
  3. Set the I/O reverse bit order through the REV_IN[1:0] and REV_OUT bits respectively in CRC Control register (CRC_CR).(a) 通过CRC控制寄存器(CRC_CR)中的REV_IN [1:0]和REV_OUT位分别设置I / O反向位顺序。(a)
  4. Set the polynomial size and coefficients through the POLYSIZE[1:0] bits in CRC Control register (CRC_CR) and CRC Polynomial register (CRC_POL) respectively.(b) 通过CRC控制寄存器(CRC_CR)和CRC多项式寄存器(CRC_POL)中的POLYSIZE [1:0]位分别设置多项式大小和系数。(b)
  5. Reset the CRC peripheral through the Reset bit in CRC Control register (CRC_CR). 通过CRC控制寄存器(CRC_CR)中的复位位复位CRC外设。
  6. Set the data to the CRC Data register. 将数据设置为CRC数据寄存器。
  7. Read the content of the CRC Data register. 读取CRC数据寄存器的内容。
  8. Disable the CRC peripheral clock. 禁用CRC外设时钟。

Note in particular steps 2, 3, and 4, which define the CRC being computed. 特别注意步骤2,3和4,它们定义了计算的CRC。 They say that their example has rev_in and rev_out false, but for the zlib crc, they need to be true. 他们说他们的例子有rev_in和rev_out假,但对于zlib crc,他们需要是真的。 Depending on the way the hardware is implemented, the polynomial will likely need to reversed as well ( 0xedb88320UL ). 根据硬件的实现方式,多项式也可能需要反转( 0xedb88320UL )。 The initial CRC needs to be 0xffffffff , and the final CRC inverted to match the zlib crc. 初始CRC需要为0xffffffff ,并且最终CRC被反转以匹配zlib crc。

I haven't tested this, but I suspect that you're not, in fact, doing an 8-bit write on the STM32. 我没有对此进行测试,但我怀疑你实际上并没有在STM32上进行8位写操作。

Instead you're probably doing a write to the full width of the register (32 bits), which of course means you're computing the CRC32 of more bytes than you intended. 相反,你可能正在写入寄存器的整个宽度(32位),这当然意味着你计算的CRC32比你想要的更多。

Disassemble the generated code to analyze the exact store instruction that is being used. 反汇编生成的代码以分析正在使用的确切存储指令。

I had similar issues implementing a CRC on an STM32 CRC module where the final checksum was not matching. 我在STM32 CRC模块上实现CRC的类似问题,其中最终校验和不匹配。 I was able to fix this by looking at the example code in stm32f30x_crc.c that is provided with STMCube. 我能够通过查看STMCube提供的stm32f30x_crc.c中的示例代码来解决这个问题。 In the source it has a function for 8-bit CRC that used the following code 在源中,它具有使用以下代码的8位CRC功能

(uint8_t )(CRC_BASE) = (uint8_t) CRC_Data; (uint8_t )(CRC_BASE)=(uint8_t)CRC_Data;

to write to the DR register. 写入DR寄存器。 As stated previously, the line CRC->DR is defined as volatile uint32_t which will access the whole register. 如前所述,CRC-> DR行定义为volatile uint32_t,它将访问整个寄存器。 It would have been helpful if ST had been more explicit about accessing the DR register rather than simply saying it supports 8-bit types. 如果ST更明确地访问DR寄存器而不是简单地说它支持8位类型,那将会很有帮助。

From my experience, you can not compare the CRC32 code between the STM32 CRC unit output with the online CRC32 calculator. 根据我的经验,您无法比较STM32 CRC单元输出与在线CRC32计算器之间的CRC32代码。

Please find my CRC32 calculator for STM32 in this link . 在此链接中找到我的用于STM32的CRC32计算器。

This function has been used in my project, and proved to be correct. 此功能已在我的项目中使用,并证明是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM