本帖最后由 FSL_TICS_A 于 2014-3-4 17:08 编辑
采用Kinetis硬件计算crc,如果是使用大端计算都可得到正确结果。但是使用小端时,计算结果都是错误的。
/*
* There are multiple 16-bit CRC polynomials in common use, but this is
* *the* standard CRC-32 polynomial, first popularized by Ethernet.
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
*/
#define CRCPOLY_LE 0xedb88320
#define CRCPOLY_BE 0x04c11db7
/**
* crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
* @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for
* other uses, or the previous crc32 value if computing incrementally.
* @p: pointer to buffer over which CRC is run
* @len: length of buffer @p
* In fact, the table-based code will work in this case, but it can be
* simplified by inlining the table in ?: form.
*/
u32 crc32_le(u32 crc, unsigned char const *p, size_t len)
{
int i;
while (len--) {
crc ^= *p++;
for (i = 0; i < 8; i++)
crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
}
return crc;
}
/**
* crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
* @crc: seed value for computation. ~0 for Ethernet, sometimes 0 for
* other uses, or the previous crc32 value if computing incrementally.
* @p: pointer to buffer over which CRC is run
* @len: length of buffer @p
* In fact, the table-based code will work in this case, but it can be
* simplified by inlining the table in ?: form.
*/
u32 crc32_be(u32 crc, unsigned char const *p, size_t len)
{
int i;
while (len--) {
crc ^= *p++ << 24;
for (i = 0; i < 8; i++)
crc =
(crc << 1) ^ ((crc & 0x80000000) ? CRCPOLY_BE :
0);
}
return crc;
}
// Definitions
typedef struct _CRC_CTRL
{
uint8_t transpose_w; //TOT
uint8_t transpose_r; //TOTR
uint8_t fxor; //bit 26 FXOR
uint8_t width;
}CRC_CTRL_DEF;
//for Transpose write(read)
#define CRC_ORDER_NORMAL 0x00
#define CRC_REVERSE_BITS 0x01
#define CRC_REVERSE_BOTH 0x02
#define CRC_REVERSE_BYTE 0x03
//width
#define CRC_BITS_16 0x00
#define CRC_BITS_32 0x01
//FXOR
#define CRC_NO_FXOR 0x00
#define CRC_FXOR 0x01
void hw_crc_config(uint32_t poly, CRC_CTRL_DEF ctrl)
{
CRC_CTRL = ((ctrl.width << CRC_CTRL_TCRC_SHIFT) & CRC_CTRL_TCRC_MASK)
| ((ctrl.fxor << CRC_CTRL_FXOR_SHIFT) & CRC_CTRL_FXOR_MASK)
| ((ctrl.transpose_r << CRC_CTRL_TOTR_SHIFT) & CRC_CTRL_TOTR_MASK)
| ((ctrl.transpose_w << CRC_CTRL_TOT_SHIFT ) & CRC_CTRL_TOT_MASK );
CRC_GPOLY = poly;
}
uint32_t hw_crc_cal_32(uint32_t seed, uint8_t const *msg, uint32_t length)
{
CRC_CTRL |= CRC_CTRL_WAS_MASK;
CRC_CRC = seed;
CRC_CTRL &= ~CRC_CTRL_WAS_MASK;
while (length--) {
CRC_CRCLL = *msg++;
}
return CRC_CRC;
}
//测试程序
const uint8_t dbg_crc_msg[] = "abcdef0123456789ghjkloqwertyuizx";
void dbg_crc32_le_all(void)
{
CRC_CTRL_DEF ctrl_reg;
uint32_t length;
uint16_t hw_crc;
uint16_t sw_crc;
uint8_t buf[64];
uint32_t i;
uint32_t *p=(uint32_t*)dbg_crc_msg;
ctrl_reg.transpose_w = CRC_REVERSE_BOTH;
ctrl_reg.transpose_r = CRC_ORDER_NORMAL;
ctrl_reg.fxor = CRC_NO_FXOR;
ctrl_reg.width = CRC_BITS_32;
for (ctrl_reg.transpose_w = 0; ctrl_reg.transpose_w < 0x04; ctrl_reg.transpose_w++)
{
for (ctrl_reg.transpose_r = 0; ctrl_reg.transpose_r < 0x04; ctrl_reg.transpose_r++)
{
for (ctrl_reg.fxor = 0; ctrl_reg.fxor <2; ctrl_reg.fxor++)
{
TRACE("\n\n-|crc:0x00 tot:%02x totr:%02X fxor:%X",ctrl_reg.transpose_w,ctrl_reg.transpose_r,
ctrl_reg.fxor);
hw_crc_config(CRCPOLY_LE,ctrl_reg);
for (length = 0; length < 32; length+=4)
{
hw_crc = hw_crc_cal_32(0,dbg_crc_msg,length);
sw_crc = crc32_le(0,dbg_crc_msg,length);
TRACE("\n-|hw:%04X sw:%04X",hw_crc,sw_crc);
}
TRACE("\n\n-|crc:~0 tot:%02x totr:%02X fxor:%X",ctrl_reg.transpose_w,ctrl_reg.transpose_r,
ctrl_reg.fxor);
hw_crc_config(CRCPOLY_LE,ctrl_reg);
for (length = 0; length < 32; length+=4)
{
hw_crc = hw_crc_cal_32(~0,dbg_crc_msg,length);
sw_crc = crc32_le(0,dbg_crc_msg,length);
TRACE("\n-|hw:%04X sw:%04X",hw_crc,sw_crc);
}
}
}
}
}
小端试过所有的TOT和TOTR,初值,和读取反模式组合都测试过,但是都与软件算的不一样。大端的都成功。 有人可以指点一下吗。谢谢。
|