<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[YTM32B1HA0 执行A&#x2F;B SWAP后Fls Ecc测试失败问题]]></title><description><![CDATA[<h1>问题描述</h1>
<p dir="auto">YTM32B1HA0 EccTst 代码，在执行 A/B SWAP 前（代码运行于原 A 面）可正常运行且测试通过；执行 A/B SWAP 切换至原 B 面后，运行相同的 EccTst 测试代码，出现Fls Ecc测试失败。</p>
<ul>
<li>
<p dir="auto">A/B Swap前Fls Ecc测试成功<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/12/db7a8f60-dda3-4e06-b04b-a17830c2922c.png" alt="eb30d6a9-511a-413a-af4e-6c778a696bc7-image.png" class=" img-fluid img-markdown" /></p>
</li>
<li>
<p dir="auto">A/B Swap后Fls Ecc测试失败<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/12/491201a9-1b2b-4cf8-8350-91ff360ffc14.png" alt="6bf9eca2-0270-4620-8f0b-5b7cb17d0c8f-image.png" class=" img-fluid img-markdown" /></p>
</li>
</ul>
<h1>复现方法</h1>
<p dir="auto">使用云途提供的EccTst_Demo程序，在工程中增加Nvr Fls操作驱动，并在Demo的main函数中增加A/B SWAP代码执行A/B面切换，然后复位MCU，并重新烧录代码到MCU原B面中，然后再次运行EccTest_Demo 代码，此次运行结果中Fls Ecc测试结果显示为失败。<br />
增加的测试代码如下所示：</p>
<pre><code class="language-c">int main(void)
{
    /* USER CODE BEGIN 1 */
    Mcu_Init(&amp;Mcu_Config);
    Mcu_InitClock(0);
#if (MCU_NO_PLL == STD_OFF)
    while (MCU_PLL_LOCKED != Mcu_GetPllStatus())
    {
        /* Busy wait until the System PLL is locked */
    }
    Mcu_DistributePllClock();
#endif
    /* USER CODE END 1 */ 
    Board_Init();
    /* USER CODE BEGIN 2 */
    Fls_ReadSwap(&amp;info);
    if (info == 0u)
	{
      Fls_WriteSwap();
      Mcu_Lld_SystemReset();
	}
    EccTst_Start();
    EccTst_TestSummerResult = EccTst_GetResult();
    EccTst_GetDetailsResult(&amp;EccTst_TestDetailResult);
    EccTst_DeInit();
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */
        /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
}
</code></pre>
<h1>原因分析</h1>
<p dir="auto">经与 IP 确认：当STS[BOOT_INFO] = 1时，通过ECCERR_INJECT_ADDR进行 ECC 错误注入，所配置的地址为存储器物理地址，不受 Flash A/B SWAP 切换逻辑影响。</p>
<p dir="auto">以地址0x2000400为例：A/B SWAP 切换前，该地址归属 A 面存储区间，向ECCERR_INJECT_ADDR配置0x2000400注入错误时，实际作用地址与 EccTst 测试所用地址一致，测试可正常通过。完成 A/B SWAP 切换后，逻辑地址0x2000400映射为 B 面存储地址；但由于错误注入机制不感知 A/B SWAP，此时仍对0x2000400配置注入时，实际会作用于<strong>A 面物理地址 0x2100400</strong>。测试代码读取逻辑地址0x2000400（B 面）时，无法命中已注入 ECC 错误的存储单元，不会触发 ECC 异常，最终造成 Fls Ecc 测试失败。</p>
<p dir="auto">进一步验证该现象，在A/B SWAP之后，对0x2000400地址注入错误，实际读取0x2100400能够触发ECC错误，且EFM ECC_ERR_ADDR寄存器捕获到地址为0x2100400<br />
<img src="https://yt-static-main.oss-cn-shanghai.aliyuncs.com/nodebb/12/3a504f55-67e5-4271-9edf-5ab7af3f91f9.png" alt="74805f65-ca8a-46a9-be1e-5118ebcea7bf-image.png" class=" img-fluid img-markdown" /></p>
<h1>修复方案</h1>
<p dir="auto">根据上述原因分析，可采用如下方案修复该问题：在执行错误注入测试时，若检测到STS[BOOT_INFO] = 1，需由代码对写入ECCERR_INJECT_ADDR的地址执行手动 A/B SWAP 映射处理。</p>
<pre><code class="language-c">#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-&gt;STS &amp; EFM_STS_BOOT_INFO_MASK) &gt;&gt; EFM_STS_BOOT_INFO_SHIFT) == 1U)
    {
        if ((InjectAddr &gt;= FLASH_PFLASH0_BASE) &amp;&amp; (InjectAddr &lt; FLASH_PFLASH0_BASE + FLASH_PFLASH_BANK_SIZE))
        {
            TempAddr =InjectAddr + FLASH_PFLASH_BANK_SIZE;
        }
        else if ((InjectAddr &gt;= FLASH_PFLASH1_BASE) &amp;&amp; (InjectAddr &lt; 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();
}

</code></pre>
<h1>影响版本及临时解决方案</h1>
<p dir="auto">本次问题影响的版本如下：</p>
<ul>
<li>YTM32B1HA0_SafLib_2_0_0及之前版本。</li>
</ul>
<p dir="auto">在本次问题修复版本正式发布前，可按照前文所述修复方案，修改EccTst_Lld_Fls.c文件中的对应函数，作为临时解决方案。</p>
]]></description><link>https://forum.ytmicro.com/topic/1941/ytm32b1ha0-执行a-b-swap后fls-ecc测试失败问题</link><generator>RSS for Node</generator><lastBuildDate>Wed, 20 May 2026 04:41:22 GMT</lastBuildDate><atom:link href="https://forum.ytmicro.com/topic/1941.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 11 May 2026 11:13:43 GMT</pubDate><ttl>60</ttl></channel></rss>