Atmel SAM G55 CRCCU CRC32 计算不可复制
Atmel SAM G55 CRCCU CRC32 calculation not replicateable
我们在我们的一个应用程序中使用了 Atmel SAM G55。在某些时候,我们想在 x86 系统上计算一个 CRC32 并将其传递给 G55(Arm 32 位)。
对于 G55,我们使用 CRCCU 来计算 CRC32:
uint32_t crccu_crc32(uint8_t *p_buffer, uint32_t ul_length, uint32_t *pcrc)
{
uint32_t ul_crc;
uint32_t ul_timeout = 0;
if (*pcrc == ~0) {
/* Reset the CRCCU */
crccu_reset(CRCCU);
}
memset((void *)&_crc_dscr, 0, sizeof(crccu_dscr_type_t));
_crc_dscr.ul_tr_addr = (uint32_t) p_buffer;
/* Transfer width: byte, interrupt enable */
_crc_dscr.ul_tr_ctrl = (uint32_t)ul_length | (2 << 24);
/* Configure CRCCU mode */
crccu_configure_mode(CRCCU, CRCCU_MR_ENABLE | CRCCU_MR_PTYPE_CCITT8023 | CRCCU_MR_DIVIDER(0));
/* Start the CRC calculation */
crccu_enable_dma(CRCCU);
/* Wait for calculation ready */
while ((crccu_get_dma_status(CRCCU) == CRCCU_DMA_SR_DMASR) &&
(ul_timeout++ < 0xFFFFFFFF)) {
}
if (ul_timeout == 0xFFFFFFFF) {
return 1;
}
/* Get CRC value */
*pcrc = crccu_read_crc_value(CRCCU);
return 0;
}
这个函数与 ASF4 的 CRC-HAL 松散相关并且工作正常(至少我们是这么认为的)。
但是,我们无法在我们的 x86 机器上计算相同的 CRC32。
为了测试 CRC32 计算,我们使用以下测试数组:
uint32_t chksmtest[8] = {6448116,148714,884134,43,5487416,45486,8484384,64817};
使用 CRCCU 计算 CRC32 得到 0x4d4ee8cc
结果。
我们在 x86 机器上尝试了几种 CRC32 实现,但无法复制此结果。我们知道CRCCU先计算CRC32LSB(G55 reference page 901) and the polynomial is 0x04C11DB7
(G55 reference page 916).
即使颠倒位 and/or 字节顺序,我们也无法复制结果。我们必须使用哪种 CRC32 实现来存档与 CRCCU 相同的结果?我们尝试了 libiberty 实现以及 W3 实现。
您的硬件正在使用多项式 0x04c11db7
计算 non-reflected 32 位 CRC,初始值为 0xffffffff
,没有最终异或。该 CRC 有一个名称:CRC-32/MPEG-2.
如前所述,您提供的 32 位值按 little-endian 顺序处理,最低有效字节在前。
当且仅当 下面的 C 代码在 little-endian 机器(例如 x86)上是 运行 时,它将产生您想要的结果:
#include <stddef.h>
unsigned crc32_mpeg2(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0xffffffff;
while (len--) {
crc ^= (unsigned)(*data++) << 24;
for (unsigned k = 0; k < 8; k++)
crc = crc & 0x80000000 ? (crc << 1) ^ 0x4c11db7 : crc << 1;
}
return crc & 0xffffffff;
}
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint32_t chksmtest[8] =
{6448116,148714,884134,43,5487416,45486,8484384,64817};
printf("0x%08x\n", crc32_mpeg2(crc32_mpeg2(0, NULL, 0), chksmtest, 8 * 4));
return 0;
}
输出:
0x4d4ee8cc
以上是一个简单的bit-wise实现。您可以查看 crcany 在软件中为该 CRC 生成更高效的 CRC 实现。
我们在我们的一个应用程序中使用了 Atmel SAM G55。在某些时候,我们想在 x86 系统上计算一个 CRC32 并将其传递给 G55(Arm 32 位)。
对于 G55,我们使用 CRCCU 来计算 CRC32:
uint32_t crccu_crc32(uint8_t *p_buffer, uint32_t ul_length, uint32_t *pcrc)
{
uint32_t ul_crc;
uint32_t ul_timeout = 0;
if (*pcrc == ~0) {
/* Reset the CRCCU */
crccu_reset(CRCCU);
}
memset((void *)&_crc_dscr, 0, sizeof(crccu_dscr_type_t));
_crc_dscr.ul_tr_addr = (uint32_t) p_buffer;
/* Transfer width: byte, interrupt enable */
_crc_dscr.ul_tr_ctrl = (uint32_t)ul_length | (2 << 24);
/* Configure CRCCU mode */
crccu_configure_mode(CRCCU, CRCCU_MR_ENABLE | CRCCU_MR_PTYPE_CCITT8023 | CRCCU_MR_DIVIDER(0));
/* Start the CRC calculation */
crccu_enable_dma(CRCCU);
/* Wait for calculation ready */
while ((crccu_get_dma_status(CRCCU) == CRCCU_DMA_SR_DMASR) &&
(ul_timeout++ < 0xFFFFFFFF)) {
}
if (ul_timeout == 0xFFFFFFFF) {
return 1;
}
/* Get CRC value */
*pcrc = crccu_read_crc_value(CRCCU);
return 0;
}
这个函数与 ASF4 的 CRC-HAL 松散相关并且工作正常(至少我们是这么认为的)。 但是,我们无法在我们的 x86 机器上计算相同的 CRC32。
为了测试 CRC32 计算,我们使用以下测试数组:
uint32_t chksmtest[8] = {6448116,148714,884134,43,5487416,45486,8484384,64817};
使用 CRCCU 计算 CRC32 得到 0x4d4ee8cc
结果。
我们在 x86 机器上尝试了几种 CRC32 实现,但无法复制此结果。我们知道CRCCU先计算CRC32LSB(G55 reference page 901) and the polynomial is 0x04C11DB7
(G55 reference page 916).
即使颠倒位 and/or 字节顺序,我们也无法复制结果。我们必须使用哪种 CRC32 实现来存档与 CRCCU 相同的结果?我们尝试了 libiberty 实现以及 W3 实现。
您的硬件正在使用多项式 0x04c11db7
计算 non-reflected 32 位 CRC,初始值为 0xffffffff
,没有最终异或。该 CRC 有一个名称:CRC-32/MPEG-2.
如前所述,您提供的 32 位值按 little-endian 顺序处理,最低有效字节在前。
当且仅当 下面的 C 代码在 little-endian 机器(例如 x86)上是 运行 时,它将产生您想要的结果:
#include <stddef.h>
unsigned crc32_mpeg2(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0xffffffff;
while (len--) {
crc ^= (unsigned)(*data++) << 24;
for (unsigned k = 0; k < 8; k++)
crc = crc & 0x80000000 ? (crc << 1) ^ 0x4c11db7 : crc << 1;
}
return crc & 0xffffffff;
}
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint32_t chksmtest[8] =
{6448116,148714,884134,43,5487416,45486,8484384,64817};
printf("0x%08x\n", crc32_mpeg2(crc32_mpeg2(0, NULL, 0), chksmtest, 8 * 4));
return 0;
}
输出:
0x4d4ee8cc
以上是一个简单的bit-wise实现。您可以查看 crcany 在软件中为该 CRC 生成更高效的 CRC 实现。