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 -
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.
-
uint16_t
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)
}