USB2.0令牌、事务及传输抓包分析
+ -

CRC5和CRC16循环冗余校验

2026-04-21 本文链接为:http://www.usbzh.com/article/detail-1620.html ,欢迎转载,转载请附上本文链接。

USB2.0 CRC5和CRC16的计算原理详见:https://www.usb.org/sites/default/files/crcdes.pdf
文档中使用的是LSB->MSB的方式,比如

setup addr 15 endp e
crc5 10101000111
10111

中addr 0x15 endp 0x0e的二进制为[地址取低7位,端点地址取低4位]

001 0101    1110

转成LSB->MSB则为:

1010100 0111

最终合并位数为:

10101000111

CRC5循环冗余校验

包含有CRC5冗余校验的令牌有IN ,SETUP,OUTSOFPINGSPLIT
CRC5冗余校验
根据公式:CRC5的polynomial值为0b100101

SETUP令牌包使用5位的CRC校验,用于ADDR字段和ENDP字段之间的数据进行循环冗余校验.
162001698875

#include <stdio.h>
#include <stdint.h>

// Bit-reverse a 16-bit value (for 11-bit data)
uint16_t bit_reverse16(uint16_t x, int bits) {
    uint16_t result = 0;
    for (int i = 0; i < bits; i++) {
        if (x & (1 << i)) {
            result |= (1 << (bits - 1 - i));
        }
    }
    return result;
}

// USB 2.0 CRC5: G(x) = x^5 + x^2 + 1  (binary 00101)
// Initial value: 0x1F (11111)
// Final XOR: 0x1F (bitwise NOT)
// Input: addr (7 bits), endpoint (4 bits)
// USB sends: ADDR[0..6] (LSB first), then ENDP[0..3] (LSB first)

uint8_t crc5_usb(uint8_t addr, uint8_t endpoint) {
    // Combine address (7 bits) and endpoint (4 bits) into 11-bit data
    // Bit positions: bits 0-6 = addr, bits 7-10 = endpoint
    // This matches USB transmission order: ADDR LSB first, then ENDP LSB first
    uint16_t data = (addr & 0x7F) | ((endpoint & 0x0F) << 7);

    // Bit-reverse the 11-bit data to convert LSB-first to MSB-first order
    uint16_t reversed_data = bit_reverse16(data, 11);

    uint8_t crc = 0x1F;  // initial value all 1s

    // Process 11 bits from MSB to LSB (after reversal)
    for (int bit = 10; bit >= 0; bit--) {
        // Get current input bit (MSB first from reversed data)
        uint8_t in_bit = (reversed_data >> bit) & 1;

        // XOR with MSB of CRC register
        uint8_t fb = (crc >> 4) & 1;  // feedback bit

        // Shift CRC left
        crc = (crc << 1) & 0x1F;

        // If feedback XOR input bit is 1, XOR with polynomial
        if (fb ^ in_bit) {
            crc ^= 0x05;  // polynomial 0b00101 (x^2 + 1)
        }
    }

    // Final XOR: invert all bits
    crc ^= 0x1F;

    return crc;
}

int main(int argc, char* argv[]) {

    int addr = 2;
    int endpoint = 0;

    if (addr < 0 || addr > 127 || endpoint < 0 || endpoint > 15) {
        printf("Error: addr must be 0-127, endpoint 0-15\n");
        return 1;
    }

    uint8_t crc = crc5_usb((uint8_t)addr, (uint8_t)endpoint);

    uint16_t data = (addr & 0x7F) | ((endpoint & 0x0F) << 7);
    uint16_t reversed_data = bit_reverse16(data, 11);

    printf("Input: addr=%d (0x%02X), endpoint=%d (0x%01X)\n", addr, addr, endpoint, endpoint);

    printf("\nUSB wire transmission order (LSB-first):\n");
    printf("  ADDR bits (bit0->bit6): ");
    for (int i = 0; i < 7; i++) {
        printf("%d", (addr >> i) & 1);
    }
    printf("\n  ENDP bits (bit0->bit3): ");
    for (int i = 0; i < 4; i++) {
        printf("%d", (endpoint >> i) & 1);
    }
    printf("\n  Combined on wire (11 bits): ");
    for (int i = 0; i < 11; i++) {
        printf("%d", (data >> i) & 1);
        if (i == 6) printf(" ");  // separator between ADDR and ENDP
    }

    printf("\n\nAfter bit-reversal (MSB-first for CRC calculation):\n");
    printf("  Reversed data (11 bits): ");
    for (int i = 10; i >= 0; i--) {
        printf("%d", (reversed_data >> i) & 1);
        if (i == 4) printf(" ");  // separator after first 7 bits
    }

    printf("\n\nCRC5 result (5 bits):\n");
    printf("  As sent on wire (LSB-first): ");
    for (int i = 0; i < 5; i++) {
        printf("%d", (crc >> i) & 1);
    }
    printf("\n  MSB-first representation:    ");
    for (int i = 4; i >= 0; i--) {
        printf("%d", (crc >> i) & 1);
    }
    printf(" (0x%02X)\n", crc);

    return 0;
}

输出为:

Input: addr=2 (0x02), endpoint=0 (0x0)

USB wire transmission order (LSB-first):
  ADDR bits (bit0->bit6): 0100000
  ENDP bits (bit0->bit3): 0000
  Combined on wire (11 bits): 0100000 0000

After bit-reversal (MSB-first for CRC calculation):
  Reversed data (11 bits): 0100000 0000

CRC5 result (5 bits):
  As sent on wire (LSB-first): 10101
  MSB-first representation:    10101 (0x15)

191153896967

以上数字使用的是MSB->LSB的方式

CRC16循环冗余校验

CRC16冗余校验使用于数据包.如DATA0,DATA1,DATA2和MDATA,用于数据包内数据的冗余校验。
162112276592

CRC16冗余校验

CRC(循环冗余校验)在线计算:http://www.ip33.com/crc.html

本文链接为:http://www.usbzh.com/article/detail-1620.html ,欢迎转载,转载请附上本文链接。

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936     USB技术交流3:1031974172

0 篇笔记 写笔记

USB2.0 包位域成员字段-PID、SOP、包地址、包端点、帧号、CRC5CRC16
包标识PIDUSB协议定义的包格式PID由8位组成,低4位是类型字段,高4位为低四位的补码。特殊用途包包括了一些用于特定场合的信牌包和握手包。PID含义说明0001令牌OUT主机发送数据到USB设备1001令牌IN主机接收从USB设备发出的数据0101......
CRC5CRC16循环冗余校验
USB2.0 CRC5CRC16的计算原理详见:https://www.usb.org/sites/default/files/crcdes.pdf文档中使用的是LSB->MSB的方式,比如setup addr 15 endp ecrc5 1010100011110111中addr ......
关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • CDC
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!