Как рассчитать CRC из 1 байта, используя модуль CRC stm32l1

Я пытаюсь рассчитать CRC однобайтового ввода данных, используя блок вычисления CRC stm32l152.
Блок CRC принимает только 32-битные входные данные. Мне удалось рассчитать CRC для ввода 32-битных данных, но теперь я изо всех сил пытаюсь заставить его работать для ввода байтовых данных.

Мои тестовые входные данные 0x20, и я ожидаю, что на выходе 0xD62B0954
Параметр CRC: полином 0x04C11DB7, инициализация: 0xFFFFFFFF

Как я могу решить эту проблему, у меня заканчиваются идеи?

Пример кода для 32-битных данных:

CRC->DR = u32Input`  
u32Crc = CRC->DR;

Я также нашел этот фрагмент кода для побайтового вычисления CRC, но результат отличается.

static uint32_t crc32_step(uint32_t crc, uint8_t data)
{
    crc = ~crc ^ data;
    CRC->DR = (~CRC->DR) ^ __RBIT(~(crc << 24));
    return (crc >> 8) ^ ~__RBIT(CRC->DR);
}

Я получаю следующий вывод, используя приведенный выше код с предоставленным CRC 0xFFFFFFFF: 0xC491DF37

Я не очень понимаю, что делает функция crc32_step, но я даже не уверен, что это правильное направление. Буду очень признателен за любые подсказки или идеи.

Вам понадобится некоторый код для отката эффектов конечных 24 нулевых битов. Однако, вероятно, было бы проще вычислить CRC в программном обеспечении (или использовать эту программную процедуру для обновления CRC для конечных байтов блока, длина которого не делится на 4). Программные подпрограммы CRC часто используют справочную таблицу для ускорения, но могут быть реализованы без справочной таблицы путем индивидуальной обработки каждого бита данных.

Ian Abbott 11.12.2020 14:54

Блок CRC в stm32 использует CRC32? если да, то не слишком ли использовать его для однобайтовой проверки? Как упоминает @IanAbbott, я бы выбрал программную реализацию с таблицей или без нее.

armengedon 11.12.2020 14:57

@armengedon Я согласен, что это было бы немного излишеством, но это только часть истории. На самом деле я сначала использую модуль CRC для вычисления 32-битных фрагментов данных, и только для оставшихся байтов, которые не составляют двойное слово, мне нужно решение для побайтового вычисления. Программное решение кажется жизнеспособным решением. Желательно без таблицы поиска, в безопасную память. Падение производительности не должно быть слишком большим, потому что макс. 3 байта для расчета. КПР от.

david 11.12.2020 15:22

Для вычисления CRC порциями (например, ноль или более «аппаратных» порций, за которыми следует ноль или единица, замыкающая «программная» порция), некоторые реализации CRC могут потребовать, чтобы биты CRC были объединены XOR со значением «все единицы» (т. -flipped) между фрагментами и/или после последнего фрагмента.

Ian Abbott 11.12.2020 16:14

Пожалуйста, предоставьте CRC 32-битных данных и этих данных. Это могут быть любые данные. Устройство можно настроить для вычисления широкого диапазона возможных CRC.

Mark Adler 11.12.2020 19:49
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
693
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вычисляемый CRC выглядит как CRC-32/MPEG2. Вот простой код на C для его вычисления:

#include <stddef.h>
#include <stdint.h>

uint32_t crc32mpeg2(uint32_t crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0xffffffff;
    while (len--) {
        crc ^= (uint32_t)(*data++) << 24;
        for (unsigned k = 0; k < 8; k++)
            crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
    }
    return crc;
}

Подпрограмма вызывается с NULL для mem, чтобы получить начальное значение CRC. Таким образом, он будет использоваться следующим образом:

#include <stdio.h>

int main(void) {
    unsigned char data[1] = { 0x20 };
    uint32_t crc = crc32mpeg2(0, NULL, 0);
    crc = crc32mpeg2(crc, data, 1);
    printf("%08x\n", crc);
    return 0;
}

Результат:

d62b0954

Спасибо за ваш код, он отлично работает. Вы правы в предположении CRC-32/MPEG2. Я приму этот ответ, так как он решает мою проблему. Кажется, нет решения с использованием модуля CRC.

david 16.12.2020 08:57

Программное решение должно быть адекватным для одного-трех байтов. Если вы можете позволить себе 1 КБ памяти для таблицы, вы можете сделать ее немного быстрее, если это необходимо.

Mark Adler 16.12.2020 17:57

Самый эффективный способ вычисления CRC в программном обеспечении — использовать таблицу и выполнять вычисления по восемь битов за раз. Ниже приведена таблица, позволяющая их рассчитать:

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

static uint32_t crc32mpeg2_table[] = {
    0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
    0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
    0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
    0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
    0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
    0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
    0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
    0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
    0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
    0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
    0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
    0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
    0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
    0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
    0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
    0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
    0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
    0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
    0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
    0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
    0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
    0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
    0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
    0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
    0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
    0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
    0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
    0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
    0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
    0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
    0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
    0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4,
};

uint32_t crc32mpeg2(uint32_t state, uint8_t *buff, size_t buff_sz)
{
    while (buff_sz-- > 0) {
        int index = (state >> 24) ^ *buff++;
        state <<= 8;
        state ^= crc32mpeg2_table[index];
    }
    return state;
}

/* this main() function to demonstrate that the crc 
 * applied to a string with a single space character works */
int main()
{
    uint8_t buff[] = { 0x20 };
    uint32_t crc = crc32mpeg2(0xffffffff, buff, sizeof buff);
    printf("0x%08x\n", crc);
}

Как видите, результатом после применения его к вашему входному буферу является ожидаемое значение:

$ ./crcmpg3 
0xd62b0954
$ _

Чтобы создать таблицу, вы можете просто запустить алгоритм, предложенный Марком Адлером (@MarkAdler) в его ответе, для полного набора возможных входных байтов (от 0x00 до 0xff), как в:

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

/* this is the function provided by Mark in his response */
uint32_t crc32mpeg2(uint32_t crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0xffffffff;
    while (len--) {
        crc ^= (uint32_t)(*data++) << 24;
        for (unsigned k = 0; k < 8; k++)
            crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
    }
    return crc;
}

int main()
{
    int i;
    char *sep = "uint32_t crc32mpeg2_table[] = {\n\t";
    for (i = 0; i < 256; i++) {
        status = crc32mpeg2(i & 0xff, &ch, sizeof ch);
        printf("%s0x%08x", sep, status);
        sep = i % 8 == 7 ? ",\n\t" : ", ";
    }
    printf("\n};\n");
}

Это создаст таблицу выше. Когда у вас есть таблица, вам просто нужно использовать эту функцию (гораздо быстрее, так как вы работаете с одним полным байтом за итерацию), чтобы получить результат:

uint32_t crc32mpeg2(uint32_t state, uint8_t *buff, size_t buff_sz)
{
    while (buff_sz-- > 0) {
        int index = (state >> 24) ^ *buff++;
        state <<= 8;
        state ^= crc32mpeg2_table[index];
    }
    return state;
}

Правильное использование функции состоит в том, чтобы вызвать ее, передав старое состояние (которое представляет собой CRC до последнего обработанного байта), чтобы получить новое состояние (новый CRC после обработки новой группы байтов). Первое значение для состояния должно быть инициализирован 0xffffffff, поэтому для вычисления CRC "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." вы можете использовать этот main:

#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

int main()
{
    /* first piece */
    char *s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, ";
    uint32_t crc = crc32mpeg2(0xffffffff, s, strlen(s)); /* intialize with 0xffffffff */
    printf("CRC(\"%s", s);

    /* second piece */
    s = "sed do eiusmod tempor incididunt ut labore et dolore ";
    crc = crc32mpeg2(crc, s, strlen(s));
    printf("%s", s);

    /* third piece */
    s = "magna aliqua.";
    crc = crc32mpeg2(crc, s, strlen(s));
    printf("%s\") => ", s);

    /* print crc of the whole string */
    printf("0x%08x\n", crc);
}

который должен вывести:

$ crcmpg3.c
CRC("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") => 0x81e9201f
$ _

Существует даже способ предварительно вычислить таблицу (таблицы) препроцессором. Я сделал это для нескольких компиляторов C, но, к сожалению, исходный код закрыт.

the busybee 16.12.2020 22:29

Другие вопросы по теме