CRC: найти ошибочный байт

Предположим, что многобайтовый блок данных дважды обрабатывается некоторой CRC, один раз без изменений и один раз с одним ошибочным байтом. Можно ли найти ошибочный байт исключительно на основе двух кодов? Обратите внимание, что это не означает, что точная природа ошибки должна быть идентифицирована только ее местоположением, а также ошибка байта не ограничена одним изменением бита, которое может быть исправлено любой CRC.


person qantik    schedule 30.04.2019    source источник
comment
Недостаточно информации. Количество битов в CRC, циклический период полинома CRC и количество байтов в блоке данных не упоминаются. Я предполагаю, что исключительно на основе двух кодов означает исключительно на основе двух CRC, одного для хороших данных и одного для плохих данных. Если ответ на вопрос положительный, должен ли ответ включать процесс определения местоположения неисправного байта?   -  person rcgldr    schedule 30.04.2019
comment
Имеется в виду в общем смысле. Существуют ли конструкции CRC любого размера, обладающие этим свойством? Нет необходимости придумывать процесс. Для некоторых приложений может быть интересно просто найти ошибки, не имея возможности их исправить.   -  person qantik    schedule 30.04.2019
comment
Вы можете определить, находится ли ошибка в одном бите в части полезной нагрузки или в части контрольной суммы (FCS), вычислив контрольную сумму для полезной нагрузки и сравнив ее с полученной контрольной суммой. Если они одинаковые, ошибка в части полезной нагрузки, в противном случае, если они разные, ошибка в части контрольной суммы.   -  person Lundin    schedule 30.04.2019
comment
Если у вас есть правильный CRC, вы по определению знаете, какими были исходные данные, поэтому вы можете просто сравнить их. Но если вы априори знаете, какими будут данные, в первую очередь нет необходимости их передавать.   -  person Clifford    schedule 30.04.2019


Ответы (1)


Дано: CRC для хороших данных и CRC для данных с одним плохим байтом. Предполагается, что два заданных CRC исправны, поэтому в самих CRC нет ошибок. Xor правильных данных CRC с неверными данными CRC. Рассматривайте это как xoring хороших данных + хороший CRC с неверными данными + плохой CRC, результатом являются данные, состоящие из нулей, за исключением одного плохого байта и соответствующего CRC. Xor также отменяет любое начальное значение CRC или последующее дополнение значения CRC.

Чтобы иметь возможность определить местоположение плохого байта, CRC должен быть уникальным для каждой возможной комбинации местоположения байта и значения байта.

Я обнаружил, что полином CRC32C 0x1edc6f41 создает уникальные CRC для данных от 1 до 190235 байт. Он дает сбой при 190236 байтах данных, так как буфер со всеми нулями, за исключением bfr[0] = 0xfb или bfr[190235] = 0x32, дает один и тот же (неуникальный) CRC = 0x364b1c30 .

Пример кода для определения местоположения с учетом правильной контрольной суммы и плохой контрольной суммы (один неверный байт):

static uint32_t crcrtbl[256];

void genrtbl(void)
{
uint32_t crc;
uint32_t b;
uint32_t c;
uint32_t i;
    for(c = 0; c < 0x100; c++){
        crc = c;
        for(i = 0; i < 8; i++){
            b = crc&1;
            crc >>= 1;
            crc ^= (0 - b) & (0x11edc6f41>>1);
        }
        crcrtbl[c] = crc;
    }
}

size_t crc32r(uint32_t crc, size_t size)
{
    while(size--){
        crc = (crc >> 8) ^ crcrtbl[crc & 0xff];
        if(0 == (crc & 0xffffff))
            break;
    }
    return(size);
}
// ...
genrtbl();  // generate table
// given good_crc and bad_crc, return location
location = crc32r(good_crc ^ bad_crc, size);

код для генерации crc

uint32_t crctbl[256];

void gentbl(void)
{
uint32_t crc;
uint32_t b;
uint32_t c;
uint32_t i;
    for(c = 0; c < 0x100; c++){
        crc = c<<24;
        for(i = 0; i < 8; i++){
            b = crc>>31;
            crc <<= 1;
            crc ^= (0 - b) & 0x1edc6f41;   // 32 bit crc
        }
        crctbl[c] = crc;
    }
}

uint32_t crc32(uint32_t crc32, uint8_t * bfr, size_t size)
{
uint32_t crc = crc32;
    while(size--)
        crc = (crc << 8) ^ crctbl[(crc >> 24)^*bfr++];
    return(crc);
}
person rcgldr    schedule 30.04.2019
comment
Работает как шарм. Я предполагаю, что обнаружение более одного неисправного байта является нетривиальным расширением? - person qantik; 01.05.2019
comment
@qantik - одиночную пакетную ошибку можно обнаружить путем обратного цикла CRC, пока вы не получите много нулевых битов, что и делает пример кода. Это не будет работать для нескольких плохих байтов или нескольких плохих пакетов или даже для нескольких плохих битов. Для нескольких плохих битов это процесс пробной ошибки, начните со всех нулей и попробуйте 2 плохих бита во всех возможных комбинациях местоположений, чтобы увидеть, соответствует ли он CRC, затем 3 битам, затем 4 битам, ... . - person rcgldr; 01.05.2019
comment
@qantik - для обработки нескольких местоположений обычно используются коды исправления ошибок, такие как код BCH (для битов) или коды RS (для байтов или другого фиксированного числа битовых элементов). - person rcgldr; 01.05.2019
comment
@qantik- я забыл упомянуть, что я провел грубую проверку всех возможных комбинаций 190235 x 255, чтобы убедиться, что код, показанный выше, работает. - person rcgldr; 01.05.2019