2024/08/22

NXP [S32K14x 功能安全特性] EIM/ERM 功能驗證

NXP S32K14x 作為一車規級的晶片,晶片本身是支援功能安全相關的特性,晶片的功能安全等級是ASIL-B等級。
從以下功能安全手冊的描述可以看到S32K14x 晶片的FLASH/SRAM 是支援硬體ECC校驗機制,支援 SEC/DED 演算法修正1bit 錯誤及多bit 錯誤檢出機制。


S32K14x 有4K FlexRAM 位在 1400_0000h ~ 1400_0FFFh
S32K11x 僅有 2K FlexRAM 位在 1400_0000h ~ 1400_07FFh 
以及 1K SRAM 位於 1FFF_FC00h ~ 1FFF_FFFFh

ECC 功能如果軟體要驗證的話,正常情況下是不會觸發bit 錯誤異常的,正常情況這個異常是很難觸發的,軟體如果要驗證這個功能需要怎麼觸發驗證呢,EIM是個錯誤注入模組可以對數據線及ECC碼進行注入錯誤驗證,確保ECC功能的安全可靠,以下是EIM模組的框體,從框圖能夠看出EIM 模組可以控制對應的bit 讀取的資料發生位元反轉。
從如下框圖也可以看出來CPU 透過LMEM(Local Memory Controller) 單元存取RAM 資源中間是途經EIM模組,從而EIM 完成對應的路徑的注錯驗證診斷RAM ECC 功能。

EIM 能夠注入錯誤,注入的錯誤如何被檢出報告,S32K內部還有個ERM模組這個模組能檢出SRAM 是否發生了ECC 錯誤及ECC錯誤的類型,並具有中斷信號輸出通知到CORE 的能力, ERM 的介紹如下:

  • EIM 單bit 錯誤注入驗證
我們使用SDK 的配置接口,使能配置EIM/ERM 透過EIM 注入1bit 錯誤,然後讀取ERM 狀態寄存器判斷注入錯誤狀態是否成功是否按照預期的檢測出ECC錯誤,對應的測試代碼如下:
eim config:
/**
 * @page misra_violations MISRA-C:2012 violations
 *
 * @section [global]
 * Violates MISRA 2012 Advisory Rule 8.7, External variable could be made static.
 * The external variables will be used in other source files in application code.
 *
 */

/* Channel configurations */
const eim_user_channel_config_t eim_InitConfig0[EIM_CHANNEL_COUNT0] =
{
    /* Channel configuration 0 */
    {
        .channel = 0U,
        .checkBitMask = 0U,
        .dataMask = 1U,
        .enable = true
    }
};

erm config:

/* Interrupt configurations */

/* Interrupt configuration 0 */
const erm_interrupt_config_t erm_Interrupt0 =
{
    .enableSingleCorrection = true,
    .enableNonCorrectable = true
};

/* ERM configurations */

/* ERM configuration 0 */
const erm_user_config_t erm_InitConfig0[ERM_CHANNEL_COUNT0] =
{
    /* Channel configuration 0 */
    {
        .channel = 0U,
        .interruptCfg = &erm_Interrupt0
    }
};

測試程式碼:

#include <stdio.h>

#include <rtthread.h>

#include <rtdevice.h>

#include <board.h>




int eim_correct(void)

{

    uint32_t test;

    uint32_t addr;

    erm_ecc_event_t retValue = ERM_EVENT_NONE;


    /* Initialize address used to test */

    *(uint32_t *)0x1FFFFFF0U = 0U;


    /* Hardware initialization */

    /* Initial for ERM module */

    ERM_DRV_Init(INST_ERM_CONFIG_1, ERM_CHANNEL_COUNT0, erm_InitConfig0);

    /* Initial for EIM module */

    EIM_DRV_Init(INST_EIM_CONFIG_1, EIM_CHANNEL_COUNT0, eim_InitConfig0);


    /* Read any address on RAM  */

    /* Enable read region Ram (0x1FFF8000 - 0x20006FFF) when debug equal Flash */

    test = *(uint32_t *)0x1FFFFFF0U;

    (void)test;


    /* Deinit EIM module */

    EIM_DRV_Deinit(INST_EIM_CONFIG_1);


    /* Check error and get address which EIM injection error */

    retValue = ERM_DRV_GetErrorDetail(INST_ERM_CONFIG_1, 0U, &addr);


    rt_kprintf("erm status %s error addr is 0x%08x\n",\

                retValue == ERM_EVENT_NONE ? "ERM_EVENT_NONE" :\

                (retValue == ERM_EVENT_SINGLE_BIT ? "ERM_EVENT_SINGLE_BIT" :\

                (retValue == ERM_EVENT_NON_CORRECTABLE ? "ERM_EVENT_NON_CORRECTABLE" : "ERM_EVENT_NONE")),\

                addr);


    return 0;

}

MSH_CMD_EXPORT_ALIAS(eim_correct, eim1 ,eim correct test);

執行上述測試程式碼,輸入eim1 測試指令,ERM 模組已經按照預期的偵測到 Single bit 錯誤。

  • ERM 單bit 錯誤中斷驗證

在上述程式碼的基礎上追加ERM 中斷啟用,查看中斷函數能否被正常執行,對應程式碼修改如下:


輸入測試命令,中斷處理函數內部已經捕獲但位元錯誤並清除掉該錯誤標誌。
如果看的仔細會發現中斷的形式EPM報出來的位址和直接查詢狀態時對應的位址時不同的,中斷的方式我們用來triger 讀取的是0x1FFFFFF0U 的測試位址,為什麼中斷報出來的是0x1fff00f0,這是因為觸發中斷的時候回去讀取中斷向量表,我們的中斷向量表是在SRAM裡,我們debug 查下0x1fff00f0儲存的是不是對應的中斷函數。透過下圖可知道確實是中斷向量,所以EPM 記錄的是最後一次觸發的一場位址。
  • EIM 多bit 錯誤注入驗證
驗證完了單bit ECC異常,我們修改EIM 的配置往ECC區域注入多bit 錯誤 看看是否也會跟上面一樣觸發中斷。
修改EIM 配置:
const eim_user_channel_config_t eim_InitConfig1[EIM_CHANNEL_COUNT1] =
{
    /* Channel configuration 0 */
    {
        .channel = 0U,
        .checkBitMask = 3U,
        .dataMask = 0U,
        .enable = true
    }
};

 新增如下測試指令eim2:

/*!

  \brief The ERM_ISR funcion invert state Led

  *- Clear event when have notify interrupt

*/

void erm_doublebit_isr(void)

{

    uint32_t addr;

    erm_ecc_event_t retValue = ERM_EVENT_NONE;


    /* Deinit EIM module */

    EIM_DRV_Deinit(INST_EIM_CONFIG_1);


    /* Check error and get address which EIM injection error */

    retValue = ERM_DRV_GetErrorDetail(INST_ERM_CONFIG_1, 0U, &addr);


    rt_kprintf("erm isr status %s error addr is 0x%08x\n",\

                retValue == ERM_EVENT_NONE ? "ERM_EVENT_NONE" :\

                (retValue == ERM_EVENT_SINGLE_BIT ? "ERM_EVENT_SINGLE_BIT" :\

                (retValue == ERM_EVENT_NON_CORRECTABLE ? "ERM_EVENT_NON_CORRECTABLE" : "ERM_EVENT_NONE")),\

                addr);

    /* The interrupt notification will be cleared.*/

    ERM_DRV_ClearEvent(INST_ERM_CONFIG_1, 0U, ERM_EVENT_NON_CORRECTABLE);

}


int eim_double_bit(void)

{

    uint32_t test;

    uint32_t addr;

    erm_ecc_event_t retValue = ERM_EVENT_NONE;


    /* Initialize address used to test */

    *(uint32_t *)0x1FFFFFF0U = 0U;


    /* Install IRQ Handlers for ERM and SysTick */

    INT_SYS_InstallHandler(ERM_double_fault_IRQn, erm_doublebit_isr, (isr_t *)0);

    /* Enable ERM IRQ */

    INT_SYS_EnableIRQ(ERM_double_fault_IRQn);


    /* Hardware initialization */

    /* Initial for ERM module */

    ERM_DRV_Init(INST_ERM_CONFIG_1, ERM_CHANNEL_COUNT0, erm_InitConfig0);

    /* Initial for EIM module */

    EIM_DRV_Init(INST_EIM_CONFIG_1, EIM_CHANNEL_COUNT1, eim_InitConfig1);


    /* Read any address on RAM  */

    /* Enable read region Ram (0x1FFF8000 - 0x20006FFF) when debug equal Flash */

    test = *(uint32_t *)0x1FFFFFF0U;

    (void)test;

 

    /* Deinit EIM module */

    EIM_DRV_Deinit(INST_EIM_CONFIG_1);


    /* Check error and get address which EIM injection error */

    retValue = ERM_DRV_GetErrorDetail(INST_ERM_CONFIG_1, 0U, &addr);


    rt_kprintf("erm status %s error addr is 0x%08x\n",\

                retValue == ERM_EVENT_NONE ? "ERM_EVENT_NONE" :\

                (retValue == ERM_EVENT_SINGLE_BIT ? "ERM_EVENT_SINGLE_BIT" :\

                (retValue == ERM_EVENT_NON_CORRECTABLE ? "ERM_EVENT_NON_CORRECTABLE" : "ERM_EVENT_NONE")),\

                addr);


    return 0;

}

MSH_CMD_EXPORT_ALIAS(eim_double_bit, eim2 ,eim uncorrect test);

輸入eim2 指令驗證:

從上面的log 可知,已經按照預期的觸發了不可糾正ECC錯誤,對應的地址和上面的 單bit異常 的地址是相同的原因 是中斷向量表的地址相同。

--
*** ref : https://www.nxpic.org.cn/module/forum/thread-802634-1-1.html ***

沒有留言:

張貼留言