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ī)矩先代碼用起來,然后再講講原理,理論結合實踐。
使用
可以從https://github.com/qinyunti/uC-CRC.git下載代碼,該版本在原版本基礎上進行了修改,刪除了其他依賴,可以單獨使用,方便移植,也可以參考https://mp.weixin.qq.com/s/FKVvzwL7wzxLJCkx3gOdJQ。
有了上一篇基礎我們不再詳細介紹如何集成該代碼,直接進入測試環(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.
以下宏配置是否使能對應的算法和反轉查找表
其中前面4個宏使能了4種算法,后面4個宏定義是否支持位反轉模式,如果是則會定義對應的CRC查找表,比如EDC_CRC_CFG_CRC32_REF_EN使能則使用CRC_TblCRC32_ref,EDC_CRC_CFG_CRC32_EN使能則使用CRC_TblCRC32。
所謂的位反轉就是bit7和bit0交換,bit6和bit1交換...,通過查表法空間換時間加快速度。有些場景需要位翻轉,所以有這個實現(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位的
流式操作,結果存在結構體參數(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->
這里提供這幾個位反轉接口,最后結果再調(diào)用這些接口進行位反轉。
CRC_Reflect_08Bit 查表法實現(xiàn)8位數(shù)據(jù)位反轉 查表是CRC_ReflectTbl
CRC_Reflect_16Bit 查表法實現(xiàn)16位數(shù)據(jù)位反轉
CRC_Reflect_32Bit 查表法實現(xiàn)32位數(shù)據(jù)位反轉
還提供兩個接口直接計算,立即返回計算值,支持查表和不查表
CRC_ChkSumCalc_16Bit
CRC_ChkSumCalc_32Bit
所以以上有幾種配置:使用查表還是不使用查表,使用位反轉還是不使用
p_model->Reflect == DEF_YES 則使用位反轉
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,不進行位反轉,不進行異或輸出,查表為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下列舉的測試用例結果一致
* ------------------------------------------------------------------
* | 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 |