/********************************************************************************************************************** * \file MTU_MBIST.c * \copyright Copyright (C) Infineon Technologies AG 2019 * * Use of this file is subject to the terms of use agreed between (i) you or the company in which ordinary course of * business you are acting and (ii) Infineon Technologies AG or its licensees. If and as long as no such terms of use * are agreed, use of this file is subject to following: * * Boost Software License - Version 1.0 - August 17th, 2003 * * Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and * accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, * and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the * Software is furnished to do so, all subject to the following: * * The copyright notices in the Software and this entire statement, including the above license grant, this restriction * and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all * derivative works of the Software, unless such copies or derivative works are solely in the form of * machine-executable object code generated by a source language processor. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. *********************************************************************************************************************/ /*********************************************************************************************************************/ /*-----------------------------------------------------Includes------------------------------------------------------*/ /*********************************************************************************************************************/ # include "Platform_Types.h" #include "MTU_MBIST.h" #include "IfxMtu_reg.h" /*********************************************************************************************************************/ /*----------------------------------------------------- Macros ------------------------------------------------------*/ /*********************************************************************************************************************/ #define MBIST_TEST_RANGE_ENABLE 0x1 /* Enable range mode */ #define MBIST_TEST_RANGE_DISABLE 0x0 /* Disable range mode: single address mode */ #define MBIST_TEST_LOWER_RANGE_LIMIT 0x00 /* Lower address range limit */ #define MBIST_TEST_HIGHER_RANGE_LIMIT 0xFF /* Higher address range limit */ /* MTU MBIST Error flags */ #define MTU_CORRECTABLE_ERROR_FLAG ((unsigned int)IFX_MTU_MC_ECCD_CERR_MSK << IFX_MTU_MC_ECCD_CERR_OFF) #define MTU_UNCORRECTABLE_ERROR_FLAG ((unsigned int)IFX_MTU_MC_ECCD_UERR_MSK << IFX_MTU_MC_ECCD_UERR_OFF) #define MTU_ADDRESS_ERROR_FLAG ((unsigned int)IFX_MTU_MC_ECCD_AERR_MSK << IFX_MTU_MC_ECCD_AERR_OFF) #define SRAM_ADDRESS_INJECTED_ERR 0x1F /* SRAM address where to inject the error */ #define MTU_CLEAR_FAULTSTS_OPERR0_MSK 0x3E /* Mask for clearing bit 0 of OPERR bitfield * in MCi_FAULTSTS (i=0-95) register */ /*********************************************************************************************************************/ /*--------------------------------------------------Global variables-------------------------------------------------*/ /*********************************************************************************************************************/ /* Please set this variable to TRUE, if an error injection is needed (only a correctable error is supported) */ #define MTU_ERR_INJECTION_ENABLE (0) /*********************************************************************************************************************/ /*--------------------------------------------------Function Prototypes----------------------------------------------*/ /*********************************************************************************************************************/ static void read_MTU_MBIST_RDBFL(IfxMtu_MbistSel mbistSel, uint32 rdflCnt, uint16 *val); static void write_MTU_MBIST_RDBFL(IfxMtu_MbistSel mbistSel, uint32 rdflCnt, uint16 val); static uint32 get_MTU_MBIST_Errors(IfxMtu_MbistSel mbistSel); static void clear_MTU_MBIST_Errors(IfxMtu_MbistSel mbistSel); /*********************************************************************************************************************/ /*------------------------------------------------Function Implementations-------------------------------------------*/ /*********************************************************************************************************************/ /* This function initializes and tests an SRAM memory using MBIST */ uint8 test_MTU_MBIST(IfxMtu_MbistSel mbistSel, uint8 uplimit, uint8 lolimit) { uint16 errAddr = 0; uint8 result = 0; /* Enable MTU clock */ IfxMtu_enableModule(); /* Check if any error flag is set. * After any System Reset: For each and every SSH in the system, the UCE alarm status in the SMU, the ECCD.UCERR * (Consequently also SERR) and the FAULTSTS.OPERR[0] are set. */ if(get_MTU_MBIST_Errors(mbistSel)) { /* Clear the alarm status flags to enable a correct error tracking */ clear_MTU_MBIST_Errors(mbistSel); } /* Initialize the selected SRAM */ //IfxMtu_clearSram(mbistSel); /* Error injection is selected */ # if (MTU_ERR_INJECTION_ENABLE == 1) { /* Select MBIST Memory Controller */ uint16 password = 0, dataVal; uint8 isEndInitEnabled = 0; password = IfxScuWdt_getSafetyWatchdogPassword(); /* Check if the EndInit is already cleared, if not, clear it */ if (IfxScuWdt_getSafetyWatchdogEndInit() == 1U) { /* Clear EndInit */ IfxScuWdt_clearSafetyEndinit(password); isEndInitEnabled = 1; } /* Enable MBIST Memory Controller */ IfxMtu_enableMbistShell(mbistSel); /* For auto-init memories: wait for the end of the clear operation */ while (IfxMtu_isAutoInitRunning(mbistSel) != 0) {} /* Read a single memory location (for example, address: 0x1F) */ IfxMtu_readSramAddress(mbistSel, SRAM_ADDRESS_INJECTED_ERR); /* Get the RDBFL(0) value */ read_MTU_MBIST_RDBFL(mbistSel, 0, &dataVal); /* Inject a correctable error (single bit error): * Only one bit should be flipped (the first bit is chosen in this example) */ /* If the first bit is 1 */ if(dataVal & 0x0001 == 0x0001) { /* Set first bit to 0 */ dataVal &= 0xfffe; } else /* The first bit is 0 */ { /* Set first bit to 1 */ dataVal |= 0x0001; } /* Update the RDBFL(0) value with the injected error */ write_MTU_MBIST_RDBFL(mbistSel, 0, dataVal); /* Inject the error: Write to a single memory location address (should be the same address read: 0x1F) */ IfxMtu_writeSramAddress(mbistSel, SRAM_ADDRESS_INJECTED_ERR); /* Disable MBIST Memory Controller */ IfxMtu_disableMbistShell(mbistSel); /* Restore the EndInit state */ if (isEndInitEnabled == 1) { /* Set EndInit protection */ IfxScuWdt_setSafetyEndinit(password); } } #endif // end of MTU_ERR_INJECTION_ENABLE /* Run the Non-Destructive Test (NDT) */ result = IfxMtu_runNonDestructiveInversionTest((IfxMtu_MbistSel)mbistSel, MBIST_TEST_RANGE_ENABLE, uplimit, lolimit, &errAddr); /* Check the test result */ /* No error has occurred */ if (result == 0) { /* If error injection is enabled */ #if (MTU_ERR_INJECTION_ENABLE == 1) { /* An error has been injected and was not detected */ while (1); // for development verification only, do not return } #else { /* No error was detected since nothing is injected */ } #endif // end of MTU_ERR_INJECTION_ENABLE } else /* An error is detected */ { /* If error injection is enabled */ #if (MTU_ERR_INJECTION_ENABLE == 1) { /* Check if the correctable error is detected */ if (((get_MTU_MBIST_Errors(mbistSel) & MTU_CORRECTABLE_ERROR_FLAG) != 0) && errAddr == SRAM_ADDRESS_INJECTED_ERR) { /* A correctable error has been injected and the test has detected it */ while (1); // for development verification only, do not return } else { /* A correctable error has been injected and another error was detected */ while (1); // for development verification only, do not return } } #else { /* MBIST or SFF test failed, no extra action here */ } #endif // end of MTU_ERR_INJECTION_ENABLE } return result; } #if (MTU_ERR_INJECTION_ENABLE == 1) /* Read the memory value of a specific RDBFL register */ static void read_MTU_MBIST_RDBFL(IfxMtu_MbistSel mbistSel, uint32 rdflCnt, uint16 *val) { Ifx_MTU_MC *mc = (Ifx_MTU_MC *)(IFXMTU_MC_ADDRESS_BASE + 0x100 * mbistSel); *val = mc->RDBFL[rdflCnt].U; } /* Write to a specific RDBFL register */ static void write_MTU_MBIST_RDBFL(IfxMtu_MbistSel mbistSel, uint32 rdflCnt, uint16 val) { Ifx_MTU_MC *mc = (Ifx_MTU_MC *)(IFXMTU_MC_ADDRESS_BASE + 0x100 * mbistSel); mc->RDBFL[rdflCnt].U = val; } #endif /* Get MBIST error flags of a specific memory */ static uint32 get_MTU_MBIST_Errors(IfxMtu_MbistSel mbistSel) { Ifx_MTU_MC *mc = (Ifx_MTU_MC *)(IFXMTU_MC_ADDRESS_BASE + 0x100 * mbistSel); return (uint32)(mc->ECCD.U & (IFXMTU_ERROR_FLAGS_MASK)); } /* Clear MCi_ECCD and MCi_FAULTSTS (i=0-95) error flags of a specific memory raised by a System Reset */ static void clear_MTU_MBIST_Errors(IfxMtu_MbistSel mbistSel) { Ifx_MTU_MC *mc = &MODULE_MTU.MC[mbistSel]; uint16 password = IfxScuWdt_getSafetyWatchdogPassword(); uint8 isEndInitEnabled = 0; /* Check if the EndInit is already cleared: * if not, clear it to enable writes on MCi_FAULTST (i=0-95) register of a specific memory */ if (IfxScuWdt_getSafetyWatchdogEndInit() == 1U) { /* Clear EndInit */ IfxScuWdt_clearSafetyEndinit(password); isEndInitEnabled = 1; } mc->ECCD.B.SERR = 0; /* Error Detected flag */ mc->ECCD.B.UCERR = 0; /* UnCorrectable Error (UCE) alarm flag */ mc->FAULTSTS.B.OPERR &= MTU_CLEAR_FAULTSTS_OPERR0_MSK; /* SSH Critical Operation Error flags: clear * bit 0, set by any System Reset */ /* Restore the EndInit state */ if (isEndInitEnabled == 1) { /* Set EndInit Watchdog (to prevent Watchdog Time Out) */ IfxScuWdt_setSafetyEndinit(password); } IfxMtu_clearErrorTracking(mbistSel); /* Clear the error tracking registers (ETRR) */ }