1 前言
前面已经将S32K3的与功能安全相关的硬件外设大致都梳理了一遍,前面在Safety简介中提到了NXP针对S32K3不同的安全机制共发布了免费的RTD和SPD,以及收费的SAF和SCST,如果恰逢你手头拮据,只能用免费的软件,而RTD和SPD又是两个独立的软件包,那么怎样将二者集成一下呢?
首先下载SPD包并安装,有如下内容:
我们需要用到的是SafetyBase, eMcem, Bist这三个模块。其中SafetyBase没啥东西,就是一些头文件,Bist模块实现了STCU2 BIST的功能,eMcem模块实现了FCCU, ERM, EIM, XBIC, DCM的功能。
2 EB的配置
首先将SafetyBase, eMcem, Bist这三个模块对应的文件夹复制到EB的安装目录plugins下,让EB可以找到相关的模块。然后就是在自己的EB工程中添加这三个模块,如下:
这样EB这边的配置就完成了。
3 S32DS的配置
对于S32DS这边的配置,就更简单了,把EB生成的代码以及RTD,SPD的源代码加入到自己的工程里面去,然后还需要修改一下链接文件,具体修改的地方如下:
4 代码的集成
接下来就是怎样在代码中集成SPD了,如果需要用SPD来实现一个基本的程序设计,那么在理想情况下,软件设计的基本流程如下:
下面贴出SPD初始化的代码:
void Spd_Init(void)
{
Mcu_ResetType ResetReason = MCU_RESET_UNDEFINED;
ResetReason = Mcu_GetResetReason();
switch(ResetReason)
{
case MCU_POWER_ON_RESET:
break;
//.....
default:
break;
}
/****************************************************************************
* if BIST(STCU) is not run yet, run LBIST and MBIST,
* this will trigger a ST_DONE functional reset.
* BIST must run with PLL enabled and CPU run in full-performance mode.
* BIST must run with FCCU faults detection disabled.
***************************************************************************/
//#define DEMO_ENABLE_BIST
#ifdef DEMO_ENABLE_BIST
Bist_StatusType bistStatus;
uint32 stcuStatus;
Std_ReturnType retStatus;
Bist_LBistRDListType Bist_LBistRDList = 0U;
Bist_MBistRDListType Bist_MBistRDList = 0U;
bistStatus = Bist_GetExecStatus(BIST_SAFETYBOOT_CFG);
if( bistStatus != BIST_OK )
{
if(bistStatus == BIST_ERROR)
{
/* Reads STCU ERR_STAT register to identify what HW error occured */
stcuStatus = Bist_GetRawErrorStatus();
(void) stcuStatus;
}
else if(bistStatus == BIST_FAILED)
{
/* Analyze which reset domain is failing */
retStatus = Bist_GetFailRDs ( &Bist_LBistRDList, &Bist_MBistRDList );
(void) retStatus;
}
else if(bistStatus == BIST_BUSY)
{
while( 1U ); /* Handle BIST HW busy state */
}
else if(bistStatus == BIST_NORUN)
{
/* Bist execution was not successfully performed due to HW hazard state. */
Bist_Run(BIST_SAFETYBOOT_CFG); /* Re-start execution */
}
else if(bistStatus == BIST_INTEGRITY_FAIL)
{
while( 1U ); /* Handle the integrity fail state */
}
}
#endif
/* enable MemManageFault, BusFault, UsageFault in SCB to use individual exception handler. Otherwise, the HardFault handler is used */
//S32_SCB->SHCSR |= (S32_SCB_SHCSR_MEMFAULTENA_MASK|S32_SCB_SHCSR_BUSFAULTENA_MASK|S32_SCB_SHCSR_USGFAULTENA_MASK);
/**************************************************/
/* eMcem example code */
/**************************************************/
/* User can get FCCU fault first if previous reset is FCCU FUNC Reset which is caused by certain FCCU fault */
eMcem_GetErrors( &faultContainer );
if(faultContainer.au32Faults[0] | faultContainer.au32Faults[1] | faultContainer.au32Faults[2])
{
printf("faultContainer = 0x%08X, 0x%08X, 0x%08X. \r\n", (unsigned int)faultContainer.au32Faults[0], (unsigned int)faultContainer.au32Faults[1], (unsigned int)faultContainer.au32Faults[2]);
}
/* Initialize eMcem */
if( eMcem_Init( &eMcem_Config_0 ) != (Std_ReturnType)E_OK )
{
/* Handle initialization failure */
printf("FCCU init failure.\r\n");
printf("DCMROD3=0x%08X, DCMROD4=0x%08X, DCMROD5=0x%08X.\r\n", (unsigned int)IP_DCM_GPR->DCMROD3, (unsigned int)IP_DCM_GPR->DCMROD4, (unsigned int)IP_DCM_GPR->DCMROD5);
printf("Trigger software destructive reset.\r\n");
while( 1U );
}
printf("FCCU init completed.\r\n");
}