假设我在Cortex M4处理器上(使用GCC 7)有很多24B块,并且我想计算一个快速的16位校验和,那么比CRC16 CCITT更快的替代方法是什么?现在,CRC-16(使用256元素的查找表)比创建缓冲区要花费更多的时间(我在这里显然是在谈论微秒,但是这些块应该以尽可能低的延迟生成,并且通过剖析可以到达那里)
我尝试展开CRC,但是它仍然需要遍历所有24个字节(2个移位,2个xor,1和1个表查找,重复24x):
uint16_t crc16_24B_unrolled(uint16_t seed, const char *data)
{
uint16_t crc = seed;
crc = (u16)((crc << 8) ^ crc16tab[((crc >> 8) ^ data[0]) & 0x00FF]);
crc = (u16)((crc << 8) ^ crc16tab[((crc >> 8) ^ data[1]) & 0x00FF]);
crc = (u16)((crc << 8) ^ crc16tab[((crc >> 8) ^ data[2]) & 0x00FF]);
... (24 times)
return crc;
}
由于数据是对齐的,并且是32位处理器,所以我认为也许我可以创建一个更简单的校验和,类似以下内容:
uint16_t data_get_chksum(const char *data)
{
// data is guaranteed to be aligned to 8B
// (although Cortex M4 supports unaligned int access)
const uint32_t * ptr32 = (const uint32_t *)data;
// just add three 32-bit integers
uint32_t chk = 0xa7f72f28; // <-- made up for the purpose of this question
chk += *ptr32++;
chk += *ptr32++;
chk += *ptr32;
// xor high and low words
return (uint16_t)((chk >> 16) ^ (chk));
}
加法和XORing显然被认为是进行校验和/散列的一种较差的方法,但是在这种情况下,如果我能获得较大的加速,我愿意得到一些误报(校验和在读取时被错误地报告为有效)。这些校验和不需要像CCITT那样是标准的,它们用于检查这些块在重启后是否有效,并将它们放置在标记为非易失性的区域中。