【问题背景】
在之前适配CRC(S32K146使用CRC模块校验数据 )帖子中,我们已经验证了CRC32功能正常,我们在使用IAR生成的镜像在末端添加CRC校验码,使用CRC模块进计算和IAR生成的值进行比较发现校验失败了,IAR的CRC32校验功能网上介绍也比较多,在此不做重点介绍,本地IAR 环境参数如下:
【问题调查】
因为CRC硬件算法功能我们本地已经验证过算法的正确性,所以开始一致怀疑是IAR生成的镜像的CRC 的正确性,本地将生成的镜像使用在线工具进行校验发现IAR生成的镜像校验码也是正确的。IAR 生成的镜像校验码为0x9c80e558
使用在线工具验证生成的镜像的CRC校验码和IAR生成的一致。
至此我们可能进入死胡同了,CRC功能和IAR生成的校验码都是经过验证是正确的,但是以下测试代码硬件CRC校验计算的值和IAR生成的是不一致的,以下验证代码计算结果如下:
unsigned int image_check(char argc,char *argv[]) { CRC_DRV_Deinit(INST_CRC_1); CRC_DRV_Init(INST_CRC_1,&crc_1_Cfg0); CRC_DRV_WriteData(INST_CRC_1,(uint8_t *)0,0xffffc); printf("crc32 %08x,IAR %08x \r\n",CRC_DRV_GetCrcResult(INST_CRC_1),*(((unsigned long *)0xffffc)));
上述代码运行结果硬件CRC计算的结果看上去是不正确的
既然CRC和IAR 都是经过验证没问题的,会不会是运行时软件读取的flash的内容和生成的镜像是有区别的?带着这个想法,软件运行起来后通过仿真器将flash 的全部内容dump 出来和原始的bin 文件进行比较,比较后发现果然是软件读取的flash 的内容和编译后的是在0x40d 处是不一样的。
至此我们已经发现了问题的原因,至于为什么不一样我们需要进一步研究下,0x40d存储的是什么内容呢?我们先查看linkfile发现S32K146 的 0x400~040f 保存的flash 的配置数据。
对应的代码配置如下
从上述配代码配置注释可知,0x40d对应的FOPT 配置,手册中对该配置说明如下
不一样的正好是bit1 的保留处理的信号,怀疑是这个保留的bit 软件读取总是0 从而出发了上述异常。
在IAR环境中,针对这种下载和读取不一致的问题可以开启镜像下载校验,这样就会在debug 下载的时候就暴露出找个问题,对应的配置如下,建议开启该选项开启该选项后会先下载然后校验,下载过程相对会耗时些。
开启后我么下载就会报出如下的错误,跟我们之前分析的原因也是一致的,只是之前我们没有开启对应镜像校验功能所以没发现该问题。
【解决方法】
知道了问题原因,我们就可以针对问题点进行解决。
解决方案1:
既然这个bit 是保留的没有使用,我们可以直接修改代码配置将默认的0x40d配置修改为0xfd,这样就不会出现上述异常了。
配置修改为0x7d,修改后编译代码运行,发现这次IAR 生成的CRC和 CRC模块计算的保持一致了。
解决方案2:
毕竟上述配置会修改默认的配置代码,虽然手册是保留未使用的bit,也不确定芯片是否有特殊的用途该bit,我们可以分段校验把0x40d的检验数据更新成0x7f这样就不需要修改NXP的默认配置。
修改代码如下:
unsigned int image_check(char argc,char *argv[]) { CRC_DRV_Deinit(INST_CRC_1); CRC_DRV_Init(INST_CRC_1,&crc_1_Cfg0); CRC_DRV_WriteData(INST_CRC_1,(uint8_t *)0,0x40d); uint8_t data_0x40d = 0x7f; CRC_DRV_WriteData(INST_CRC_1,(uint8_t *)&data_0x40d,1); CRC_DRV_WriteData(INST_CRC_1,(uint8_t *)0x40e,0xffbee); printf("crc32 %08x,IAR %08x \r\n",CRC_DRV_GetCrcResult(INST_CRC_1),*(((unsigned long *)0xffffc)));
修改后代码验证CRC 和 IAR 的也是匹配的。
上述两种修改方案个人倾向与第二种,第二种不会修改默认配置,因为手册里也没有写这个bit 写0 会不又有潜在的问题,不确定芯片原厂的芯片设计该bit 是否有特殊用途只是手册上未说明罢了。