查看: 319|回复: 0

[原创] 【S32K146 功能安全特性】EIM/ERM 功能验证

[复制链接]
  • TA的每日心情
    奋斗
    前天 13:25
  • 签到天数: 594 天

    [LV.9]以坛为家II

    51

    主题

    2222

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    7062
    最后登录
    2024-4-27
    发表于 2024-1-22 22:30:50 | 显示全部楼层 |阅读模式
    本帖最后由 andeyqi 于 2024-1-24 14:14 编辑

    S32K146 作为一颗车规级的芯片,芯片自身是支持功能安全相关的特性,芯片的功能安全等级是ASIL-B等级。从以下功能安全手册的描述可以看到S32K14X 芯片的FLASH/SRAM 是支持硬件ECC校验机制,支持 SEC/DED 算法纠正1bit 错误及多bit 错误检出机制。
    2485.jpg

    ECC 功能如果软件要验证的话,正常情况下是不会触发bit 错误异常的,正常情况这个异常是很难触发的,软件如果要验证这个功能需要怎么触发验证呢,EIM是个错误注入模块可以对数据线及ECC码进行注入错误验证,确保ECC功能的安全可靠,以下是EIM模块的框体,从框图能够看出EIM 模块可以控制对应的bit 读取的数据发生位反转。
    32624.jpg
    从如下框图也可以看出来CPU 通过LMEM(Local Memory Controller) 单元访问RAM 资源中间是途经EIM模块,从而EIM 完成对应的路径的注错验证诊断RAM ECC 功能。
    EIM.PNG
    EIM 能够注入错误,朱武的错误如何被检出报告,S32K内部还有个ERM模块这个模块能检出SRAM 是否发生了ECC 错误及ECC错误的类型,并具有中断信号输出通知到CORE 的能力,ERM 的介绍如下:
    screenshot-20240122-154638.png


    • EIM 单bit 错误注入验证
    我们使用SDK 的配置接口,使能配置EIM/ERM 通过EIM 注入1bit 错误,然后读取ERM 状态寄存器判断注入错误状态是否成功是否按照预期的检测出ECC错误,对应的测试代码如下:
    eim config:
    1. /**
    2. * @page misra_violations MISRA-C:2012 violations
    3. *
    4. * @section [global]
    5. * Violates MISRA 2012 Advisory Rule 8.7, External variable could be made static.
    6. * The external variables will be used in other source files in application code.
    7. *
    8. */

    9. /* Channel configurations */
    10. const eim_user_channel_config_t eim_InitConfig0[EIM_CHANNEL_COUNT0] =
    11. {
    12.     /* Channel configuration 0 */
    13.     {
    14.         .channel = 0U,
    15.         .checkBitMask = 0U,
    16.         .dataMask = 1U,
    17.         .enable = true
    18.     }
    19. };
    复制代码
    erm config:
    1. /* Interrupt configurations */

    2. /* Interrupt configuration 0 */
    3. const erm_interrupt_config_t erm_Interrupt0 =
    4. {
    5.     .enableSingleCorrection = true,
    6.     .enableNonCorrectable = true
    7. };

    8. /* ERM configurations */

    9. /* ERM configuration 0 */
    10. const erm_user_config_t erm_InitConfig0[ERM_CHANNEL_COUNT0] =
    11. {
    12.     /* Channel configuration 0 */
    13.     {
    14.         .channel = 0U,
    15.         .interruptCfg = &erm_Interrupt0
    16.     }
    17. };
    复制代码
    测试代码:
    1. #include <stdio.h>
    2. #include <rtthread.h>
    3. #include <rtdevice.h>
    4. #include <board.h>



    5. int eim_correct(void)
    6. {
    7.     uint32_t test;
    8.     uint32_t addr;
    9.     erm_ecc_event_t retValue = ERM_EVENT_NONE;

    10.     /* Initialize address used to test */
    11.     *(uint32_t *)0x1FFFFFF0U = 0U;

    12.     /* Hardware initialization */
    13.     /* Initial for ERM module */
    14.     ERM_DRV_Init(INST_ERM_CONFIG_1, ERM_CHANNEL_COUNT0, erm_InitConfig0);
    15.     /* Initial for EIM module */
    16.     EIM_DRV_Init(INST_EIM_CONFIG_1, EIM_CHANNEL_COUNT0, eim_InitConfig0);

    17.     /* Read any address on RAM  */
    18.     /* Enable read region Ram (0x1FFF8000 - 0x20006FFF) when debug equal Flash */
    19.     test = *(uint32_t *)0x1FFFFFF0U;
    20.     (void)test;

    21.     /* Deinit EIM module */
    22.     EIM_DRV_Deinit(INST_EIM_CONFIG_1);

    23.     /* Check error and get address which EIM injection error */
    24.     retValue = ERM_DRV_GetErrorDetail(INST_ERM_CONFIG_1, 0U, &addr);

    25.     rt_kprintf("erm status %s error addr is 0x%08x\n",\
    26.                 retValue == ERM_EVENT_NONE ? "ERM_EVENT_NONE" :\
    27.                 (retValue == ERM_EVENT_SINGLE_BIT ? "ERM_EVENT_SINGLE_BIT" :\
    28.                 (retValue == ERM_EVENT_NON_CORRECTABLE ? "ERM_EVENT_NON_CORRECTABLE" : "ERM_EVENT_NONE")),\
    29.                 addr);

    30.     return 0;
    31. }
    32. MSH_CMD_EXPORT_ALIAS(eim_correct, eim1 ,eim correct test);
    复制代码

    运行上述测试代码,输入eim1 测试命令,ERM 模块已经按照预期的检测到单bit 错误。
    eim_8898.jpg

    • ERM 单bit 错误中断验证
    在上述代码的基础上追加ERM 中断使能,查看中断函数能否被正常执行,对应代码修改如下:
    screenshot-20240122-172024.png


    输入测试命令,中断处理函数内部已经捕获到但比特错误并清除掉该错误标志。
    13395.jpg

    如果看的仔细会发现中断的形式EPM宝出来的地址和直接查询状态时对应的地址时不同的,中断的方式我们用来triger 读取的是0x1FFFFFF0U 的测试地址,为什么中断报出来的是0x1fff00f0,这个是因为触发中断的时候回去读取中断向量表,我们的中断向量表是在SRAM里,我们debug 查下0x1fff00f0存储的是不是对应的中断函数。通过下图可知道确实是中断向量,所以EPM 记录的是最后一次触发的一场地址。
    24841.jpg

    • EIM 多bit 错误注入验证
    验证完了单bit ECC异常,我们修改EIM 的配置往ECC区域注入多bit 错误 看看是否也会跟上面一样触发中断。
    修改EIM 配置:

    1. const eim_user_channel_config_t eim_InitConfig1[EIM_CHANNEL_COUNT1] =
    2. {
    3.     /* Channel configuration 0 */
    4.     {
    5.         .channel = 0U,
    6.         .checkBitMask = 3U,
    7.         .dataMask = 0U,
    8.         .enable = true
    9.     }
    10. };
    复制代码
    添加如下测试指令eim2:
    1. /*!
    2.   \brief The ERM_ISR funcion invert state Led
    3.   *- Clear event when have notify interrupt
    4. */
    5. void erm_doublebit_isr(void)
    6. {
    7.     uint32_t addr;
    8.     erm_ecc_event_t retValue = ERM_EVENT_NONE;

    9.     /* Deinit EIM module */
    10.     EIM_DRV_Deinit(INST_EIM_CONFIG_1);

    11.     /* Check error and get address which EIM injection error */
    12.     retValue = ERM_DRV_GetErrorDetail(INST_ERM_CONFIG_1, 0U, &addr);

    13.     rt_kprintf("erm isr status %s error addr is 0x%08x\n",\
    14.                 retValue == ERM_EVENT_NONE ? "ERM_EVENT_NONE" :\
    15.                 (retValue == ERM_EVENT_SINGLE_BIT ? "ERM_EVENT_SINGLE_BIT" :\
    16.                 (retValue == ERM_EVENT_NON_CORRECTABLE ? "ERM_EVENT_NON_CORRECTABLE" : "ERM_EVENT_NONE")),\
    17.                 addr);
    18.     /* The interrupt notification will be cleared.*/
    19.     ERM_DRV_ClearEvent(INST_ERM_CONFIG_1, 0U, ERM_EVENT_NON_CORRECTABLE);
    20. }

    21. int eim_double_bit(void)
    22. {
    23.     uint32_t test;
    24.     uint32_t addr;
    25.     erm_ecc_event_t retValue = ERM_EVENT_NONE;

    26.     /* Initialize address used to test */
    27.     *(uint32_t *)0x1FFFFFF0U = 0U;

    28.     /* Install IRQ Handlers for ERM and SysTick */
    29.     INT_SYS_InstallHandler(ERM_double_fault_IRQn, erm_doublebit_isr, (isr_t *)0);
    30.     /* Enable ERM IRQ */
    31.     INT_SYS_EnableIRQ(ERM_double_fault_IRQn);

    32.     /* Hardware initialization */
    33.     /* Initial for ERM module */
    34.     ERM_DRV_Init(INST_ERM_CONFIG_1, ERM_CHANNEL_COUNT0, erm_InitConfig0);
    35.     /* Initial for EIM module */
    36.     EIM_DRV_Init(INST_EIM_CONFIG_1, EIM_CHANNEL_COUNT1, eim_InitConfig1);

    37.     /* Read any address on RAM  */
    38.     /* Enable read region Ram (0x1FFF8000 - 0x20006FFF) when debug equal Flash */
    39.     test = *(uint32_t *)0x1FFFFFF0U;
    40.     (void)test;

    41.     /* Deinit EIM module */
    42.     EIM_DRV_Deinit(INST_EIM_CONFIG_1);

    43.     /* Check error and get address which EIM injection error */
    44.     retValue = ERM_DRV_GetErrorDetail(INST_ERM_CONFIG_1, 0U, &addr);

    45.     rt_kprintf("erm status %s error addr is 0x%08x\n",\
    46.                 retValue == ERM_EVENT_NONE ? "ERM_EVENT_NONE" :\
    47.                 (retValue == ERM_EVENT_SINGLE_BIT ? "ERM_EVENT_SINGLE_BIT" :\
    48.                 (retValue == ERM_EVENT_NON_CORRECTABLE ? "ERM_EVENT_NON_CORRECTABLE" : "ERM_EVENT_NONE")),\
    49.                 addr);

    50.     return 0;
    51. }
    52. MSH_CMD_EXPORT_ALIAS(eim_double_bit, eim2 ,eim uncorrect test);
    复制代码
    输入eim2 命令验证:
    11912.jpg


    从上面的log 可知,已经按照预期的触发了不可纠正ECC错误,对应的地址和上面的单bit 一场的地址是相同的原因对应的是中断向量表的地址。



    /* 资料分割线 */

    测试代码已上传至如下路径(https://gitee.com/andeyqi/rt-thread/tree/master/bsp/s32k14x
    S32K1xx ECC 错误处理.pdf (598.13 KB, 下载次数: 0)
    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-27 23:28 , Processed in 0.112490 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表