Embedded 如何计算被分割和缓冲的大数据块上的CRC32?
假设我有一个1024kb的数据,它经过1kB的缓冲,从发送器到接收器传输了1024次 最后一个缓冲区包含一个计算得出的CRC32值作为最后4个字节 然而,由于RAM限制,接收器必须逐个缓冲器计算CRC32缓冲器 我想知道如何应用CRC32计算的线性分布加法来匹配总CRC32值 我研究了CRC计算及其分配偏好。计算及其线性度不太清楚,无法实现 那么,是否存在一个数学表达式,用于将计算出的CRC32添加到缓冲器上,以与计算出的CRC32结果相匹配 例如:Embedded 如何计算被分割和缓冲的大数据块上的CRC32?,embedded,crc,crc32,distributive,Embedded,Crc,Crc32,Distributive,假设我有一个1024kb的数据,它经过1kB的缓冲,从发送器到接收器传输了1024次 最后一个缓冲区包含一个计算得出的CRC32值作为最后4个字节 然而,由于RAM限制,接收器必须逐个缓冲器计算CRC32缓冲器 我想知道如何应用CRC32计算的线性分布加法来匹配总CRC32值 我研究了CRC计算及其分配偏好。计算及其线性度不太清楚,无法实现 那么,是否存在一个数学表达式,用于将计算出的CRC32添加到缓冲器上,以与计算出的CRC32结果相匹配 例如: int CRC32Total = 0; in
int CRC32Total = 0;
int CRC32[1024];
for(int i = 0; i < 1024; i++){
CRC32Total = CRC32Total + CRC32[i];
}
int CRC32总计=0;
int CRC32[1024];
对于(int i=0;i<1024;i++){
CRC32总计=CRC32总计+CRC32[i];
}
开始传输时,使用OnFirstBlock方法将CrcChecksum重置为其初始值。对于收到的每个块,调用OnBlockReceived更新校验和。请注意,必须按照正确的顺序处理块。处理完最后一个块后,最后一个CRC在CrcChecksum变量中
// In crc32.c
uint32_t UpdateCrc(uint32_t crc, const void *data, size_t length)
const uint8_t *current = data;
while (length--)
crc = (crc >> 8) ^ Crc32Lookup[(crc & 0xFF) ^ *current++];
}
// In your block processing application
static uint32_t CrcChecksum;
void OnFirstBlock(void) {
CrcChecksum = 0;
}
void OnBlockReceived(const void *data, size_t length) {
CrcChecksum = UpdateCrc(CrcChecksum, data, length);
}
开始传输时,使用OnFirstBlock方法将CrcChecksum重置为其初始值。对于收到的每个块,调用OnBlockReceived更新校验和。请注意,必须按照正确的顺序处理块。处理完最后一个块后,最后一个CRC在CrcChecksum变量中
// In crc32.c
uint32_t UpdateCrc(uint32_t crc, const void *data, size_t length)
const uint8_t *current = data;
while (length--)
crc = (crc >> 8) ^ Crc32Lookup[(crc & 0xFF) ^ *current++];
}
// In your block processing application
static uint32_t CrcChecksum;
void OnFirstBlock(void) {
CrcChecksum = 0;
}
void OnBlockReceived(const void *data, size_t length) {
CrcChecksum = UpdateCrc(CrcChecksum, data, length);
}
对于“查看CRC计算”的实现或语言,您没有提供任何线索。然而,我所看到的每一个实现都是为逐段计算CRC而设计的,完全符合您的需要 对于zlib中提供的
crc32()
例程,可以使用它(在C中):
然后,crc
是所有块串联的crc。您不需要函数来组合单个块的CRC
如果出于其他原因,您确实需要一个函数来组合CRC,例如,如果您需要在多个CPU上拆分CRC计算,那么zlib为此提供了
crc32_combine()
函数。您没有提供任何线索,说明“查看CRC计算”的实现方式或语言。然而,我所看到的每一个实现都是为逐段计算CRC而设计的,完全符合您的需要
对于zlib中提供的crc32()
例程,可以使用它(在C中):
然后,crc
是所有块串联的crc。您不需要函数来组合单个块的CRC
如果出于其他原因,您确实需要一个函数来组合CRC,例如,如果您需要在多个CPU上拆分CRC计算,那么zlib为此提供了
crc32_combine()
函数。补充我对您问题的评论,我在这里添加了贯穿整个过程的代码:作为线性阵列的数据生成、添加到传输数据的CRC32、错误注入、使用计算的CRC32进行“分块”接收和错误检测。你可能只对“接收”部分感兴趣,但我认为有一个完整的例子可以让你更清楚地理解它
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
// ---------------------- buildCRC32table ------------------------------
static const uint32_t CRC32_POLY = 0xEDB88320;
static const uint32_t CRC32_XOR_MASK = 0xFFFFFFFF;
static uint32_t CRC32TABLE[256];
void buildCRC32table (void)
{
uint32_t crc32;
for (uint16_t byte = 0; byte < 256; byte++)
{
crc32 = byte;
// iterate thru all 8 bits
for (int i = 0; i < 8; i++)
{
uint8_t feedback = crc32 & 1;
crc32 = (crc32 >> 1);
if (feedback)
{
crc32 ^= CRC32_POLY;
}
}
CRC32TABLE[byte] = crc32;
}
}
// -------------------------- myCRC32 ----------------------------------
uint32_t myCRC32 (uint32_t previousCRC32, uint8_t *pData, int dataLen)
{
uint32_t newCRC32 = previousCRC32 ^ CRC32_XOR_MASK; // remove last XOR mask (or add first)
// add new data to CRC32
while (dataLen--)
{
uint32_t crc32Top24bits = newCRC32 >> 8;
uint8_t crc32Low8bits = newCRC32 & 0x000000FF;
uint8_t data = *pData++;
newCRC32 = crc32Top24bits ^ CRC32TABLE[crc32Low8bits ^ data];
}
newCRC32 ^= CRC32_XOR_MASK; // put XOR mask back
return newCRC32;
}
// ------------------------------ main ---------------------------------
int main()
{
// build CRC32 table
buildCRC32table();
uint32_t crc32;
// use a union so we can access the same data linearly (TX) or by chunks (RX)
union
{
uint8_t array[1024*1024];
uint8_t chunk[1024][1024];
} data;
// use time to seed randomizer so we have different data every run
srand((unsigned int)time(NULL));
/////////////////////////////////////////////////////////////////////////// Build data to be transmitted
////////////////////////////////////////////////////////////////////////////////////////////////////////
// populate array with random data sparing space for the CRC32 at the end
for (int i = 0; i < (sizeof(data.array) - sizeof(uint32_t)); i++)
{
data.array[i] = (uint8_t) (rand() & 0xFF);
}
// now compute array's CRC32
crc32 = myCRC32(0, data.array, sizeof(data.array) - sizeof(uint32_t));
printf ("array CRC32 = 0x%08X\n", crc32);
// to store the CRC32 into the array, we want to remove the XOR mask so we can compute the CRC32
// of all received data (including the CRC32 itself) and expect the same result all the time,
// regardless of the data, when no errors are present
crc32 ^= CRC32_XOR_MASK;
// load CRC32 at the very end of the array
data.array[sizeof(data.array) - 1] = (uint8_t)((crc32 >> 24) & 0xFF);
data.array[sizeof(data.array) - 2] = (uint8_t)((crc32 >> 16) & 0xFF);
data.array[sizeof(data.array) - 3] = (uint8_t)((crc32 >> 8) & 0xFF);
data.array[sizeof(data.array) - 4] = (uint8_t)((crc32 >> 0) & 0xFF);
/////////////////////////////////////////////// At this point, data is transmitted and errors may happen
////////////////////////////////////////////////////////////////////////////////////////////////////////
// to make things interesting, let's add one bit error with 1/8 probability
if ((rand() % 8) == 0)
{
uint32_t index = rand() % sizeof(data.array);
uint8_t errorBit = 1 << (rand() & 0x7);
// add error
data.array[index] ^= errorBit;
printf("Error injected on byte %u, bit mask = 0x%02X\n", index, errorBit);
}
else
{
printf("No error injected\n");
}
/////////////////////////////////////////////////////// Once received, the data is processed in 'chunks'
////////////////////////////////////////////////////////////////////////////////////////////////////////
// now we access the data and compute its CRC32 one chunk at a time
crc32 = 0; // initialize CRC32
for (int i = 0; i < 1024; i++)
{
crc32 = myCRC32(crc32, data.chunk[i], sizeof data.chunk[i]);
}
printf ("Final CRC32 = 0x%08X\n", crc32);
// because the CRC32 algorithm applies an XOR mask at the end, when we have no errors, the computed
// CRC32 will be the mask itself
if (crc32 == CRC32_XOR_MASK)
{
printf ("No errors detected!\n");
}
else
{
printf ("Errors detected!\n");
}
}
#包括
#包括
#包括
#包括
//-------------------------buildcrc32表------------------------------
静态常数uint32\u t CRC32\u POLY=0xEDB88320;
静态常数uint32\u t CRC32\u XOR\u掩码=0xFFFFFF;
静态uint32_t CRC32表[256];
void buildcrc32表格(void)
{
uint32_t crc32;
用于(uint16_t字节=0;字节<256;字节++)
{
crc32=字节;
//遍历所有8位
对于(int i=0;i<8;i++)
{
uint8\u t反馈=crc32&1;
crc32=(crc32>>1);
如果(反馈)
{
crc32^=crc32_POLY;
}
}
crc32表格[字节]=crc32;
}
}
//----------------------------myCRC32----------------------------------
uint32\u t myCRC32(uint32\u t先前的CRC32,uint8\u t*数据,内部数据)
{
uint32\u t newCRC32=previousCRC32^CRC32\u XOR\u MASK;//删除最后一个XOR MASK(或添加第一个)
//向CRC32添加新数据
while(dataLen--)
{
uint32\u t CRC32TOP24位=新的CRC32>>8;
uint8_t crc32Low8bits=newCRC32&0x000000FF;
uint8_t data=*pData++;
新CRC32=CRC32TOP24位^CRC32表[CRC32LOW8位^data];
}
newCRC32^=CRC32\u异或\u掩码;//将异或掩码放回
返回新的CRC32;
}
//-----------------------------------主要---------------------------------
int main()
{
//构建CRC32表
buildCRC32table();
uint32_t crc32;
//使用联合,以便我们可以线性(TX)或分块(RX)访问相同的数据
联盟
{
uint8_t数组[1024*1024];
uint8_t块[1024][1024];
}数据;
//使用时间为随机化器设定种子,以便每次运行时都有不同的数据
srand((无符号整数)时间(NULL));
///////////////////////////////////////////////////////////////////////////构建要传输的数据
////////////////////////////////////////////////////////////////////////////////////////////////////////
//在数组末尾为CRC32填充随机数据备用空间
对于(int i=0;i<(sizeof(data.array)-sizeof(uint32_t));i++)
{
数组[i]=(uint8_t)(rand()&0xFF);
}
//现在计算阵列的CRC32
crc32=myCRC32(0,data.array,sizeof(data.array)-sizeof(uint32_t));
printf(“数组CRC32=0x%08X\n”,CRC32);
//要将CRC32存储到阵列中,我们需要删除XOR掩码,以便计算CRC32
//所有接收到的数据(包括CRC32本身),并始终期望相同的结果,
//无论数据如何,当不存在错误时
crc32^=crc32异或掩模;
//负载CRC