Part Number: TMS320F2808
We have discovered that ESD events causes the frequency of the TMS320F2808 chip on our PCB interface to change. The DSP restarts correctly most of the time according to the WD settings. However, sometimes the interface freezes and becomes fully or partially unresponsive.
The ESD event is created by discharging from a human body through a screwdriver and to the GND of the interface (or the chassis).
The chip runs at 100MHz with an external crystal of 20MHz and during an ESD event, XCLKOUT is changed to 2.5MHz during the reset. Most of the time XCLKOUT correctly returns to 100MHz and normal operation continues. Unfortunately, sometimes it gets stuck at 2.5MHz or other frequencies such as 0Mhz (XCLKOUT stays high), 5MHz, 17.5MHz, 50MHz and even 200MHz (!). Frequencies under 100MHz cause the DSP to freeze as can be seen from a stripped-down FW where almost only a GPIO is toggling. At 200MHz the GPIO continues to toggle however at double the rate. Debugging is seemingly still possible sometimes at some frequencies (seen at 200MHz and 50MHz). Connecting JTAG, COM, and CAN interfaces to the PCB greatly increases the sensitivity to the ESD events. Also enabling more of our modules in main.c seems to increase the rate at which these freezing events happen. Modules consist of timer interrupts, EEPROM, GPIO, SPI, UART, FLASH, RTC, CAN, PWM, and some of our own modules.
These findings prompted monitoring XCLK, PLLSTS, PLLCR, and WD of the SYSCTRL register. Before going into the details of the registers, it is important to note that no glitches have been seen with the oscilloscope (Siglent SDS1204X-E) on the Vdd(1.8V), VddIO(3.3V), and X2 (external 20MHz crystal) pins during the ESD event. This might be because the voltage spikes are too fast to observe/trigger on. The /XRS pin also seems unchanged during an ESD event. For now, the focus has been on the internal DSP registers.
main.c:
int main( void )
{
#if USE_PORT_CANOPEN
#else
is_programming = false;
#endif
_copy_code_from_flash_to_ram();
InitSysCtrl();
//modules_init();
EnableInterrupts();
SetDog();
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO16 = 1; // pullup off
GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 0; // G16/EQEP1A/SPISIMOC/CANTXB
GpioCtrlRegs.GPADIR.bit.GPIO16 = 1; // 1:output, 0:input
GpioDataRegs.GPASET.bit.GPIO16 = 0; // Load output latch
EDIS;
for( ; ; )
{
RTASSERT_RESET(main_loop_active);
//ServiceDog();
GpioDataRegs.GPASET.bit.GPIO16 = 1;
delay(100);
GpioDataRegs.GPACLEAR.bit.GPIO16 = 1;
delay(100);
#if USE_PORT_CANOPEN
#else
if (is_programming) { //Exit loop if the start programming message was received
break;
}
#endif
//stackutils_check();
ServiceDog();
RTASSERT_IS_LESS(main_loop_active, 15000000);
} //End of the main loop
return 0;
}
InitPll(DSP28_PLLCR,DSP28_CLKINDIV) in InitSysCtrl() where DSP28_PLLCR=10 and DSP28_CLKINDIV=0:
void InitPll(Uint16 val, Uint16 clkindiv)
{
volatile Uint16 iVol;
test++;
// Make sure the PLL is not running in limp mode
if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)
{
// Missing external clock has been detected (running in limp mode)
// Replace this line with a call to an appropriate
// SystemShutdown(); function.
//ResetProc();
// EALLOW;
// SysCtrlRegs.PLLSTS.bit.MCLKCLR = 1;
// EDIS;
asm(" ESTOP0");
//asm(" RPT #20 || NOP");
}
// CLKINDIV MUST be 0 before PLLCR can be changed from
// 0x0000. It is set to 0 by an external reset XRSn
if (SysCtrlRegs.PLLSTS.bit.CLKINDIV != 0)
{
SysCtrlRegs.PLLSTS.bit.CLKINDIV = 0;
}
// Change the PLLCR
if (SysCtrlRegs.PLLCR.bit.DIV != val)
{
//thread_enter_critical_registers();
EALLOW;
// Before setting PLLCR turn off missing clock detect logic
SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;
SysCtrlRegs.PLLCR.bit.DIV = val;
EDIS;
//thread_leave_critical_registers();
// Optional: Wait for PLL to lock.
// During this time the CPU will switch to OSCCLK/2 until
// the PLL is stable. Once the PLL is stable the CPU will
// switch to the new PLL value.
//
// This time-to-lock is monitored by a PLL lock counter.
//
// Code is not required to sit and wait for the PLL to lock.
// However, if the code does anything that is timing critical,
// and requires the correct clock be locked, then it is best to
// wait until this switching has completed.
// Wait for the PLL lock bit to be set.
// Note this bit is not available on 281x devices. For those devices
// use a software loop to perform the required count.
// The watchdog should be disabled before this loop, or fed within
// the loop via ServiceDog().
// Uncomment to disable the watchdog
DisableDog();
while(SysCtrlRegs.PLLSTS.bit.PLLLOCKS != 1)
{
// Uncomment to service the watchdog
// ServiceDog();
}
//thread_enter_critical_registers();
EALLOW;
SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;
SysCtrlRegs.PLLSTS.bit.CLKINDIV != clkindiv; // Disable CLKIN divide by 2
EDIS;
//thread_leave_critical_registers();
}
}
SYSCTRL during normal 100MHz operation:

SYSCTRL after ESD event where XCLKOUT eventually becomes 200MHz:

SYSCTRL after shorting X2 while XCLKOUT=200MHz. Here XCLK becomes 50MHz while the missing clock flag is set (PLLSTS[MCLKSTS]=1) and the WD is not operating (no changes):
Since PLLSTS[MCLKSTS] is set I assumed XCLKOUT would be in the range of 1-5Mhz, not 50Mhz?

Conducting a SW reset by writing a faulty pattern to WDCR[WDCHK] while debugging during normal operation (XCLKOUT=100MHZ) also freezes the DSP (no GPIO is toggling). XCLKOUT becomes stuck at 2.5MHz while WDCR[WDFLAG] is toggling. The PLLSTS[MCLKSTS] bit is not set, so I am not sure if the is “limp mode” or something else. As for the PLL and XCLK during this test, the following changes are observed:
- PLLSTS[CLKINDIV] = 0
- PLLCR[DIV] = 1010b --> PLLCR[DIV] = 0000b (default)
- PLLSTS[PLLLOCKS] = 1b --> Unchanged
- XCLK[XCLKDIV] = 10b --> XCLK[XCLKDIV] = 00b
Now the question is if there is any way to reset the DSP so that it resumes normal operation (it goes back to 100Mhz consistently) after resetting from an ESD event? The event does not seem to break the DSP, but the WD is unable to reset somehow and XCLKOUT is stuck at seemingly arbitrary multiples of OSCCLK or it even 0 (staying high). JTAG connection is unfortunately lost during most of the ESD events so reading the registers is not possible making debugging difficult. The goal here is to reset the DSP back to normal operation in order to comply with certification requirements with regards to Electrical Fast Transient Test Failure.