This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS570LC4357: Programmable Built-In Self-Test (PBIST) Module

Part Number: TMS570LC4357
Other Parts Discussed in Thread: HALCOGEN,

Hello, I am looking for reference on how to perform PBIST self test. I see in technical reference manual, there is a statement which says 'Supports testing of PBIST ROM itself as well'. I wanted to perform PBIST self test and I am following the below steps. Always the test fails, need your support and guidance.

// Step 1:
// Disable PBIST internal clocks.
pbist_regs[PACT] = 0x0UL;

// Step 2:
// ROM clock source is GCLK1 divided by 4. PBIST will reset for 64 VBUS cycles
// Maximum PBIST ROM_CLK frequency supported is 82.5MHz.
// Memory self-test controller is disabled
sys_regs[MSTGCR] &= 0xFFFFFCF0UL;
sys_regs[MSTGCR] |= 0x00000205UL;

// Step 3:
// Global memory hardware initialization is disabled
sys_regs[MINITGCR] = 0x5UL;

// Step 4:
// Memory self-test controller is enabled
sys_regs[MSTGCR] &= 0xFFFFFFF0UL;
sys_regs[MSTGCR] |= 0xAUL;

// Step 5:
// Memory self-test run complete status: Memory self-test is not completed
sys_regs[MSTCGSTAT] = 0x1UL;

// Step 6:
// PBIST controller is enabled
sys_regs[MSINENA] = 0x1UL;

// Step 7:
// Wait for 64 VBUS clock cycles at least, based on HCLK to VCLK ratio
#define VBUS_CLK_CYCLES 64U
for (Uint32 index = 0UL; index < (VBUS_CLK_CYCLES + (VBUS_CLK_CYCLES * 1u)); index++);

// Step 8:
// Enable PBIST internal clocks.
pbist_regs[PACT] = 0x1UL;

// Step 9:
// CPU control of PBIST, setting this bit allows the host processor to
// configure the PBIST controller registers
pbist_regs[DLR] = 0x10UL;

// Step 10:
// TODO: Custom always fail algorithm, this will not use the ROM and just set a fail
// Ram Group Select: 0
// Return Data Select: 0
// Data Width Register: 2
// Sense Margin Select Register: 0
// Pipeline Latency Select: 0
// RAM Latency Select: 0
pbist_regs[RAMT] = 0x00002000UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE400UL) = 0x4C000001UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE440UL) = 0x00000075UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE404UL) = 0x4C000002UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE444UL) = 0x00000075UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE408UL) = 0x4C000003UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE448UL) = 0x00000075UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE40CUL) = 0x4C000004UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE44CUL) = 0x00000075UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE410UL) = 0x4C000005UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE450UL) = 0x00000075UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE414UL) = 0x4C000006UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE454UL) = 0x00000075UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE418UL) = 0x00000000UL;
*reinterpret_cast<volatile Uint32*>(0xFFFFE458UL) = 0x00000001UL;

// Step 11:
// TODO: Run PBIST
pbist_regs[RSVD] = 1UL;

// Step 12:
// Wait until memory self-test done is indicated
while ((sys_regs[MSTCGSTAT] & 0x1UL) != 0x1UL);

// Get the result
Bool ret_val = false;
if(is_test_passed())
    ret_val = true;

// Step 13:
// Disable PBIST clocks and ROM clock
pbist_regs[PACT] = 0x0UL;

// Step 14:
// Disable PBIST
sys_regs[MSTGCR] &= 0xFFFFFFF0UL;
sys_regs[MSTGCR] |= 0x5UL;

// Step 15:
return ret_val;

  • Below are the clock configurations:

    // Clocks
    #define GCLK1_FREQUENCY (180) // MHz
    #define HCLK_FREQUENCY (90) // MHz
    #define VCLK_FREQUENCY (90) // MHz
    #define VCLK2_FREQUENCY (90) // MHz
    #define VCLK3_FREQUENCY (90) // MHz
    #define RTI1CLK_FREQUENCY (90) // MHz

  • Hello,

    The PBIST ROM clock frequency is limited to 100MHz. 

    But your code configures the ROM Clock 180MHz:

    // Step 4:
    // Memory self-test controller is enabled
    sys_regs[MSTGCR] &= 0xFFFFFFF0UL;
    sys_regs[MSTGCR] |= 0xAUL;

  • Hi Wang, in Step 2, the frequency is set to 45MHz. In step 4, i am not altering the 'ROM_DIV' bits of the MSTGCR register and the bits value should retain to 2 right?

    Am i missing something?

    Regards,

    Kishore

  • Hello Kishore,

    You are right. The clock in your configuration is 45Mhz. 

    Did you use the code (startup.c) generated by HALCoGen?

  • Hi Wang,

    We are using TMS570LC4357, Revision B silicon. We are not able to get the PBIST code generated through halcogen for this controller, but we could generate for 3137 which we used it as reference.

    for this version of silicon, i believe we need not worry about the PBIST errata (PBIST#4). Mostly our code is based on startup.c code from halcogen tool.

    Regards,

    Kishore

  • Hello Wang, Happy New Year!!!

    did u get a chance to look into this query. both the PBIST and STC self tests are failing for me. But all other memory tests using these controllers are passing.

    Regards,

    Kishore

  • Hello Kishore,

    Yes, I just did a test, it works: the bit 0 of FSRF0 is set.

  • Thanks Wang. I made a mistake in check the status register. i was expecting the 'FSRF0' bit to be 0 instead of 1. This has solved PBIST self test issue.

    Coming to the STC self test, i am using the below steps. The processor is resetting after the step 7 executes. could you please check if the steps are ok?

    // Step 1:
    // Run a diagnostic check on the CPU self-test controller
    // Maximum STC clock rate support at 180 MHz GCLK1 is 90 MHz. Divide GCLK1 by 2 to achieve this
    // clock rate.
    stc_ctrl_regs[STCCLKDIV] = 0x02020000UL;

    // Step 2:
    // Clear CPU RST status bit in the System Exception Status Register in the system module
    volatile Uint32* sys1_esr = reinterpret_cast<volatile Uint32*>(SYS1_REG_BASE_ADDR + 0xE4U);
    *sys1_esr |= (1UL << 5U);

    // Step 3:
    // Select one test interval, restart self-test next time
    stc_ctrl_regs[STCGCR0] &= 0x0000F8FEUL;
    stc_ctrl_regs[STCGCR0] |= 0x00010001UL;

    // Step 4:
    // Maximum time-out period
    stc_ctrl_regs[STCTPR] = 0xFFFFFFFFUL;

    // Step 5:
    // Enable comparator self-check and stuck-at-0 fault insertion in CPU
    stc_ctrl_regs[STCSCSCR] &= 0xFFFFFFE0UL;
    stc_ctrl_regs[STCSCSCR] |= 0x0000001AUL;

    // Step 6:
    // wait for 64 VBUS clock cycles at least, based on HCLK to VCLK ratio
    #define VBUS_CLK_CYCLES 64U
    for (Uint32 index = 0UL; index < (VBUS_CLK_CYCLES + (VBUS_CLK_CYCLES * 1u)); index++);

    // Step 7:
    // Enable self-test, Select only Core1 for self-test, Self-test run is enabled
    stc_ctrl_regs[STCGCR1] &= 0xFFFFF0F0UL;
    stc_ctrl_regs[STCGCR1] |= 0x0000050AUL;

    // Step 8:
    // Keep CPU in standby mode.
    __asm__ __volatile__ (
    "WFI \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "DMB \n"
    "DSB \n"
    );

    Regards,

    Kishore

  • Hello Kishore,

    I will check, then come back to you.

  • Hello,

    I run a test. There is no problem.

    Please configure STC clock divider in system register:

    systemREG2->STCCLKDIV = (0x00u) << 24;

  • This is the code for STC self-check:

    /* perform STC module self check */
    boolean STC_SelfCheck()
    {
    volatile uint32 i = 0U;
    uint32_t tstStat, index;

    /* Run a diagnostic check on the CPU self-test controller */
    /* First set up the STC clock divider as STC is only supported up to 90MHz */
    systemREG2->STCCLKDIV = (0x00u) << 24;

    /* STC clock is now normal mode CPU clock frequency/2 = 300MHz/3 */
    stcREG1->STCCLKDIV = 0x05050000U; //CLKDIV0 and CLKDIV1 = 5+1

    /* Select one test interval, restart self-test next time, 0x00010001 */
    stcREG1->STCGCR0 = 0x00010001U;

    /* Enable comparator self-check and stuck-at-0 fault insertion in CPU, 0x1A */
    stcREG1->STCSCSCR = 0x1AU;

    /* Maximum time-out period */
    stcREG1->STCTPR = 0xFFFFFFFFU;

    // wait for 64 VBUS clock cycles at least, based on HCLK to VCLK ratio
    #define VBUS_CLK_CYCLES 64U
    for (index = 0UL; index < (VBUS_CLK_CYCLES + (VBUS_CLK_CYCLES * 1u)); index++);

    /* Enable self-test */
    stcREG1->STCGCR1 = 0x50AU; //5: Select only Core1 for self-test.

    /* USER CODE BEGIN (9) */
    /* USER CODE END */
    wfi: asm(" WFI");
    asm(" NOP");
    asm(" NOP");
    asm(" NOP");
    asm(" NOP");
    asm(" NOP");
    asm(" NOP");
    asm(" NOP");
    asm(" NOP");
    asm(" DMB");
    asm(" DMB");
    goto wfi;

    tstStat = stcREG1->STCFSTAT;

    return tstStat;
    }

  • Hi Wang, after i did the update per your suggestion, i am still seeing the CPU self test is failing. Not sure what it could be. Below are the steps.

    // Step 1:
    // Configure CPU Logic BIST Clock Divider (STCLKDIV) of system2 module
    volatile Uint32* const sys2_stc_clk_div = reinterpret_cast<volatile Uint32*>(SYS2_REG_BASE_ADDR + 0x08UL);
    *sys2_stc_clk_div = 0x00000000UL;

    // Step 2:
    // Run a diagnostic check on the CPU self-test controller
    // Maximum STC clock rate support at 180 MHz GCLK1 is 90 MHz. Divide GCLK1 by 2 to achieve this
    // clock rate.
    stc_ctrl_regs[STCCLKDIV] = 0x02020000UL;

    // Step 3:
    // Clear CPU RST status bit in the System Exception Status Register in the system module
    volatile Uint32* sys1_esr = reinterpret_cast<volatile Uint32*>(SYS1_REG_BASE_ADDR + 0xE4U);
    *sys1_esr = (1UL << 5U);

    // Step 4:
    // Run specified no of test intervals starting from interval 0
    // Start test from interval 0 or continue the test.
    // It is expected to change the value pointed by stc_gcr0.
    stc_ctrl_regs[STCGCR0] &= 0x0000F8FEUL;
    stc_ctrl_regs[STCGCR0] |= ((125UL << 16UL) | 1UL);

    // Step 5:
    // Configure Maximum time-out period
    stc_ctrl_regs[STCTPR] = 0xFFFFFFFFUL;

    // Step 6:
    // wait for 64 VBUS clock cycles at least, based on HCLK to VCLK ratio
    #define VBUS_CLK_CYCLES 64U
    for (Uint32 index = 0UL; index < (VBUS_CLK_CYCLES + (VBUS_CLK_CYCLES * 1u)); index++);

    // Step 7:
    // Enable self-test, Select only Core1 for self-test, Self-test run is enabled
    stc_ctrl_regs[STCGCR1] &= 0xFFFFF0F0UL;
    stc_ctrl_regs[STCGCR1] |= 0x0000050AUL;

    // Step 8:
    // Keep CPU in standby mode.
    __asm__ __volatile__ (
    "WFI \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "nop \n"
    "DMB \n"
    "DSB \n"
    );

    return;

    Regards,

    Kishore

  • I thought you got error when running STC self check.

    I will try your code for CPU self test.

  • Hi Wang, you are right, i was looking into STC self test before. After your latest suggestion, that test also works fine. But the last test which is CPU self test is failing.

    Regards,

    Kishore

  • Hello Kishore,

    I run the test, it works.

    TEST_DONE = 1 and TEST_FAIL = 0, the CPU self-test is completed successfully.

    STCFSTAT = 0x00000000

  • Hi Wang, I saw that the TMS5704357 safety library code, only STC self test has been performed only once. But in 3137, STC test was performed twice with different intervals. Also each test followed a software reset in 3137 case, is that needed to be followed on 4347? please confirm.

    Regards,

    Kishore

  • Hello Kishore,

    For CPU self-test on LS31x device, we can run 24 intervals together, or we can run several slices per time. If the tests are run in slices, the software can tell the STC controller to continue the run from the next interval onwards. You can use either way.

    The example code generated by HALCoGen or in the startup.c of the SafetyLibrary has two STC test: STC self-check and STC self-test (or CPU self-test). 

    STC generates a CPU reset after completion of the test regardless of pass or fail. No SW reset is needed after test. Can you please tell me which file performs two STC test and issues a SW reset? Thanks 

  • Hi Wang, by SW reset i mean, the reset that happens via test itself, there is no explicit SW reset. 

    We are using TMS570LC4357, do i still need to perform STC and CPU self tests separately? what we are observing is, STC self test passes and after the reset, when i performed CPU self test, i am not seeing a reset after the test execution.

    Regards,

    Kishore

  • Hi Wang, i took a snippet from safety library code, if you see below, CPU self test function call is commented. do u know why?

    Also in the safety library code, i dont see 'cpuSelfTest' function defined anywhere. So i am wondering if we really need to perform this test, only the STC self test with 125 intervals as a input should be good enough?

    /* clear self-check mode */

    #if defined(_TMS570LS31x_) || defined(_TMS570LS12x_) || defined(_RM48x_) || defined(_RM46x_) || defined(_RM42x_) || defined(_TMS570LS04x_)
    stcREG->STCSCSCR = 0x05U;

    /* clear STC global status flags */
    stcREG->STCGSTAT = 0x3U;
    #endif
    #if defined(_TMS570LC43x_) || defined(_RM57Lx_)
    stcREG1->STCSCSCR = 0x05U;

    /* clear STC global status flags */
    stcREG1->STCGSTAT = 0x3U;
    #endif

    /* clear ESM group1 channel 27 status flag */
    esmREG->SR1[0U] = 0x08000000U;

    /* Start CPU Self-Test */
    /*there is no alternate usercode place holder to place the safety library api so this block of code can *
    get overwritten on helcogen code regeneration*/
    /*********************************************************************************************************/
    /*cpuSelfTest(STC_INTERVAL, STC_MAX_TIMEOUT, TRUE);*/
    stcSelfTestConfig.stcClockDiv = 0; /* STC Clock divider = 1 */
    stcSelfTestConfig.intervalCount = 1; /* One interval only */
    stcSelfTestConfig.restartInterval0 = TRUE; /* Start from interval 0 */
    stcSelfTestConfig.timeoutCounter = 0xFFFFFFFF; /* Timeout counter*/
    _SL_HoldNClear_nError();

    /* mask vim interrupts before running STC */
    vimREG->REQMASKCLR0 = 0xFFFFFFFFu;
    vimREG->REQMASKCLR1 = 0xFFFFFFFFu;
    vimREG->REQMASKCLR2 = 0xFFFFFFFFu;
    vimREG->REQMASKCLR3 = 0xFFFFFFFFu;

    /* ensure no pending ESM GRP2 errors before running STC */
    if(esmREG->SSR2 == 0u)
    #if defined(_TMS570LS31x_) || defined(_TMS570LS12x_) || defined(_RM48x_) || defined(_RM46x_) || defined(_RM42x_) || defined(_TMS570LS04x_)
    {SL_SelfTest_STC(STC_RUN, TRUE, &stcSelfTestConfig);}
    #endif
    #if defined(_TMS570LC43x_) || defined(_RM57Lx_)
    {SL_SelfTest_STC(STC1_RUN, TRUE, &stcSelfTestConfig);}
    #endif
    /*********************************************************************************************************/
    }
    }

  • Hi,

    As you knew, the STC (SelfTest Controller) can provide a very high diagnostic coverage on the lockstep CPUs. It is a very important functional safety feature on this device. The CPU self-test (also called STC self-test) should be performed. You can run all tests (125 interval for STC1) during startup, or you can run sliced tests during the normal operation as run-time diagnostic. 

    The advantage of run the test during startup is that your SW doesn't need to save the CPU contents. But the run-time CPU self-test requires your SW to save the CPU contents before the self-test and reload them after the CPU reset caused by the completion of the STC test interval. 

    You don't have to do STC self-check which is to check the STC's internal compare logic. 

    {SL_SelfTest_STC(STC1_RUN, TRUE, &stcSelfTestConfig);}  -- this is to run the STC self-test or CPU self-test.

    cpuSelfTest(...) function is not used in S. Library example code.

  • Hi Wang, Thanks a lot for your support, now i am able to see all tests passed.

    Kishore