AnsweredAssumed Answered

Watchdog reset in LLS

Question asked by alessandro morniroli on May 28, 2015
Latest reply on Jun 11, 2015 by alessandro morniroli

Hi,

 

I'm using a Kinetis K22 MCU (but the same problem is noticeable also on a K11 device).

 

You can find attached to this message a zip archive with both Processor Expert/IAR project and sources (MK22FX512VMC12  used as target).

 

My "test setup":

 

- MK22FX512VMC12 (MK11DN512VLK5)
- Processor Expert 10.4.2 standalone for code generation

- IAR 7.10.1.6735 for compiler/IDE

 

Scenario:

 

- watchdog period set @ 1200ms (no window mode)

- external accelerometer configured to generate an interrupt @2khz each new data ready (interrupt data ready pin is configured as wakeup source). Accelerometer data ready interrupt is enabled after 5 seconds that program is running

- low power timer (LPTMR) configured as wakeup source @1khz. Within LPTMR interrupt, a counter is incremented. When the timer reachs 1000 (1 second elapsed), a flag is set in order to signal that the watchdog should be cleared

- two led used as debug

- MCU used in stop mode (LLS) after the initial configuration

 

Problem:

 

- as soon as the accelerometer data ready interrupt is enabled, watchdog resets the MCU

 

My main.c:

 

#include "Cpu.h" #include "IO_Map.h" #include "LED1_PE.h" #include "PE_Const.h" #include "SPI_PE.h" #include "WAIT_PE.h" #include "WD_PE.h"   /**  * 1 if WD should be cleared / 0 otherwise.  */ unsigned char wdTrigger;   /**  * Values for configuring the accelerometer (in order to generate wakeup  * interrupt in LLS)  */ static const char accConfig[9][2] = {     {0x14, 0xB6},     {0x12, 0x40},     {0x11, 0x80},     {0x10, 0x0F},     {0x20, 0x00},     {0x21, 0x00},     {0x1A, 0x01},     {0x11, 0x00},     {0x17, 0x10} };   /**  * Main function.  */ int main (void) {     /**      * Flag telling after how many seconds accelerometer interrupt is enabled.      */     static unsigned char accCounter = 5;       unsigned char  i;     unsigned short reset;       /* Read the reset cause register. */     reset  = (RCM_SRS1 << 8);     reset |= RCM_SRS0;       /* Internal WD reset? */     if (reset & RSTSRC_WDOG)     {         /* Debug. */         asm ("nop");     }       /* PE low level init. */     PE_low_level_init();       /* Enable interrupt. */     Cpu_EnableInt ();       /* Configure accelerometer. */     for (i = 0; i < 8; i++)     {         /* Send command via SPI. */         SPI_PE_SendBlock (PE_LDD_GetDeviceStructure (PE_LDD_COMPONENT_SPI_PE_ID), (void*) &accConfig[i], 2);           /* Wait some time (just in case). */         WAIT_PE_Waitms (1);     }       /* Loop forever... */     while (1)     {         /* Go to LLS. */         Cpu_SetOperationMode (DOM_STOP, NULL, NULL);           /* Clear WD? */         if (wdTrigger)         {             /* Toggle debug led1. */             LED1_PE_NegVal (NULL);               /* Clear WD. */             WD_PE_Clear (NULL);               /* Accelerometer interrupt still not enabled? */             if (accCounter)             {                 /* Decrement counter. */                 if (!(--accCounter))                 {                     /* Enable interrupt. */                     SPI_PE_SendBlock (PE_LDD_GetDeviceStructure (PE_LDD_COMPONENT_SPI_PE_ID), (void*) &accConfig[8], 2);                       /* Wait some time (just in case). */                     WAIT_PE_Waitms (1);                 }             }         }           /* Clear flag. */         wdTrigger = 0;     } }

 

My Events.c

 

/* ################################################################### **     Filename    : Events.c **     Project     : WD_K22 **     Processor   : MK22FX512VMC12 **     Component   : Events **     Version     : Driver 01.00 **     Compiler    : IAR ARM C Compiler **     Date/Time   : 2015-05-27, 14:29, # CodeGen: 0 **     Abstract    : **         This is user's event module. **         Put your event handler code here. **     Settings    : **     Contents    : **         Cpu_OnNMIINT - void Cpu_OnNMIINT(void); ** ** ###################################################################*/ /*! ** @file Events.c ** @version 01.00 ** @brief **         This is user's event module. **         Put your event handler code here. */ /*! **  @addtogroup Events_module Events module documentation **  @{ */ /* MODULE Events */   #include "Cpu.h" #include "Events.h"   #ifdef __cplusplus extern "C" { #endif     /* User includes (#include below this line is not maintained by Processor Expert) */   /* ** =================================================================== **     Event       :  LPTMR_PE_OnCounterRestart (module Events) ** **     Component   :  LPTMR_PE [TimerUnit_LDD] */ /*! **     @brief **         Called if counter overflow/underflow or counter is **         reinitialized by modulo or compare register matching. **         OnCounterRestart event and Timer unit must be enabled. See **         [SetEventMask] and [GetEventMask] methods. This event is **         available only if a [Interrupt] is enabled. **     @param **         UserDataPtr     - Pointer to the user or **                           RTOS specific data. The pointer passed as **                           the parameter of Init method. */ /* ===================================================================*/ void LPTMR_PE_OnCounterRestart(LDD_TUserData *UserDataPtr) {     /**      * External flag for clearing WD (declared by main).      */     extern unsigned char wdTrigger;       /**      * Counter for set WD flag each second.      */     static unsigned short counter;       /* Toggle debug led0. */     LED0_PE_NegVal (NULL);       /* Increment counter. */     counter++;       /* 1second elapsed? */     if (counter == 1000)     {         /* Clear counter. */         counter = 0;           /* Set WD flag. */         wdTrigger = 1;     } }   /* ** =================================================================== **     Event       :  Cpu_OnLLSWakeUpINT (module Events) ** **     Component   :  Cpu [MK22FN1M0MC12] */ /*! **     @brief **         This event is called when Low Leakage WakeUp interrupt **         occurs. LLWU flags indicating source of the wakeup can be **         obtained by calling the [GetLLSWakeUpFlags] method. Flags **         indicating the external pin wakeup source are automatically **         cleared after this event is executed. It is responsibility **         of user to clear flags corresponding to internal modules. **         This event is automatically enabled when [LLWU interrupt **         request] is enabled. */ /* ===================================================================*/ void Cpu_OnLLSWakeUpINT(void) {     unsigned int i32ulFlag = Cpu_GetLLSWakeUpFlags ();       /* Low power timer wakeup. */     if (i32ulFlag & LLWU_INT_MODULE0)     {         /* Clear LPTMR interrupt flag. */         LPTMR_PDD_ClearInterruptFlag (LPTMR0_BASE_PTR);     }       /* Accelerometer interrupt wakeup. */     if (i32ulFlag & LLWU_EXT_PIN11)     {         /* Debug. */         asm ("nop");     } }   /* END Events */   #ifdef __cplusplus }  /* extern "C" */ #endif   /*! ** @} */ /* ** ################################################################### ** **     This file was created by Processor Expert 10.4 [05.11] **     for the Freescale Kinetis series of microcontrollers. ** ** ################################################################### */

 

Using an oscilloscope to check the toggle of LED1 (which is done before the clear of the WD), the reset occurs before the timeout period elapses (resets at ~750ms), as you can see from this image (channel 2 is the LED1, channel 1 is the acceleromeer interrupt data ready pin at 2khz).

 

IMG_6213.JPG

 

The strange thing is that If I change the data ready interrupt frequency of the acceloremeter from 2khz to 250hz, the program is working correctly w/o resetting, as you can see from the next image.

 

IMG_6216.JPG

 

It seems that the MCU doesn't like waking up from LLS too fast (is really 2khz too fast, compared with the core clock running at 96mhz?) when the WD is enabled.

 

If the watchdog is disabled, no problems occur.

 

Another strange thing: changing watchdog timeout period from 1200ms to 2500ms (with interrupt @2khz), everything works correctly.

 

2500ms.jpg

 

Has anyone ever noticed a problem like this?

 

Alessandro

Original Attachment has been moved to: WD_K22.zip

Outcomes