簡體   English   中英

如何使用 stm32l1 CRC 單元計算 1 字節的 CRC

[英]How to calulate CRC of 1 byte using stm32l1 CRC unit

我正在嘗試使用 stm32l152 的 CRC 計算單元計算一字節數據輸入的 CRC。
CRC 單元僅接受 32 位輸入。 我能夠讓它計算 32 位數據輸入的 CRC,但現在我正在努力讓它為字節數據輸入工作。

我的測試輸入數據是0x20 ,我希望為 output 0xD62B0954
CRC參數: 0x04C11DB7 ,init-val: 0xFFFFFFFF

我該如何解決這個問題,我的想法不多了?

32位數據的示例代碼:

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

我還找到了這個代碼片段,用於按字節計算 CRC,但 output 不同。

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);
}

我使用上面的代碼得到以下 output 並提供0xFFFFFFFF的 crc: 0xC491DF37

我不太明白crc32_step function 是做什么的,但我什至不確定這是否是 go 的正確方向。 我將不勝感激任何提示或想法。

正在計算的 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;
}

output 是:

d62b0954

在軟件中計算 crcs 的最有效方法是使用表格並一次計算 8 位。 下面是一個表格,可讓您計算這些:

#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
$ _

要生成表格,您可以只運行 Mark Adler (@MarkAdler) 在他的響應中提出的算法,以獲取完整的可能輸入字節集(從0x000xff ),如下所示:

#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");
}

它將生成上表。 一旦你有了表格,你只需要使用這個 function (更快,因為你每次迭代操作一個完整字節)來獲得結果:

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;
}

The correct use of the function is to call it by passing the old state (which is the CRC upto the last byte processed) to get the new state (the new CRC after processing a new bunch of bytes) The first value for the state must初始化為0xffffffff ,因此要計算"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." 你可以使用這個主要的:

#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);
}

這應該是 output:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM