用于在引导加载程序应用程序中计算 crc 的软件逻辑

Software logic for calculating crc in a bootloader application

我找到了一个文件来通过一些接口检查传入应用程序的crc,程序如下:

#define CRC16POLY   0x1021  
#define PKTLEN_128  128

typedef struct Crc16Data {
    uint16_t currentCrc;    //!< Current CRC value.
} crc16_data_t;

void crc16_init(crc16_data_t * crc16Config)
{
    // initialize running crc and byte count
    crc16Config->currentCrc = 0;
}

void crc16_update(crc16_data_t * crc16Config, const uint8_t * src, uint32_t lengthInBytes)
{
    uint32_t crc = crc16Config->currentCrc;

    uint32_t j;
    for (j=0; j < lengthInBytes; ++j)
    {
        uint32_t i;
        uint32_t byte = src[j];
        crc ^= byte << 8;
        for (i = 0; i < 8; ++i)
        {
            uint32_t temp = crc << 1;
            if (crc & 0x8000)
            {
                temp ^= 0x1021;
            }
            crc = temp;
        }
    }

    crc16Config->currentCrc = crc;
}

void crc16_finalize(crc16_data_t * crc16Config, uint16_t * hash)
{
    *hash = crc16Config->currentCrc;
}

我理解这是简单的 crc 软件逻辑,不涉及任何硬件生成的 crc 机制来计算传入应用程序的 crc,它只是计算应用程序的字节并将它们相加并正确放置?谁能解释 void crc16_update(crc16_data_t * crc16Config, const uint8_t * src, uint32_t lengthInBytes) 函数内部发生了什么? 并且在其中一个文件中 crc16update(....) 函数被调用如下:

crc16_update(&crcInfo,buffer,PKTLEN_128);

在另一个函数 crcInfo 中,缓冲区信息来自

static void read_bytes(uint8_t * buffer, uint32_t byteCount)
{
    uint32_t currentBytesRead = 0;

    while(currentBytesRead != byteCount)
    {
        if (readOffset != writeOffset)
        {
            buffer[currentBytesRead++] = callback_buffer[readOffset++];
            readOffset &= XMODEM_BUFLEN - 1;
        }
    }
}

static int read_packet(uint8_t *buffer, uint8_t idx)
{
    uint8_t  seq[2],crc1,crc2;
    uint16_t  crc16, verify16;
    crc16_data_t crcInfo;

    read_bytes(seq,2);

    read_bytes(buffer,PKTLEN_128);
    crc16_init(&crcInfo);
    crc16_update(&crcInfo,buffer,PKTLEN_128);
    crc16_finalize(&crcInfo,&verify16);

    read_bytes(&crc1,1);
    read_bytes(&crc2,1);
    crc16  = ((uint16_t)crc1 << 8)|crc2;

    if ((crc16 != verify16) || (seq[0] != idx) || (seq[1] != (uint8_t) ((~(uint32_t)idx)&0xff)))
        return(-1);

    return(0);
}

函数 void crc16_update(crc16_data_t * crc16Config, const uint8_t * src, uint32_t lengthInBytes) 内部发生了什么?提前致谢。

此代码:

    crc ^= byte << 8;
    for (i = 0; i < 8; ++i)
    {
        uint32_t temp = crc << 1;
        if (crc & 0x8000)
        {
            temp ^= 0x1021;
        }
        crc = temp;
    }

用字节更新 CRC。它模拟运行一个线性反馈移位寄存器,其状态为crc的值。这可以写得更紧凑,可能更容易看到发生了什么:

    crc ^= byte << 8;
    for (int i = 0; i < 8; i++)
        crc = crc & 0x8000 ? (crc << 1) ^ 0x1021 : crc << 1;

crc的高位决定是否与寄存器异或多项式0x1021,寄存器上移一位后,高位掉尾.

要了解有关如何实现此实现的更多信息,您应该阅读 Ross William's CRC tutorial