跳转至内容
  • 28 主题
    40 帖子
    houjun_xiaoH
    问题描述

    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测试结果显示为失败。
    增加的测试代码如下所示:

    int main(void) { /* USER CODE BEGIN 1 */ Mcu_Init(&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(&info); if (info == 0u) { Fls_WriteSwap(); Mcu_Lld_SystemReset(); } EccTst_Start(); EccTst_TestSummerResult = EccTst_GetResult(); EccTst_GetDetailsResult(&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 */ } 原因分析

    经与 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文件中的对应函数,作为临时解决方案。

  • 2k 主题
    8k 帖子
    xianghanX

    IPC是用来选择外设模块的时钟源,改变slow bus和IPC没直接关系,只有当外设被配置成slow bus才会有影响

  • Blog posts from individual members

    47 主题
    147 帖子
    swustS
    前言

    Bootloader (引导加载程序)是嵌入式系统上电启动后运行的第一段代码。它常驻在 Flash 的最前面(一般从 0x0 地址开始),通常需要被永久保护、绝对不允许被修改。在汽车电子领域,boot loader扮演者非常重要的角色,其作用主要体现在以下方面:

    防止固件被非法篡改,提高ECU的安全性; 很多场景需要OTA升级,而boot loader提供了更新软件的能力; 隔离底层硬件和上层业务。
    本文以YTM32B1系列微控制器(基于 ARM Cortex-M0+/M33/M7 内核) 为例,介绍汽车嵌入式 Boot 的流程。 Boot loader跳转本质

    Boot 跳转 App 的本质不是调用某个函数,而是把 CPU 的启动上下文切换到 App 的向量表,让 App 像刚上电复位后启动一样运行。其中,有两个最关键的东西:MSP 和 Reset_Handler。
    所以 Boot 要做的事情可以概括为:

    确认 App 镜像存在且合法; 关闭 Boot 自己已经打开的中断和外设影响; 关闭 SysTick; 清除 NVIC 使能与挂起; 把向量表重定位到 App 首地址; 把 MSP 切换为 App 向量表中的初始栈顶; 跳转到 App 的 Reset_Handler; 标准跳转流程 上电运行Boot
    芯片复位后,CPU 默认从 0x0000_0000 取向量表,因此通常先进入 BootLoader。
    Boot 可以先完成以下事情: 时钟初始化 看门狗处理 升级标志检查 固件校验 通信升级
    如果无需升级,只需要运行App,直接执行跳转。 跳转前的收尾工作 关闭全局中断
    SDK调用INT_SYS_DisableIRQGlobal(),MCAL可在特权模式下调用SuspendAllInterrupts()来关闭全局中断。
    ps:调用"Sys_GoToSupervisor()"进入特权模式。 关闭Systick SysTick->CTRL = 0U; SysTick->LOAD = 0U; SysTick->VAL = 0U; 关闭所有 NVIC 中断使能 NVIC->ICER[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL)); NVIC->ICPR[(((uint32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)IRQn) & 0x1FUL));

    NVIC属于的寄存器是异步寄存器,有写缓冲延迟,而Cortex-M是流水线架构,需要加上如下两句

    __DSB();(数据同步屏障) __ISB();(指令同步屏障)

    在不清楚当前开启了哪些中断或开启的中断较多时,可以使用循环将所有bit都清一遍,对于Cortex-M0+内核:

    NVIC->ICER[0] = 0xFFFFFFFFUL; __DSB(); __ISB();

    Cortex-M33内核:

    for (uint8_t i = 0; i < 15U; i++) { NVIC->ICER[i] = 0xFFFFFFFFUL; } __DSB(); __ISB(); 清掉所有 NVIC 挂起位 NVIC->ICPR[0] = 0xFFFFFFFFUL; __DSB(); __ISB(); for (uint8_t i = 0; i < 15U; i++) { NVIC->ICPR[i] = 0xFFFFFFFFUL; } __DSB(); __ISB(); 关闭所有外设 重定位向量表 SCB->VTOR = app_addr; __DSB(); __ISB(); 设置 MSP 并跳转复位入口 __set_MSP(app_msp); __DSB(); __ISB(); app_entry();

    其中,

    app_msp = *(volatile uint32_t *)addr,app_entry = (pFunction)app_reset, 关键注意事项 Boot和App空间一定不能重叠,划分地址时需要注意; 跳转前检查栈顶地址是否合法; 下载App需要修改Flash起始地址; 进入 App 后,应该按正常冷启动流程重新初始化。 代码参考

    Uds Fbl demo合集
    https://cloud.ytm32.cn/s/vBECk?path=%2F03_Fbl demo

    常见问题总结

    https://forum.ytmicro.com/topic/18/le-bootloader问题汇总?_=1758613536259

  • 云途开发生态介绍

    快速上手云途开发生态

  • 云途论坛规则/Yuntu Forum Rules

    发帖前请查看

  • YT CONFIG TOOL调查问卷

    帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...

  • Online Users