SPRZ171T December 2004 – September 2020 SM320F2801-EP , SM320F2808-EP , TMS320F2801 , TMS320F2801-Q1 , TMS320F28015 , TMS320F28016 , TMS320F28016-Q1 , TMS320F2802 , TMS320F2802-Q1 , TMS320F2806 , TMS320F2806-Q1 , TMS320F2808 , TMS320F2808-Q1 , TMS320F2809 , TMS320F2809-Q1
WD: Limitation on Watchdog Module: Corrupted Watchdog Key Writes
0 on C280x silicon
0, A, B on F2801, F2802, F2806, F2808, and F2801x silicon
When using the on-chip PLL (PLLCR ≠ 0), writes of the 0x55/0xAA sequence to WDKEY register may be corrupted. Although the watchdog counter will be reset correctly, this will cause a Watchdog (WD) interrupt or reset depending on the state of the WDENINT bit in the SCSR register.
Implement a software function (ServiceWatchDog) that performs the writes of 0x55 and 0xAA to the WDKEY register, as shown below. The WD interrupt (WAKEINT in the PIE) is remapped to a pseudo interrupt service routine (ISR). The ServiceWatchDog routine will deterministically force a WD interrupt each time the function is called. This forced interrupt will be serviced by the pseudo ISR. The pseudo ISR will then acknowledge the interrupt and remap the WAKEINT interrupt back to the normal WD ISR.
The WDINT signal, once triggered, will stay active low for 512 OSC Clock cycles. If another WD event (timeout or bad key write) comes before this signal has gone inactive high, the event will not be captured by the WD module. See the TMS320x280x, 2801x, 2804x DSP System Control and Interrupts Reference Guide section on Watchdog Reset or Watchdog Interrupt Mode for more information
Case 2: Applications Using the WD Reset
This case uses the interrupt feature of the WD module to work around the possible corruption of the WDKEY register and to service any WD events that would normally trigger a reset. Applications that only used the reset feature of the WD will now need to properly map and enable the WAKEINT interrupt in the PIE. Applications will also need to enable the interrupt function of the WD by setting the WDENINT bit in the SCSR register. The reset feature of the WD will only be enabled inside the WatchdogInterrupt interrupt service routine (ISR) and triggered when a true WD event occurs, either from a WD timeout or an incorrect write to the WDKEY register or the WDCHK bits in the WDCR register. Inside the ISR an incorrect value is written to the WDKEY to force the WD reset. Since the WD reset is gated by servicing the WD interrupt, applications must re-enable WD interrupts via the PIEIER and the INTM bit in ST1 inside other ISRs. In order to service the WD(reset the WD counter) during normal operation, implement a software function (ServiceWatchDog) that performs the writes of 0x55 and 0xAA to the WDKEY register, as shown below. The WD interrupt (WAKEINT in the PIE) is remapped to a pseudo ISR. The ServiceWatchDog routine will deterministically force a WD interrupt each time the function is called. This forced interrupt will be serviced by the pseudo ISR. The pseudo ISR will then acknowledge the interrupt and remap the WAKEINT interrupt back to the normal WD ISR.
Code example for Case 1
void ServiceWatchdog (void)
{
EALLOW;
DINT; // Disable Global Interrupts
if(SysCtrlRegs.WDCNTR < 254) // If watchdog counter is
// less then 254, then there
// is enough time to use the
// service watchdog function;
// otherwise, assume it is
// too late and let the
// watchdog time out.
{
PieVectTable.WAKEINT = &PseudoWatchdogInterrupt; // Remap
// vector to pseudo routine
SysCtrlRegs.WDKEY = 0x0000; // Force an interrupt always
SysCtrlRegs.WDKEY = 0x0055;
SysCtrlRegs.WDKEY = 0x00AA; // This will clear the
// watchdog counter
}
EINT; // Enable global interrupts
EDIS;
}
interrupt void PseudoWatchdogInterrupt(void)
{
EALLOW;
PieVectTable.WAKEINT = &WatchdogInterrupt; // This will clear
// PIEIFR.INT1.8 flag
// and remap back to
// proper service
// routine
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
EDIS;
}
interrupt void WatchdogInterrupt(void)
{
// Proper Watchdog Interrupt;
}
Code example for Case 2
void ServiceWatchdog (void)
{
EALLOW;
DINT; // Disable Global Interrupts
if(SysCtrlRegs.WDCNTR < 254) // If watchdog counter is
// less then 254, then there
// is enough time to use the
// service watchdog function;
// otherwise, assume it is
// too late and let the
// watchdog time out.
{
PieVectTable.WAKEINT = &PseudoWatchdogInterrupt; // Remap
// vector to pseudo routine
SysCtrlRegs.WDKEY = 0x0000; // Force an interrupt always
SysCtrlRegs.WDKEY = 0x0055;
SysCtrlRegs.WDKEY = 0x00AA; // This will clear the
// watchdog counter
}
EINT; // Enable global interrupts
EDIS;
}
interrupt void PseudoWatchdogInterrupt(void)
{
EALLOW;
PieVectTable.WAKEINT = &WatchdogInterrupt; // This will clear
// PIEIFR.INT1.8 flag
// and remap back to
// proper service
// routine
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
EDIS;
}
interrupt void WatchdogInterrupt(void)
{
EALLOW;
SysCtrlRegs.SCSR = 0x0000; // Set the WD to generate WDRSTn
SysCtrlRegs.WDKEY = 0x0000; // In case WDINTn is not low, force
// the reset with a bad key write
EDIS;
// Proper Watchdog Interrupt;
}