CPU Registers Test API Functions

The code for this module is contained in source/stl_cpu_reg_s.asm with include/stl_cpu_reg.h containing the API declarations for use by applications.

Note that these tests only check the core registers for stuck bits. If your application requires a much more complete CPU test, see STL_HWBIST instead.

Error Injection

The functions in this module all have an injectError parameter that when set to true, will overwrite an incorrect test pattern to a register instead of the expected pattern in order to generate a failure.

The CCS Registers view can also be used to inject errors in nearly any of these registers while debugging. Place a breakpoint in the assembly function on the line after the test pattern is written to the register but before the comparison is done. Find that register in the “Core Registers” section of the Registers view and flip a bit. Resume the application and confirm that the function return value indicates an error was detected.

Module Details

group stl_cpu_reg

Defines

STL_CPU_REG_PASS 0x0U
STL_CPU_REG_FAIL 0x1U

Functions

uint16_t STL_CPU_REG_testCPURegisters(bool injectError)
uint16_t STL_CPU_REG_testFPURegisters(bool injectError)
uint16_t STL_CPU_REG_testVCRCRegisters(uint32_t *scratchRAM, bool injectError)
static uint16_t STL_CPU_REG_checkCPURegisters(bool injectError)

Tests CPU registers.

This function tests CPU core registers for stuck bits. The following registers are tested:

  • ACC

  • P

  • XAR0 to XAR7

  • XT

  • SP

  • IFR, IER and DBGIER

  • ST0

  • ST1 (excluding IDLESTAT and LOOP bits)

  • DP

Parameters
  • injectError: when false the test writes the test pattern to the registers as expected. When true, the test will write an unexpected error pattern to ACC to simulate a stuck bit, causing the test to fail.

The values of ST0, ST1, DP, IER, IFR, and DBGIER and the save-on-entry XAR registers, as defined by the compiler calling convention, are saved and restored in this test.

Note that the IDLESTAT and LOOP bits of ST1 are not tested by this function as they are read-only. IDLESTAT is set when the IDLE instruction is used to enter a low-power mode. Performing a functional test of the low-power mode will indirectly serve as a test of IDLESTAT.

The LOOP bit is set by the LOOPZ and LOOPNZ instructions. The C2000 compiler will not generate code that uses these instructions. If an application contains hand-coded assembly that uses them, the LOOP bit may also be tested by performing a functional test of the applicable LOOP instruction.

Note

You should disable interrupts before calling this test. Also note this test was written with POST use in mind, particularly before interrupts are enabled even at the PIE or CPU IER level. Keep in mind that INTM being set doesn’t prevent interrupts from propagating to the IFR registers, so although this function saves and restores IFR, an interrupt arriving in IFR during this test will be cleared by the restore or could cause a failure of this test. If this test needs to be used during runtime, you may want to modify STL_CPU_REG_testCPURegisters() in stl_cpu_reg.asm to remove the IFR test (and related save and restore). Alternatively, you can disable all interrupts at the PIE level (PIEIER) or in the case of non-PIE interrupts (like CPU Timers 1 and 2) at the peripheral level and restore them after STL_CPU_REG_checkCPURegisters() completes.

Return

If the test passes, the routine returns STL_CPU_REG_PASS. Otherwise, it returns STL_CPU_REG_FAIL.

static uint16_t STL_CPU_REG_checkFPURegisters(bool injectError)

Tests FPU registers.

This function tests FPU registers for stuck bits. The following registers are tested:

  • R0 to R7

  • RND32, TF, ZI, NI, ZF, NF bits of STF register.

  • Shadow registers for R0 to R7 and STF

Parameters
  • injectError: when false the test writes the test pattern to the registers as expected. When true, the test will write an unexpected error pattern to R5H to simulate a stuck bit, causing the test to fail.

The values of STF and the save-on-entry RnH registers, as defined by the compiler calling convention, are saved and restored in this test.

Note

You should disable interrupts before calling this test.

Return

If the test passes, the routine returns STL_CPU_REG_PASS. Otherwise, it returns STL_CPU_REG_FAIL.

static uint16_t STL_CPU_REG_checkVCRCRegisters(bool injectError)

Tests VCRC registers.

This function tests VCRC (Cyclic Redundancy Check Unit) registers for stuck bits. The following registers are tested:

  • VCRCPOLY

  • VCRCSIZE

  • VCRC

  • VSTATUS

Parameters
  • injectError: when false the test writes the test pattern to the registers as expected. When true, the test will write an unexpected error pattern to VCRCPOLY to simulate a stuck bit, causing the test to fail.

The values of VCRCPOLY, VCRCSIZE, and VSTATUS are saved and restored in this test.

Note

You should disable interrupts before calling this test.

Return

If the test passes, the routine returns STL_CPU_REG_PASS. Otherwise, it returns STL_CPU_REG_FAIL.

Pseudocode

Since the functions in this module are written in assembly, it may be hard to follow for users who are not will versed in the C28x instruction set. Some pseudocode versions of the module functions are provided below to make them easier to understand. Some knowledge of the C28x core registers may still be helpful however. See the C28x CPU and Instruction Set Guide and the C28x Extended Instruction Sets Manual for more details.

STL_CPU_REG_testCPURegisters

This is pseudocode for the STL_CPU_REG_testCPURegisters() assembly function that is used by C function STL_CPU_REG_checkCPURegisters().

//
// To keep pseudocode less complicated, adjustment of the length of the
// pattern given the size of the register is not shown below. REG_TEST_PATTERN
// will either mean 0xAAAA or 0xAAAAAAAA depending on what is appropriate for
// the register being tested.
//
REG_TEST_PATTERN    = 0xAAAA or 0xAAAAAAAA
REG_ERROR_PATTERN   = 0x555D

ST1_CLR_TEST_MASK   = 0xFF5B // PAGE0 is always 1, IDLESTAT and LOOP not tested
ST1_SET_TEST_MASK   = 0x0A00 // M0M1MAP and OBJMODE are always 1

TEST_ITERATIONS     = 1

uint16_t STL_CPU_REG_testCPURegisters(bool injectError)
{
    [context save (see conventions in https://www.ti.com/lit/pdf/spru514)]

    //************************************************************************
    //
    // Test of the accumulator (ACC, lower half AL, upper half AH)
    //
    //************************************************************************
    if(injectError == true)
    {
        AL = REG_ERROR_PATTERN    // Write incorrect pattern to AL
    }
    else
    {
        AL = REG_TEST_PATTERN     // Write usual test pattern to AL
    }

    if(AL != REG_TEST_PATTERN)
    {
        goto failCPURegTest
    }

    AH = REG_TEST_PATTERN
    if(AH != REG_TEST_PATTERN)
    {
        goto failCPURegTest
    }

    //
    // Now repeat the test with the inverted pattern
    //
    AL = ~REG_TEST_PATTERN
    if(AL != ~REG_TEST_PATTERN)
    {
        goto failCPURegTest
    }

    AH = ~REG_TEST_PATTERN
    if(AH != ~REG_TEST_PATTERN)
    {
        goto failCPURegTest
    }

    //************************************************************************
    //
    // Test of the P register
    //
    //************************************************************************
    P = REG_TEST_PATTERN
    if(P != REG_TEST_PATTERN)
    {
        goto failCPURegTest
    }

    P = ~REG_TEST_PATTERN
    if(P != ~REG_TEST_PATTERN)
    {
        goto failCPURegTest
    }

    //************************************************************************
    //
    // Test of auxiliary (XARn) and multiplicand (XT) registers
    //
    //************************************************************************
    iterations = TEST_ITERATIONS
    pattern = REG_TEST_PATTERN

    while(iterations >= 0)
    {
        pattern = ~pattern

        XAR0..7 = pattern
        if(XAR0..7 != pattern)
        {
            goto failCPURegTest
        }

        XT = pattern
        if(XT != pattern)
        {
            goto failCPURegTest
        }

        iterations--
    }

    //************************************************************************
    //
    // Test of stack pointer (SP)
    //
    //************************************************************************
    saveSP = SP
    SP = pattern
    if(SP != pattern)
    {
        SP = saveSP             // Restore the SP first
        goto failCPURegTest
    }

    pattern = ~pattern
    SP = pattern
    if(SP != pattern)
    {
        SP = saveSP             // Restore the SP first
        goto failCPURegTest
    }

    //************************************************************************
    //
    // Test of return program counter (RPC)
    //
    //************************************************************************
    saveRPC = RPC
    savePattern = pattern

    pattern &= 0x003F           // RPC is 22 bits

    RPC = pattern
    if(RPC != pattern)
    {
        RPC = saveRPC           // Restore the RPC first
        goto failCPURegTest
    }

    pattern = ~pattern
    pattern &= 0x003F

    RPC = pattern
    if(RPC != pattern)
    {
        RPC = saveRPC           // Restore the RPC first
        goto failCPURegTest
    }

    RPC = saveRPC               // Restore the RPC
    pattern = savePattern       // Restore the full pattern

    //************************************************************************
    //
    // Test of various 16-bit registers (ST0, ST1, DP, IER, IFR and DBGIER)
    //
    //************************************************************************
    saveST0 = ST0
    saveST1 = ST1
    saveDP = DP
    saveIER = IER
    saveIFR = IFR
    saveDBGIER = DBGIER

    iterations = TEST_ITERATIONS

    while(iterations >= 0)
    {
        DP = pattern
        if(DP != pattern)
        {                           // Note these 16-bit reg tests have a
            goto fail16BitRegTest   // different fail path because of the need
        }                           // to restore their original values

        ST0 = pattern
        if(ST0 != pattern)
        {
            goto fail16BitRegTest
        }

        IFR = pattern
        if(IFR != pattern)
        {
            goto fail16BitRegTest
        }

        DBGIER = pattern
        if(DBGIER != pattern)
        {
            goto fail16BitRegTest
        }

        IER = pattern
        if(IER != pattern)
        {
            goto fail16BitRegTest
        }

        pattern = ~pattern
        iterations--
    }

    //
    // ST1 is tested separately because it needs some special bits masked
    //
    savePattern = pattern
    IER = 0                         // Clear IER so we can set INTM safely

    pattern &= ST1_CLR_TEST_MASK
    pattern |= ST1_SET_TEST_MASK

    ST1 = pattern
    if(ST1 != pattern)
    {
        goto fail16BitRegTest
    }

    pattern = ~pattern
    pattern &= ST1_CLR_TEST_MASK
    pattern |= ST1_SET_TEST_MASK

    ST1 = pattern
    if(ST1 != pattern)
    {
        goto fail16BitRegTest
    }

    pattern = savePattern

    //************************************************************************
    //
    // Finally, set PASS/FAIL status and finish context restore
    //
    //************************************************************************
    status = TEST_PASSED
    goto restore16BitReg

fail16BitRegTest:
    status = TEST_FAILED

restore16BitReg:
    ST0 = saveST0
    ST1 = saveST1
    DP = saveDP
    IER = saveIER
    IFR = saveIFR
    DBGIER = saveDBGIER
    goto endCPURegTest

failCPURegTest:
    status = TEST_FAILED

endCPURegTest:
    [context restore]

    return(status)
}

STL_CPU_TEST_testFPURegisters

This is pseudocode for the STL_CPU_TEST_testFPURegisters() assembly function that is used by C function STL_CPU_REG_checkFPURegisters().

//
// To keep pseudocode less complicated, adjustment of the length of the
// pattern given the size of the register is not shown below. REG_TEST_PATTERN
// will either mean 0xAAAA or 0xAAAAAAAA depending on what is appropriate for
// the register being tested.
//
REG_TEST_PATTERN    = 0xAAAA or 0xAAAAAAAA
REG_ERROR_PATTERN   = 0x555D

STF_TEST_MASK_MSB   = 0x0000 // Masks for unwritable or reserved bits
STF_TEST_MASK_LSB   = 0x027C

TEST_ITERATIONS     = 1

uint16_t STL_CPU_TEST_testFPURegisters(bool injectError)
{
    [context save (see conventions in https://www.ti.com/lit/pdf/spru514)]

    //************************************************************************
    //
    // Test of floating-point result and status registers RnH, RnL, and STF
    //
    //************************************************************************
    iterations = TEST_ITERATIONS
    pattern = REG_TEST_PATTERN

    while(iterations >= 0)
    {
        pattern = ~pattern

        R0H..R7H = pattern
        R0L..R7L = pattern

        if(injectError == true)
        {
            R5H = REG_ERROR_PATTERN    // Write incorrect pattern to R5H
        }

        [trigger a shadow register save and restore]

        if(R0H..R7H != pattern)
        {
            goto failFPURegTest
        }

        if(R0L..R7L != pattern)
        {
            goto failFPURegTest
        }

        //
        // STF is tested separately because it needs some special bits masked
        //
        savePattern = pattern
        pattern &= ((STF_TEST_MASK_MSB << 16) | STF_TEST_MASK_LSB)

        STF = pattern
        [trigger a shadow register save and restore]

        if(STF != pattern)
        {
            goto failFPURegTest
        }

        pattern = savePattern

        iterations--
    }

    //************************************************************************
    //
    // Finally, set PASS/FAIL status and finish context restore
    //
    //************************************************************************
    status = TEST_PASSED
    goto endFPURegTest

    failFPURegTest:
        status = TEST_FAILED

    endFPURegTest:
        [context restore]

        return(status)
}

STL_CPU_REG_testVCRCRegisters

This is pseudocode for the STL_CPU_REG_testVCRCRegisters() assembly function that is used by C function STL_CPU_REG_checkVCRCRegisters().

//
// To keep pseudocode less complicated, adjustment of the length of the
// pattern given the size of the register is not shown below. REG_TEST_PATTERN
// will either mean 0xAAAA or 0xAAAAAAAA depending on what is appropriate for
// the register being tested.
//
REG_TEST_PATTERN    = 0xAAAA or 0xAAAAAAAA
REG_ERROR_PATTERN   = 0x555D

VSTATUS_TEST_MASK_MSB   = 0x8000  // Masks for unwritable or reserved bits
VSTATUS_TEST_MASK_LSB   = 0x0000
VCRCSIZE_TEST_MASK_MSB  = 0x001F
VCRCSIZE_TEST_MASK_LSB  = 0x0007

TEST_ITERATIONS     = 1

uint16_t STL_CPU_REG_testVCRCRegisters(uint32_t *scratchRAM, bool injectError)
{
    [context save (see conventions in https://www.ti.com/lit/pdf/spru514)]

    //************************************************************************
    //
    // Test of VCRC registers VSTATUS, VCRC, VCRCPOLY, and VCRCSIZE
    //
    //************************************************************************
    iterations = TEST_ITERATIONS
    pattern = REG_TEST_PATTERN

    while(iterations >= 0)
    {
        pattern = ~pattern

        //
        // *scratchRAM is used since nearly all of the move instructions for
        // the VCRC registers require a memory location as an operand, although
        // it may look like an unnecessary intermediate step below.
        //
        *scratchRAM = pattern
        VCRC = *scratchRAM
        VCRCPOLY = *scratchRAM

        if(injectError == true)
        {
            VCRCPOLY = REG_ERROR_PATTERN    // Write incorrect pattern to VCRCPOLY
        }

        *scratchRAM = VCRC
        if(*scratchRAM != pattern)
        {
            goto failVCRCRegTest
        }

        *scratchRAM = VCRCPOLY
        if(*scratchRAM != pattern)
        {
            goto failVCRCRegTest
        }

        //
        // VSTATUS is tested separately because it needs some bits masked
        //
        savePattern = pattern
        pattern &= ((VSTATUS_TEST_MASK_MSB << 16) | VSTATUS_TEST_MASK_LSB)
        *scratchRAM = pattern

        VSTATUS = *scratchRAM

        *scratchRAM = VSTATUS
        if(*scratchRAM != pattern)
        {
            goto failVCRCRegTest
        }

        pattern = savePattern

        //
        // VCRCSIZE is tested separately because it needs some bits masked
        //
        savePattern = pattern
        pattern &= ((VCRCSIZE_TEST_MASK_MSB << 16) | VCRCSIZE_TEST_MASK_LSB)
        *scratchRAM = pattern

        VCRCSIZE = *scratchRAM

        *scratchRAM = VCRCSIZE
        if(*scratchRAM != pattern)
        {
            goto failVCRCRegTest
        }

        pattern = savePattern

        iterations--
    }

    //************************************************************************
    //
    // Finally, set PASS/FAIL status and finish context restore
    //
    //************************************************************************
    status = TEST_PASSED
    goto endVCRCRegTest

    failVCRCRegTest:
        status = TEST_FAILED

    endVCRCRegTest:
        [context restore]

        return(status)
}