请教USB传输中CRC5的计算问题,谢谢
我始终不能使用 在线-ip33 中的计算工具,将图中的给出的传输包中的CRC5计算正确图中: ADDR=2,ENDP=0,那在在线-ip33 中, 选择CRC计算类型是 CRC-5/USB,
现在7位ADDR 和 4位ENDP,低位在前的位数据排列为0100 000 0000,
请问我填写CRC计算的数据是 0x40 0x00 吗?得到CRC5的计算结果是 0x18,
和图片中的 crc5=0x15 不同. 请问该如何计算呢? 谢谢
而数据传输包中的CRC16, 直接按照实例数据,使用 在线-ip33 的CRC-16/USB计算工具, 计算出来的结果和实例的CRC16数据是一致的! CRC5存在数据的补位问题,不知道如何处理?
搜刮了下github,找到两个比较权威的仓库有crc5函数,其中CRC5_MSBfirst计算结果和图中一致可以参考下
opentitan/hw/dv/dpi/usbdpi/usb_crc.c at master · lowRISC/opentitan
wireshark/wsutil/crc5.c at master · wireshark/wireshark
示例代码:
#include <stdint.h>
#include <stdio.h>
#define INT_SIZE 32// Assumes 32-bit integer size
uint32_t CRC5_MSBfirst(uint32_t dwInput, int iBitcnt) {
const uint32_t poly5 = (0x05 << (INT_SIZE - 5));
uint32_t crc5 = (0x1f << (INT_SIZE - 5));
uint32_t udata = (dwInput << (INT_SIZE - iBitcnt));
if ((iBitcnt < 1) || (iBitcnt > INT_SIZE)) {// Validate iBitcnt
return 0xffffffff;
}
while (iBitcnt--) {
if ((udata ^ crc5) & (0x1 << (INT_SIZE - 1))) {// bit4 != bit4?
crc5 <<= 1;
crc5 ^= poly5;
} else {
crc5 <<= 1;
}
udata <<= 1;
}
// Shift back into position
crc5 >>= (INT_SIZE - 5);
// Invert contents to generate crc field
crc5 ^= 0x1f;
return crc5;
}// CRC5()
/* This is the little endian version, so you can feed an 11 bit data
* value and get back 5 bits to OR in to the top to construct 16 bits
*
* Adapted by mdhayter
*/
uint32_t CRC5(uint32_t dwInput, int iBitcnt) {
const uint32_t poly5 = 0x14;
uint32_t crc5 = 0x1f;
uint32_t udata = dwInput;
if ((iBitcnt < 1) || (iBitcnt > INT_SIZE)) {// Validate iBitcnt
return 0xffffffff;
}
while (iBitcnt--) {
if ((udata ^ crc5) & 0x01) {
crc5 >>= 1;
crc5 ^= poly5;
} else {
crc5 >>= 1;
}
udata >>= 1;
}
// Invert contents to generate crc field
crc5 ^= 0x1f;
return crc5;
}// CRC5()
static uint8_t crc5_usb_bits(uint32_t v, int vl, uint8_t ival)
{
/* This function is based on code posted by John Sullivan to Wireshark-dev
* mailing list on Jul 21, 2019.
*
* "One of the properties of LFSRs is that a 1 bit in the input toggles a
*completely predictable set of register bits *at any point in the
*future*. This isn't often useful for most CRC caculations on variable
*sized input, as the cost of working out which those bits are vastly
*outweighs most other methods."
*
* In USB 2.0, the CRC5 is calculated on either 11 or 19 bits inputs,
* and thus this approach is viable.
*/
uint8_t rv = ival;
static const uint8_t bvals = {
0x1e, 0x15, 0x03, 0x06, 0x0c, 0x18, 0x19, 0x1b,
0x1f, 0x17, 0x07, 0x0e, 0x1c, 0x11, 0x0b, 0x16,
0x05, 0x0a, 0x14
};
for (int i = 0; i < vl; i++) {
if (v & (1 << i)) {
rv ^= bvals;
}
}
return rv;
}
uint8_t crc5_usb_11bit_input(uint16_t input)
{
return crc5_usb_bits(input, 11, 0x02);
}
int main() {
uint8_t addr = 0x20;
uint8_t endp = 0;
uint32_t combined_data = ((uint32_t)addr << 4) | (endp & 0x0F); // 组合 7 位 ADDR 和 4 位 ENDP
printf("combined_data 结果: 0x%04X\n", combined_data);
uint8_t result = CRC5_MSBfirst(combined_data,11);
printf("MSB CRC5 结果: 0x%02X\n", result);
printf("MSB CRC5 ~结果: 0x%02X\n", (~result) & 0xFF);
result = CRC5(combined_data,11);
printf("LSB CRC5 结果: 0x%02X\n", result);
printf("LSB CRC5 ~结果: 0x%02X\n", (~result) & 0xFF);
auto x = crc5_usb_11bit_input(combined_data);
printf("crc5_usb_11bit_input LSB 结果: 0x%02X\n", x);
return 0;
}
明天我来试试程序计算,非常感谢您的指点! 把程序移植到 擎天柱 核心板上,KC251 编译测试了一下, 使用USB已知数据计算了 CRC5, 结果符合样本数据(见 www.usbzh.com 中usb报文)
具体结果描述参见 main.c 中说明;
下面附上整个工程,再次感谢 ercircle 的指点! 机灵小老鼠 发表于 2025-3-30 18:55
把程序移植到 擎天柱 核心板上,KC251 编译测试了一下, 使用USB已知数据计算了 CRC5, 结果符合样本数据( ...
{:4_250:}真棒,指点谈不上,一起学习
页:
[1]