STM32G030 / CRC_DR / 如何使用32位写入?

问题描述 投票:0回答:1

当我对 CRC_DR 使用字访问时,不知怎的,我没有得到 0xD0FA 和 0x12345678 和 16 位 POLY 0x1021。

示例:伪代码:

RCC.CRCEN=1; CRC_CR.POLYSIZE=0b01; CRC_POL=0x1021; CRC_INIT=0; CRC_CR.RESET=1;
CRC_DR=0x12345678;
CRC_DR contains 0x0000B42C but my own CRC routine says 0xD0FA.

但这工作正常:

RCC.CRCEN=1; CRC_CR.POLYSIZE=0b01; CRC_POL=0x1021; CRC_INIT=0; CRC_CR.RESET=1;
CRC_DR=0x78563412;

REV* 位都没有帮助我(我尝试了所有 8 种组合......)。 我想知道在哪种情况下 REV* 位可以提供帮助...... 更有可能的是,字节顺序需要调整...... 例如:

char word[4] = {'b','i','r','d'};
The 'b' should be fed first to the CRC unit...

我更喜欢使用“DMA 访问”这个词,因为: 与 DMA-1 字节相比,速度快两倍多,比我手工制作的汇编程序例程快 25%...

stm32 endianness crc dma
1个回答
0
投票

STM32 CRC 单元莫名其妙地输入从最高有效字节开始,正如您已经注意到的那样,这与该 MCU 的整个其余部分是小端字节序相冲突。因此,如果内存中有字节 0x12 0x34 0x56 0x78 并且将它们作为一个字读取,它们将被读取为 0x78563412 并且 CRC 单元将它们作为 0x78 0x56 0x34 0x12 输入,而如果您逐字节读取并输入对于 CRC,它们的顺序为 0x12 0x34 0x56 0x78 - 这当然会导致不同的结果。后一种方法是绝大多数通信和存储协议中常用的方法,这就是为什么大多数用户对 STM32 CRC 单元感到困惑(包括我)。

较新的 STM32 CRC_CR 中的 REV_xx 位对此无济于事,因为它们执行按位反转,但它们不交换字节。需要按位反转,因为一些 CRC 化身就是这样简单定义的。归根结底,CRC 只是一个带有反馈抽头的移位寄存器,并且移位寄存器可以设计为任一方向。这与初始/最终异或和其他一些很少使用的晦涩功能一起,使得 CRC 作为一种可参数化的算法达到了痛苦的程度。

现在,如果您使用处理器馈送 CRC(与 DMA 不同,DMA 中仅按字节馈送是可行的,但考虑到它可以自主工作,这并不那么痛苦),在从内存中读取单词之后并将其馈送到 CRC 之前,您可以使用

REV指令交换字节。在 C 中,您可以使用 CMSIS 内在函数 __REV()

JW

© www.soinside.com 2019 - 2024. All rights reserved.