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

 

  1. 1Introduction
  2. 2Device and Development Tool Support Nomenclature
  3. 3Device Markings
  4. 4Silicon Change Overview
  5. 5Usage Notes and Known Design Exceptions to Functional Specifications
    1. 5.1 Usage Notes
      1. 5.1.1 PIE: Spurious Nested Interrupt After Back-to-Back PIEACK Write and Manual CPU Interrupt Mask Clear Usage Note
    2. 5.2 Known Design Exceptions to Functional Specifications
      1.      Advisory
      2.      Advisory
      3.      Advisory
      4.      Advisory
      5.      Advisory
      6.      Advisory
      7.      Advisory
      8.      Advisory
      9.      Advisory
      10.      Advisory
      11.      Advisory
      12.      Advisory
      13.      Advisory
      14.      Advisory
      15.      Advisory
      16.      Advisory
      17.      Advisory
      18.      Advisory
      19.      Advisory
      20.      Advisory
      21.      Advisory
      22.      Advisory
  6. 6Documentation Support
  7. 7Trademarks
  8. 8Revision History

Advisory

WD: Limitation on Watchdog Module: Corrupted Watchdog Key Writes

Revision(s) Affected

0 on C280x silicon

0, A, B on F2801, F2802, F2806, F2808, and F2801x silicon

Details

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.

Workaround(s)

  1. Use PLL in bypass mode (PLLCR = 0) or PLL off mode (PLLOFF = 1 in PLLSTS register). In this case, CLKINDIV in the PLLSTS register can be set or cleared. This is valid for both the WD interrupt and the WD reset cases.
  2. Case 1: Applications Using the WD Interrupt

    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.

    Note:

    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;
}