TDA4 功能安全模块SDL2

文章详细介绍了TIJ784S4芯片中ESM(错误信号监测)模块的功能,包括对MAIN、MCU、WKUP三个域的错误监测,以及中断和PIN脚反馈方式。通过代码示例展示了如何配置参数以启用和设置错误事件的优先级。此外,还提到了在实际项目中遇到的与datasheet不符的问题,以及针对这些问题的解决策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ESM

在之前的TDA4 SDL功能安全介绍中说道ESM是一个非常重要的模块。但是个人理解不够深刻,在加上最近项目的需要又一次重新深入理解给大家详细介绍这个模块。

模块介绍

ESM可以监测MAIN,MCU,WKUP三个域所发生的支持错误。具体所支持的事件如下:

Mcal\pdk\packages\ti\csl\soc\j784s4\src\cslr_intr_mcu_esm0.h //MCU域支持事件
Mcal\pdk\packages\ti\csl\soc\j784s4\src\cslr_intr_wkup_esm0.h //WAKEUP域支持事件
Mcal\pdk\packages\ti\csl\soc\j784s4\src\cslr_intr_esm0.h //MAIN域支持

监测的反馈方式之前介绍过分为:中断或者pin脚方式。
中断分为main,wakeup,mcu三种域类型,每种类型又分为high priority,low priority,config三种功能。

highlowconfig
WKUP141140142
MCU9998100
MAIN494853
void SDL_ESM_hiInterruptHandler_MCU (uintptr_t arg);
void SDL_ESM_hiInterruptHandler_WKUP (uintptr_t arg);
void SDL_ESM_hiInterruptHandler_MAIN (uintptr_t arg);
void SDL_ESM_loInterruptHandler_MCU (uintptr_t arg);
void SDL_ESM_loInterruptHandler_WKUP(uintptr_t arg);
void SDL_ESM_loInterruptHandler_MAIN (uintptr_t arg);
void SDL_ESM_configInterruptHandler_MCU(uintptr_t arg);
void SDL_ESM_configInterruptHandler_WKUP(uintptr_t arg);
void SDL_ESM_configInterruptHandler_MAIN(uintptr_t arg);

Error Pin又分为两种:MCU_SAFETY_ERROR和SOC_SAFETY_ERROR。WKUP Domain没有任何输出引脚。
在这里插入图片描述
这里被TI给坑了,J784S4如果按照上面参考根本不对,需要参考J721E的datasheet,发现调试了半天wdg demo是好的,我自己是不好的。发现这块是有区别的,需要自己手写代码,参考下面代码!!!下面是J721E上面是J784S4。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

代码详解

参数配置

.esmErrorConfig: 0代表group,3代表index。group可以参考下图的数组排列是个4*8的数组,每32个bit代表一个group。index代表每一个bit,bit的排列方式最低位为0,最高位为31。

.enableBitmap: 使能的bit就要参考最开始的.h文件自己定义所筛序,使能对应的事件。

.priorityBitmap: 0为低优先级,1为高优先级。

.errorpinBitmap: 代表是否使能pin脚输出。

static SDL_ESM_config CCM_Test_esmInitConfig_MCU =
{
    .esmErrorConfig = {0u, 3u}, /* Self test error config */

    .enableBitmap = {
                     0xffffffffu, 0xff0fffffu, 0x7fffffffu, 0x00000007u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,    
                    },
     /**< All events enable: except timer and self test  events, and Main ESM output */
    /* Temporarily disabling vim compare error as well*/
    .priorityBitmap = {
                       0xffffffffu, 0xff0fffffu, 0x7fffffffu, 0x00000007u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                      },
    /**< All events high priority: except timer, selftest error events, and Main ESM output */
    .errorpinBitmap = {
                       0xffffffffu, 0xff0fffffu, 0x7fffffffu, 0x00000007u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                      },
    /**< All events high priority: except timer, selftest error events, and Main ESM output */
};
static SDL_ESM_config CCM_Test_esmInitConfig_WKUP =
{
    .esmErrorConfig = {0u, 0u}, /* Self test error config */
    .enableBitmap = {
                     0xffffffffu, 0x00180003u, 0xffffffffu, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                    },
     /**< All events enable: except clkstop events for unused clocks */
    .priorityBitmap = {
                       0xfffffcffu, 0x00180003u, 0xffffffffu, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                      },
    /**< All events high priority: except clkstop events for unused clocks,
     *   and make VTM WKUP_VTM0_THERM_LVL_GT_TH1_INTR_0 and
     *   WKUP_VTM0_THERM_LVL_LT_TH0_INTR_0 events low priority */
    .errorpinBitmap = {
                       0xfffffcffu, 0x00180003u, 0xffffffffu, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                      },
    /**< All events high priority: except clkstop for unused clocks
     *   and make VTM WKUP_VTM0_THERM_LVL_GT_TH1_INTR_0 and
     *   WKUP_VTM0_THERM_LVL_LT_TH0_INTR_0 events not output to pin */
};
static SDL_ESM_config CCM_Test_esmInitConfig_MAIN =
{
    .esmErrorConfig = {0u, 0u}, /* Self test error config 20*32+8=648 ifconfig self test ecc ccm esm call back not execute but interrupt normal*/
    .enableBitmap = {
                     0x00000000u, 0xffffffdbu, 0x7fffffffu, 0xffffffffu,
                     0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
                     0xffffffffu, 0xfffffffbu, 0xffffffffu, 0xffffffffu,
                     0xffff7fffu, 0xffffffffu, 0xffffffffu, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     #ifdef ESM_ENABLE_MAIN_CCM_INTERRUT
                     0x0007c1f0u, 0x000001f0u, 0x00000000u, 0x00000000u, //644~648 654~658 676~680
                     #else
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, //644~648 654~658 676~680
                     #endif
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                     0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,                     
                    },
     /**< All events enable: except clkstop events for unused clocks
      *   and PCIE events */
    .priorityBitmap = {
                         0x00000000u, 0xffffffdbu, 0x7fffffffu, 0xffffffffu,
                         0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
                         0xffffffffu, 0xfffffffbu, 0xffffffffu, 0xffffffffu,
                         0xffff7fffu, 0xffffffffu, 0xffffffffu, 0x00000000u,
                         0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                         #ifdef ESM_ENABLE_MAIN_CCM_INTERRUT
                         0x0007c1f0u, 0x000001f0u, 0x00000000u, 0x00000000u, //644~648 654~658 676~680
                         #else
                         0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, //644~648 654~658 676~680
                         #endif
                         0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                         0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 
                      },
    /**< All events high priority: except clkstop events for unused clocks
     *   and PCIE events */
    .errorpinBitmap = {
                       0x00000000u, 0xffffffdbu, 0x7fffffffu, 0xffffffffu,
                       0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu,
                       0xffffffffu, 0xfffffffbu, 0xffffffffu, 0xffffffffu,
                       0xffff7fffu, 0xffffffffu, 0xffffffffu, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       #ifdef ESM_ENABLE_MAIN_CCM_INTERRUT
                       0x0007c1f0u, 0x000001f0u, 0x00000000u, 0x00000000u, //644~648 654~658 676~680
                       #else
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, //644~648 654~658 676~680
                       #endif
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u,
                       0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u, 
                      },
 };

中断配置与处理

high priority和low priority最终都会调用同一个中断函数处理。

static void SDL_ESM_processInterruptSource(uint32_t esmInstBaseAddr,
                                           SDL_ESM_IntType esmIntType,
                                           uint32_t intSrc)
{
    SDL_ESM_Instance_t *SDL_ESM_instance;
    SDL_ESM_Inst esmInstType;
    uint32_t groupNumber, intIndex;
    int32_t isHandled = (int32_t)FLAG_NO;
    SDL_ESM_selectEsmInstFromAddr(esmInstBaseAddr,
                                  &esmInstType,
                                  &SDL_ESM_instance);
    if (intSrc != NO_EVENT_VALUE) {
        if (intSrc < (BITS_PER_WORD*SDL_ESM_MAX_EVENT_MAP_NUM_WORDS)) {
            SDL_ESM_getGroupNumberIndex(intSrc, &groupNumber, &intIndex);
            if((SDL_ESM_instance->esmInitConfig.enableBitmap[groupNumber]
               & (((uint32_t)MASK_BIT)<<intIndex)) != INVALID_BIT) {
                /* Check if this is due to self test */
                if((groupNumber
                    == SDL_ESM_instance->esmInitConfig.esmErrorConfig.groupNumber) &&
                   (intIndex ==  SDL_ESM_instance->esmInitConfig.esmErrorConfig.bitNumber)){
                    SDL_ESM_selfTestCallback(SDL_ESM_instance);
                    isHandled = (int32_t)FLAG_YES;
                }
                else if((SDL_ESM_instance->eccenableBitmap[groupNumber]
                        & (((uint32_t)MASK_BIT)<<intIndex)) != INVALID_BIT) {
                    isHandled = SDL_ESM_instance->eccCallBackFunction(esmInstType, esmIntType,
                                                                      groupNumber, intIndex,
                                                                      intSrc, SDL_ESM_instance->eccCallBackFunctionArg);
                }
                else if((SDL_ESM_instance->ccmenableBitmap[groupNumber]
                        & (((uint32_t)MASK_BIT)<<intIndex)) != INVALID_BIT) {
                    isHandled = SDL_ESM_instance->CCMCallBackFunction(esmInstType, esmIntType,
                                                                      groupNumber, intIndex,
                                                                      intSrc, SDL_ESM_instance->ccmCallBackFunctionArg);
                }
                else
                {
                    isHandled = (int32_t)FLAG_NO;
                }
            }
            if (isHandled != (int32_t)FLAG_YES)
            {
                (void)SDL_ESM_instance->callback(esmInstType, esmIntType,
                                                 groupNumber, intIndex,
                                                 intSrc, SDL_ESM_instance->arg);
            }
            (void)SDL_ESM_clearIntrStatus(esmInstBaseAddr, intSrc);
        }
    }
    return;
}

SDL_ESM_selfTestCallback是根据.esmErrorConfig参数决定,认为这个错误的产生是我们自己模拟出来不需要任何处理与提示。
下面这两个是特殊处理的模块:

eccCallBackFunction是根据ECC模块对ESM初始化决定的。如果不初始化的情况下产生这个错误会导致进入data abort异常,这点不难理解。

SDL_ECC_initEsm(SDL_ESM_INST_MAIN_ESM0);
SDL_ECC_initEsm(SDL_ESM_INST_MCU_ESM0);

CCMCallBackFunction是根据CCM模块对ESM初始化决定的同上面ECC。

SDL_CCM_init(SDL_CCM_MCU_R5F0);

如果是不属于上述三种的错误将会走进一个通用的错误处理,也就是ESM模块本身初始化时所注册的函数。打印出来的groupChannel和index参考上面描述的。

int32_t SDL_ESM_applicationCallbackFunction(SDL_ESM_Inst esmInst,
                                            SDL_ESM_IntType esmIntrType,
                                            uint32_t grpChannel,
                                            uint32_t index,
                                            uint32_t intSrc,
                                            uintptr_t *arg)
{

    int32_t retVal = 0;
    
    UART_printf("ESM Call back function called : instType 0x%x, intType 0x%x, " \
                "grpChannel 0x%x, index 0x%x, intSrc 0x%x\n",
                esmInst, esmIntrType, grpChannel, index, intSrc);

    CddCCM_Int_Clear(intSrc);

    return retVal;
}

我们可以调用API模拟注入错误中断,通过下面函数。

SDL_ESM_runESMInjectInstance(SDL_ESM_INST_MCU_ESM0, 1, 3);

PIN脚配置与处理

MCU1_0使能PIN脚错误监测。

void WdgApp_EnableESMErrorPin(void)
{
    uint32 regVal;

    /* MCU_SAFETY_ERRORn PAD configuration */
    /* Unlock lock key registers for Partition 7: IO PAD
       configuration registers in WKUP_CTRL_MMR */
    /* write Partition 7 Lock Key 0 Register */
    LLD_REG32_WR(CSL_WKUP_CTRL_MMR0_CFG0_BASE + 0x1D008, 0x68EF3490);
    /* write Partition 7 Lock Key 1 Register */
    LLD_REG32_WR(CSL_WKUP_CTRL_MMR0_CFG0_BASE + 0x1D00C, 0xD172BC5A);
    /* Check for unlock */
    regVal = LLD_REG32_RD(CSL_WKUP_CTRL_MMR0_CFG0_BASE + 0x1D008);
    while ((regVal & 0x1) != 0x1U)
    {
        regVal = LLD_REG32_RD(CSL_WKUP_CTRL_MMR0_CFG0_BASE + 0x1D008);
    }
    /* Unlocking done */

    regVal = LLD_REG32_RD(CSL_WKUP_CTRL_MMR0_CFG0_BASE + 0x1C110U);
    regVal |= 0x00000U;
    LLD_REG32_WR(CSL_WKUP_CTRL_MMR0_CFG0_BASE + 0x1C110U, regVal);

    return;
}

测试修改wdg的超时时间,900ms为启动时间,剩下2s恰好为超时时间,可以看到MCU_SAFETY_ERROR一直持续拉低。
在这里插入图片描述

在这里插入图片描述
当产生错误的时候中断回掉之后可以通过LLD_ESMResetErrPin(ESM_INSTANCE);将错误取消拉高。

void WdgApp_ESMIsr(uintptr_t handle)
{
    uint32 intrStatus;
    RTIDwwdGetStatus(WdgApp_RtiInstance, &intrStatus);
    if ((HW_GET_FIELD(intrStatus, RTI_RTIWDSTATUS_DWDST) != 1U) ||
        (HW_GET_FIELD(intrStatus, RTI_RTIWDSTATUS_DWWD_ST) != 1U))
    {
        WdgApp_TestPassed = E_NOT_OK;
    }
    else
    {
        WdgApp_TestPassed = E_OK;
    }
    RTIDwwdClearStatus(WdgApp_RtiInstance, intrStatus);
    LLD_ESMClearIntrStatus(ESM_INSTANCE, ESM_ERR_SIG);
    LLD_ESMClearIntrStatus(WKUP_ESM_INSTANCE, WKUP_ESM_ERR_SIG);


    /* Reset error pin if interrupt mode */
    if (WdgApp_UserInput == 0U)
    {
        LLD_ESMResetErrPin(ESM_INSTANCE);
    }

    WdgApp_IsrFlag = 1U;
}

结语

功能安全后续也只挑几个项目相关的某块讲解,后续会更新有关安全启动的文章。最近也一直在整理安全启动的资料,里面东西还是很多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值