Программная логика для расчета crc в приложении загрузчика - PullRequest
0 голосов
/ 25 июня 2018

Я нашел файл для проверки 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)? Заранее спасибо.

1 Ответ

0 голосов
/ 25 июня 2018

Этот код:

    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 с регистром, после того как регистр сдвинут на один бит вверх, причем старший бит сбрасывается с конца.

Чтобы узнать больше о том, как реализована эта реализация, вы должны прочитать Учебное пособие Росса Уильяма по CRC .

...