0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Micrium全家桶之uC-CRC: 0x02 CRC

嵌入式USB開發(fā) ? 來源:嵌入式USB開發(fā) ? 作者:嵌入式USB開發(fā) ? 2023-06-08 11:00 ? 次閱讀

本文轉(zhuǎn)自公眾號,歡迎關(guān)注

Micrium全家桶之uC-CRC: 0x02 CRC (qq.com)

前言

前一篇我們講了Micrium全家桶之uC-CRC: 0x01 ECC:https://mp.weixin.qq.com/s/FKVvzwL7wzxLJCkx3gOdJQ。ECC常用于NAND進行誤碼校正。而CRC一般用于錯誤檢測,比如鏡像,協(xié)議的正確完備性檢測。

這一篇我們來講講uC-CRC組件的CRC部分,老規(guī)矩先代碼用起來,然后再講講原理,理論結(jié)合實踐。

使用

可以從https://github.com/qinyunti/uC-CRC.git下載代碼,該版本在原版本基礎(chǔ)上進行了修改,刪除了其他依賴,可以單獨使用,方便移植,也可以參考https://mp.weixin.qq.com/s/FKVvzwL7wzxLJCkx3gOdJQ。

有了上一篇基礎(chǔ)我們不再詳細介紹如何集成該代碼,直接進入測試環(huán)節(jié)。

文件

如果只使用CRC的話只需要crc_cfg.h和edc_crc.c,edc_crc.h即可。

配置

其中cec_cfg.h的宏EDC_CRC_CFG_OPTIMIZE_ASM_EN配置是否使用匯編代碼實現(xiàn),默認為DEF_DISABLED.

以下宏配置是否使能對應(yīng)的算法和反轉(zhuǎn)查找表

其中前面4個宏使能了4種算法,后面4個宏定義是否支持位反轉(zhuǎn)模式,如果是則會定義對應(yīng)的CRC查找表,比如EDC_CRC_CFG_CRC32_REF_EN使能則使用CRC_TblCRC32_ref,EDC_CRC_CFG_CRC32_EN使能則使用CRC_TblCRC32。

所謂的位反轉(zhuǎn)就是bit7和bit0交換,bit6和bit1交換...,通過查表法空間換時間加快速度。有些場景需要位翻轉(zhuǎn),所以有這個實現(xiàn)。

#define EDC_CRC_CFG_CRC16_1021_EN               DEF_ENABLED    /* See Note #3.                                         */


#define EDC_CRC_CFG_CRC16_8005_EN               DEF_ENABLED


#define EDC_CRC_CFG_CRC16_8048_EN               DEF_ENABLED


#define EDC_CRC_CFG_CRC32_EN                    DEF_ENABLED


#define EDC_CRC_CFG_CRC16_1021_REF_EN           DEF_ENABLED


#define EDC_CRC_CFG_CRC16_8005_REF_EN           DEF_ENABLED


#define EDC_CRC_CFG_CRC16_8048_REF_EN           DEF_ENABLED


#define EDC_CRC_CFG_CRC32_REF_EN                DEF_ENABLED

接口

CRC提供了以下接口

CRC_Open_16Bit


CRC_WrBlock_16Bit


CRC_WrOctet_16Bit


CRC_Close_16Bit


CRC_Open_32Bit


CRC_WrBlock_32Bit


CRC_WrOctet_32Bit


CRC_Close_32Bit

提供了兩組接口16位的和32位的

流式操作,結(jié)果存在結(jié)構(gòu)體參數(shù)種 只支持查表法

CRC_Open_16Bit()->

CRC_WrBlock_16Bit()-> 一次寫多個字節(jié)

CRC_WrOctet_16Bit()-> 一次寫一個字節(jié)

CRC_Close_16Bit()->

32位的類似

CRC_Open_32Bit->

CRC_WrBlock_32Bit->

CRC_WrOctet_32Bit->

CRC_Close_32Bit->

這里提供這幾個位反轉(zhuǎn)接口,最后結(jié)果再調(diào)用這些接口進行位反轉(zhuǎn)。

CRC_Reflect_08Bit 查表法實現(xiàn)8位數(shù)據(jù)位反轉(zhuǎn) 查表是CRC_ReflectTbl

CRC_Reflect_16Bit 查表法實現(xiàn)16位數(shù)據(jù)位反轉(zhuǎn)

CRC_Reflect_32Bit 查表法實現(xiàn)32位數(shù)據(jù)位反轉(zhuǎn)

還提供兩個接口直接計算,立即返回計算值,支持查表和不查表

CRC_ChkSumCalc_16Bit

CRC_ChkSumCalc_32Bit

所以以上有幾種配置:使用查表還是不使用查表,使用位反轉(zhuǎn)還是不使用

p_model->Reflect == DEF_YES 則使用位反轉(zhuǎn)

p_model->TblPtr == (const CPU_INT16U *)0則不使用查表

測試

以CRC_ChkSumCalc_16Bit為例

CPU_INT16U   crc = CRC_ChkSumCalc_16Bit((CRC_MODEL_16*)&CRC_ModelCRC16_8005,(void*)p_datap,strlen(p_datap),&err);

第一個參數(shù)傳入默認配置好的

const CRC_MODEL_16  CRC_ModelCRC16_8005 = {


0x8005u,


0x0000u,


DEF_NO,


0x0000u,


&CRC_TblCRC16_8005[0]


};

即多項式為0x8005,初始值為0x0000,不進行位反轉(zhuǎn),不進行異或輸出,查表為CRC_TblCRC16_8005。

測試代碼如下

#include < stdio.h >
#include < stdint.h >
#include "edc_crc.h"
uint8_t s_buffer[33];
int crc_main(int argc, char* argv[])
{
  const char* p_datap="123456789";
  EDC_ERR err;
  CPU_INT16U   crc = CRC_ChkSumCalc_16Bit((CRC_MODEL_16*)&CRC_ModelCRC16_8005,(void*)p_datap,strlen(p_datap),&err);
  if(EDC_CRC_ERR_NONE != err)
  {
    printf("err\\r\\n");
  }
  else
  {
    printf("crc = %#x\\r\\n",crc);
  }
  return 0;
}

打印值如下

crc = 0xfee8

和edc_crc.h下列舉的測試用例結(jié)果一致

*                       ------------------------------------------------------------------
*                       |    POLY    |  REFLECT?  |  INIT VAL  | COMP. OUT? |     CRC    |
*                       -------------+------------+------------+------------+-------------
*                       |     0x1021 |     NO     |     0x0000 |     NO     |     0x31C3 |
*                       |     0x1021 |     NO     |     0x0000 |     YES    |     0xCE3C |
*                       |     0x1021 |     NO     |     0x1D0F |     NO     |     0xE5CC |
*                       |     0x1021 |     NO     |     0xFFFF |     NO     |     0x29B1 |
*                       |     0x1021 |     NO     |     0xFFFF |     YES    |     0xD64E |
*                       -------------+------------+------------+------------+-------------
*                       |     0x1021 |     YES    |     0x0000 |     NO     |     0x2189 |
*                       |     0x1021 |     YES    |     0x0000 |     YES    |     0xDE76 |
*                       |     0x1021 |     YES    |     0xFFFF |     NO     |     0x6F91 |
*                       |     0x1021 |     YES    |     0xFFFF |     YES    |     0x906E |
*                       -------------+------------+------------+------------+-------------
*                       |     0x8005 |     NO     |     0x0000 |     NO     |     0xFEE8 |
*                       |     0x8005 |     NO     |     0x0000 |     YES    |     0x0117 |
*                       |     0x8005 |     NO     |     0xFFFF |     NO     |     0xAEE7 |
*                       |     0x8005 |     NO     |     0xFFFF |     YES    |     0x5118 |
*                       -------------+------------+------------+------------+-------------
*                       |     0x8005 |     YES    |     0x0000 |     NO     |     0xBB3D |
*                       |     0x8005 |     YES    |     0x0000 |     YES    |     0x44C2 |
*                       |     0x8005 |     YES    |     0xFFFF |     NO     |     0x4B37 |
*                       |     0x8005 |     YES    |     0xFFFF |     YES    |     0xB4C8 |
*                       -------------+------------+------------+------------+-------------
*                       |     0x8048 |     NO     |     0x0000 |     NO     |     0x80A0 |
*                       |     0x8048 |     NO     |     0x0000 |     YES    |     0x7F5F |
*                       |     0x8048 |     NO     |     0xFFFF |     NO     |     0xE8E0 |
*                       |     0x8048 |     NO     |     0xFFFF |     YES    |     0x171F |
*                       -------------+------------+------------+------------+-------------
*                       |     0x8048 |     YES    |     0x0000 |     NO     |     0x1506 |
*                       |     0x8048 |     YES    |     0x0000 |     YES    |     0xEAF9 |
*                       |     0x8048 |     YES    |     0xFFFF |     NO     |     0x1710 |
*                       |     0x8048 |     YES    |     0xFFFF |     YES    |     0xE8EF |
*                       -------------+------------+------------+------------+-------------
*                       | 0x04C11DB7 |     NO     | 0x00000000 |     NO     | 0x89A1897F |
*                       | 0x04C11DB7 |     NO     | 0x00000000 |     YES    | 0x765E7680 |
*                       | 0x04C11DB7 |     NO     | 0xFFFFFFFF |     NO     | 0x0376E6E7 |
*                       | 0x04C11DB7 |     NO     | 0xFFFFFFFF |     YES    | 0xFC891918 |
*                       -------------+------------+------------+------------+-------------
*                       | 0x04C11DB7 |     YES    | 0x00000000 |     NO     | 0x2DFD2D88 |
*                       | 0x04C11DB7 |     YES    | 0x00000000 |     YES    | 0xD202D277 |
*                       | 0x04C11DB7 |     YES    | 0xFFFFFFFF |     NO     | 0x340BC6D9 |
*                       | 0x04C11DB7 |     YES    | 0xFFFFFFFF |     YES    | 0xCBF43926 |
*                       -------------+------------+------------+------------+-------------

CRC原理

參考

https://www.iar.com/knowledge/support/technical-notes/general/checksum-generation/

https://ecomputernotes.com/computernetworkingnotes/communication-networks/cyclic-redundancy-check

CRC即Cyclic Redundancy Check循環(huán)冗余校驗碼,用來進行錯誤檢測,我們對數(shù)據(jù)進行CRC計算得到一個校驗碼,校驗碼和數(shù)據(jù)一起發(fā)送,接收時再對數(shù)據(jù)計算CRC和收到的校驗碼比對,如果校驗值一樣則認為數(shù)據(jù)正確。其根本原理還是奇偶校驗,只是可以認為是花式奇偶校驗,源數(shù)據(jù)反轉(zhuǎn)一個bit會對應(yīng)到CRC值的1位變化,但是源數(shù)據(jù)多位改變則有可能CRC不變。

所以CRC的校驗?zāi)芰Σ⒉皇呛軓?但是比奇偶校驗和求和校驗強,且好在簡單計算快,所以以太網(wǎng)等數(shù)據(jù)傳輸,一些傳感器數(shù)據(jù),底層總線信號包等都使用CRC校驗。

從另一個角度CRC是基于二進制除法(MODULO ARITHMETIC)的算法,要傳輸?shù)臄?shù)據(jù)單元被一個預(yù)定的除數(shù)(二進制數(shù))除以得到余數(shù)。這個余數(shù)稱為CRC。CRC比除數(shù)小1位。這意味著如果CRC為n位,則除數(shù)為n+ 1位。發(fā)送方將這個CRC附加到數(shù)據(jù)單元的末尾,這樣得到的數(shù)據(jù)單元就可以被預(yù)定的除數(shù)完全整除,即余數(shù)變?yōu)榱?。在目的地,輸入的?shù)據(jù)單元(即數(shù)據(jù)+ CRC)被相同的數(shù)字(預(yù)定的二進制除數(shù))所除,如果能整除就說明數(shù)據(jù)正確。

圖片

過程如下

先選擇除數(shù)(即二進制值),即對應(yīng)的我們所說的多項式,比如選1011則對應(yīng)多項式x^3+X^1+x^0,位數(shù)為4.

然后在源數(shù)據(jù)的后面添上4-1個0.比如源數(shù)據(jù)是1001則變?yōu)榱?001000,然后這個值除以1011

注意這里除法有一點不一樣,看最左邊的一位如果余數(shù)最左邊是0則商0,否則商1,另外做減法時不需要借位,只需要滿足0-1=1 0-0=0 1-1=0 1-0=1

圖片

以上運算最終得到余數(shù)110所以,所以接到數(shù)據(jù)后就是1001110

接收端檢測時用1001110除以1011,如果余數(shù)為0說明數(shù)據(jù)正確

圖片

總結(jié)一下

l除數(shù)(多項式的位數(shù))是CRC值的位數(shù)+1,比如對于8位CRC,其多項式的最高位為X^8,包括常數(shù)項就是9位。

lCRC可以檢測到所有影響奇數(shù)位的突發(fā)錯誤,偶數(shù)位不保證

l選擇的多項式?jīng)Q定了檢測錯誤的能力和類型,所以才有了那些標準的多項式

比如

圖片

除數(shù)和多項式的關(guān)系如下,最高次項始終是1,次數(shù)和CRC位數(shù)一樣.

圖片

用多項式的角度看除法就是如下圖,注意減法時不需要借位,系數(shù)滿足1bit的減法。

圖片

而CRC的計算一般都采用了查表法。

CRC計算工具

https://crccalc.com/?crc=01020304&method=crc32&datatype=hex

http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

https://www.lammertbies.nl/comm/info/crc-calculation.html

總結(jié)

以上進行了uC-CRC的CRC部分測試以及相應(yīng)的原理講解,在理解的基礎(chǔ)上可以將代碼集成到自己的項目中使用。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5046

    文章

    18817

    瀏覽量

    298562
  • NAND
    +關(guān)注

    關(guān)注

    16

    文章

    1653

    瀏覽量

    135730
  • crc
    crc
    +關(guān)注

    關(guān)注

    0

    文章

    197

    瀏覽量

    29357
  • Micrium
    +關(guān)注

    關(guān)注

    1

    文章

    7

    瀏覽量

    11726
收藏 人收藏

    評論

    相關(guān)推薦

    Micrium全家uC-FS: 0x02 NAND FTL算法原理詳解

    uC-FS的NAND驅(qū)動實現(xiàn)基于一篇論文:《KAST: K-Associative Sector Translation for NAND Flash Memory in Real-Time Systems》所以有必要先介紹下該論文的內(nèi)容,以便后面理解代碼的實現(xiàn)。
    的頭像 發(fā)表于 06-08 10:55 ?1415次閱讀
    <b class='flag-5'>Micrium</b><b class='flag-5'>全家</b><b class='flag-5'>桶</b><b class='flag-5'>之</b><b class='flag-5'>uC</b>-FS: <b class='flag-5'>0x02</b> NAND FTL算法原理詳解

    Micrium全家uC-FS: 0x01 NAND FTL

    這一篇我們來講講Micrium全家uC-FS。文件系統(tǒng)是一個比較龐大的組件,我們以從下往上的順序介紹,即先以一個具體的設(shè)備:NAND為例,講其FTL的原理和實現(xiàn),然后再講FS部分。
    的頭像 發(fā)表于 06-08 10:58 ?1454次閱讀
    <b class='flag-5'>Micrium</b><b class='flag-5'>全家</b><b class='flag-5'>桶</b><b class='flag-5'>之</b><b class='flag-5'>uC</b>-FS: <b class='flag-5'>0x</b>01 NAND FTL

    Micrium全家uC-CRC: 0x01 ECC

    我們這一篇來講講Micrium全家uC-CRC。該代碼庫提供了CRC算法進行錯誤檢測EDC,使用HAMMING算法實現(xiàn)ECC錯誤糾正。E
    的頭像 發(fā)表于 06-08 11:04 ?1071次閱讀
    <b class='flag-5'>Micrium</b><b class='flag-5'>全家</b><b class='flag-5'>桶</b><b class='flag-5'>之</b><b class='flag-5'>uC-CRC</b>: <b class='flag-5'>0x</b>01 ECC

    STM32的CRC外設(shè)如何設(shè)置

    本文中將介紹的就是如何配置IAR的CRC參數(shù),使與STM32的CRC硬件模塊保持一致。本文中的例子都基于STM32F072進行。
    的頭像 發(fā)表于 09-28 06:05 ?1.7w次閱讀

    CRC的LSB表示方式該如何計算?

    的結(jié)果是011000111B=0xC7,都和格西CRC計算器結(jié)果0x02不一致。那么到底在對LSB表示的CRC該如何計算?還是說我的計算過程有問題?
    發(fā)表于 03-05 11:34

    CRC的LSB表示方式該如何計算?

    的結(jié)果是011000111B=0xC7,都和格西CRC計算器結(jié)果0x02不一致。那么到底在對LSB表示的CRC該如何計算?還是說我的計算過程有問題?
    發(fā)表于 03-05 13:59

    從M24SR通過i2c發(fā)送和接收字節(jié)時無法計算CRC

    命令來讀取CC文件長度,我將如何計算CRC?起始位0xAC 0x02 0x00 0xB0 0x0
    發(fā)表于 07-17 08:15

    CRC校驗源碼分析

    CRC根據(jù)權(quán)(即多項表達式)的不同而相應(yīng)的源代碼也有稍許不同。以下是各種常用的權(quán): CRA8 =X8+X5+X4+1 CRC-CCITT =X16+X12+X5+1
    發(fā)表于 04-07 20:49 ?117次下載

    STM32軟件CRC和硬件CRC速度測試

    軟件提前生成CRC表,用于查詢。分別使用軟件CRC算法和硬件CRC外設(shè)對一個緩存進行計算,目的是從該緩存中找到同步頭。同步頭共11字節(jié),前兩個字節(jié)為后九個字節(jié)的CRC校驗值。通過迭代算
    發(fā)表于 05-09 11:45 ?6313次閱讀
    STM32<b class='flag-5'>之</b>軟件<b class='flag-5'>CRC</b>和硬件<b class='flag-5'>CRC</b>速度測試

    CRC算法原理和CRC編碼的實現(xiàn)方式與使用Verilog對CRC編碼進行描述

    CRC 校驗是一種在數(shù)據(jù)通信系統(tǒng)和其它串行傳輸系統(tǒng)中廣泛使用的錯誤檢測手段。通用的CRC 標準有CRC-8、CRC-16、CRC-32、
    發(fā)表于 08-06 16:39 ?36次下載
    <b class='flag-5'>CRC</b>算法原理和<b class='flag-5'>CRC</b>編碼的實現(xiàn)方式與使用Verilog對<b class='flag-5'>CRC</b>編碼進行描述

    CRC校驗 、STM32中CRC計算單元、 CRC應(yīng)用

    CRC校驗、STM32中CRC計算單元、CRC應(yīng)用
    的頭像 發(fā)表于 03-04 13:54 ?5841次閱讀

    用于單片機的CRC數(shù)據(jù)校驗方法

    方法也夠用了。二、代碼實現(xiàn)1.CRC表格crc table:static const u16 ccitt_table[256] = { 0x0000, 0x1021,
    發(fā)表于 12-17 18:35 ?3次下載
    用于單片機的<b class='flag-5'>CRC</b>數(shù)據(jù)校驗方法

    FPGA學(xué)習(xí)CRC校驗

    其中有的CRC寄存器初始值設(shè)置為全1,如以太網(wǎng)的CRC32,目的就是為了能檢測出數(shù)據(jù)前面的0的個數(shù)。1234算出來的CRC,跟01234算出來的,不一樣,這就能應(yīng)對前面帶
    發(fā)表于 08-26 14:11 ?2263次閱讀

    講講Micrium全家uC-CRC算法

    我們這一篇來講講Micrium全家uC-CRC。該代碼庫提供了CRC算法進行錯誤檢測EDC,使用HAMMING算法實現(xiàn)ECC錯誤糾正。
    的頭像 發(fā)表于 05-04 10:47 ?749次閱讀
    講講<b class='flag-5'>Micrium</b><b class='flag-5'>全家</b><b class='flag-5'>桶</b>的<b class='flag-5'>uC-CRC</b>算法

    這個CRC計算單元是如何基于固定的生成多項式(0x4C11DB7)來獲取給定數(shù)據(jù)緩沖區(qū)的CRC碼的?

    這個CRC計算單元是如何基于固定的生成多項式(0x4C11DB7)來獲取給定數(shù)據(jù)緩沖區(qū)的CRC碼的?
    的頭像 發(fā)表于 05-16 16:06 ?483次閱讀