Micrium全家桶之uC-CRC: 0x02 CRC (qq.com)
前言
前一篇我们讲了Micrium全家桶之uC-CRC: 0x01 ECC:https://mp.weixin.qq.com/s/FKVvzwL7wzxLJCkx3gOdJQ。ECC常用于NAND进行误码校正。而CRC一般用于错误检测,比如镜像,协议的正确完备性检测。
这一篇我们来讲讲uC-CRC组件的CRC部分,老规矩先代码用起来,然后再讲讲原理,理论结合实践。
使用
可以从https://github.com/qinyunti/uC-CRC.git下载代码,该版本在原版本基础上进行了修改,删除了其他依赖,可以单独使用,方便移植,也可以参考https://mp.weixin.qq.com/s/FKVvzwL7wzxLJCkx3gOdJQ。
有了上一篇基础我们不再详细介绍如何集成该代码,直接进入测试环节。
文件
如果只使用CRC的话只需要crc_cfg.h和edc_crc.c,edc_crc.h即可。
配置
其中cec_cfg.h的宏EDC_CRC_CFG_OPTIMIZE_ASM_EN配置是否使用汇编代码实现,默认为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交换...,通过查表法空间换时间加快速度。有些场景需要位翻转,所以有这个实现。
#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位的
流式操作,结果存在结构体参数种 只支持查表法
CRC_Open_16Bit()->
CRC_WrBlock_16Bit()-> 一次写多个字节
CRC_WrOctet_16Bit()-> 一次写一个字节
CRC_Close_16Bit()->
32位的类似
CRC_Open_32Bit->
CRC_WrBlock_32Bit->
CRC_WrOctet_32Bit->
CRC_Close_32Bit->
这里提供这几个位反转接口,最后结果再调用这些接口进行位反转。
CRC_Reflect_08Bit 查表法实现8位数据位反转 查表是CRC_ReflectTbl
CRC_Reflect_16Bit 查表法实现16位数据位反转
CRC_Reflect_32Bit 查表法实现32位数据位反转
还提供两个接口直接计算,立即返回计算值,支持查表和不查表
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);
第一个参数传入默认配置好的
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 |