YTM32B1HA0 EccTst 代码,在执行 A/B SWAP 前(代码运行于原 A 面)可正常运行且测试通过;执行 A/B SWAP 切换至原 B 面后,运行相同的 EccTst 测试代码,出现Fls Ecc测试失败。
A/B Swap前Fls Ecc测试成功
eb30d6a9-511a-413a-af4e-6c778a696bc7-image.png
A/B Swap后Fls Ecc测试失败
6bf9eca2-0270-4620-8f0b-5b7cb17d0c8f-image.png
使用云途提供的EccTst_Demo程序,在工程中增加Nvr Fls操作驱动,并在Demo的main函数中增加A/B SWAP代码执行A/B面切换,然后复位MCU,并重新烧录代码到MCU原B面中,然后再次运行EccTest_Demo 代码,此次运行结果中Fls Ecc测试结果显示为失败。
增加的测试代码如下所示:
经与 IP 确认:当STS[BOOT_INFO] = 1时,通过ECCERR_INJECT_ADDR进行 ECC 错误注入,所配置的地址为存储器物理地址,不受 Flash A/B SWAP 切换逻辑影响。
以地址0x2000400为例:A/B SWAP 切换前,该地址归属 A 面存储区间,向ECCERR_INJECT_ADDR配置0x2000400注入错误时,实际作用地址与 EccTst 测试所用地址一致,测试可正常通过。完成 A/B SWAP 切换后,逻辑地址0x2000400映射为 B 面存储地址;但由于错误注入机制不感知 A/B SWAP,此时仍对0x2000400配置注入时,实际会作用于A 面物理地址 0x2100400。测试代码读取逻辑地址0x2000400(B 面)时,无法命中已注入 ECC 错误的存储单元,不会触发 ECC 异常,最终造成 Fls Ecc 测试失败。
进一步验证该现象,在A/B SWAP之后,对0x2000400地址注入错误,实际读取0x2100400能够触发ECC错误,且EFM ECC_ERR_ADDR寄存器捕获到地址为0x2100400
74805f65-ca8a-46a9-be1e-5118ebcea7bf-image.png
根据上述原因分析,可采用如下方案修复该问题:在执行错误注入测试时,若检测到STS[BOOT_INFO] = 1,需由代码对写入ECCERR_INJECT_ADDR的地址执行手动 A/B SWAP 映射处理。
#if defined (CPU_YTM32B1HA0) #define FLASH_PFLASH0_BASE 0x2000000U #define FLASH_PFLASH1_BASE 0x2100000U #define FLASH_PFLASH_BANK_SIZE 0x100000U #endif ECCTST_FUNC static void EccTst_Lld_Fls_TestEnable(uint32 InjectAddr, uint32 InjectData0, uint32 InkectData1) { volatile uint32 TempData = 0; uint32 TempAddr = 0; /*enable the error injection,the one bit ECC error will happen when read data in test address*/ EccTst_Lld_Fls_EnInjectErr(); /*Inject error data and address*/ EccTst_Lld_Fls_InjectData(InjectData0, InkectData1); /*The inject address does not swap with the A/B SWAP*/ if (((EFM->STS & EFM_STS_BOOT_INFO_MASK) >> EFM_STS_BOOT_INFO_SHIFT) == 1U) { if ((InjectAddr >= FLASH_PFLASH0_BASE) && (InjectAddr < FLASH_PFLASH0_BASE + FLASH_PFLASH_BANK_SIZE)) { TempAddr =InjectAddr + FLASH_PFLASH_BANK_SIZE; } else if ((InjectAddr >= FLASH_PFLASH1_BASE) && (InjectAddr < FLASH_PFLASH1_BASE + FLASH_PFLASH_BANK_SIZE)) { TempAddr =InjectAddr - FLASH_PFLASH_BANK_SIZE; } else { TempAddr = InjectAddr; } } else { TempAddr = InjectAddr; } EccTst_Lld_Fls_InjectAddr(TempAddr); __ASM("ISB"); __ASM("DSB"); #if (PLATFORM_ENABLE_CACHE == STD_ON) /* MR12 Rule 11.4 VIOLATION: In this specific case, need to clear the DCACHE for ECC error injection, * and couldn't adhere to M3CM Rule-11.4. */ SCB_InvalidateDCache_by_Addr((uint32 *)InjectAddr, 64); /*PRQA S 0306*/ #endif /*Trigger fls ECC error*/ /* MR12 Rule 11.4 VIOLATION: In this specific case, need to read the InjectAddr to trigger ECC error, * and couldn't adhere to M3CM Rule-11.4. */ TempData = *((uint32 *)InjectAddr); /*PRQA S 0306*/ /*The purpose of the following code is simply to keep the previous line of code from being optimized by the compiler.*/ TempData += 1U; if (TempData != 1U) { __ASM("nop"); } EccTst_Lld_Fls_DisInjectErr(); } 影响版本及临时解决方案本次问题影响的版本如下:
YTM32B1HA0_SafLib_2_0_0及之前版本。在本次问题修复版本正式发布前,可按照前文所述修复方案,修改EccTst_Lld_Fls.c文件中的对应函数,作为临时解决方案。