cancel
Showing results for 
Search instead for 
Did you mean: 

Window Watchdog (WWDG) Early Wakeup Interrupt (EWI) configuration bugs in firmware library

wenbin
Associate II
Posted on November 06, 2015 at 16:44

Hello, WWDG should be used in my application, some safety operations should be done in the EWI, I found some bugs in the firmware library, which will be discussed here to help other developers.

Experiment set-ups:

IDE: IAR 7.40

Board: STM32746G-Discovery (STM32F746NG embedded)

Firmware version: V1.2.0

HAL_WWDG_Start_IT function should be used to start WWDG and enable EWI. Below is the original implementation:

HAL_StatusTypeDef HAL_WWDG_Start_IT(WWDG_HandleTypeDef *hwwdg)

{

  /* Process Locked */

  __HAL_LOCK(hwwdg); 

  /* Change WWDG peripheral state */  

  hwwdg->State = HAL_WWDG_STATE_BUSY;

  /* Enable the Early Wakeup Interrupt */ 

  __HAL_WWDG_ENABLE_IT(hwwdg, WWDG_IT_EWI);

  /* Enable the peripheral */

  __HAL_WWDG_ENABLE(hwwdg);  

  /* Return function status */

  return HAL_OK;

}

Bug1:

WWDG isn't unlocked and isn't changed to READY state before leaving. The WWDG resets the system immediately when calling this function.

Bug2:

EWI should be enabled (Set EWI bit) after enabling WWDG (Set WDGA bit), or the WWDG resets the system immediately. I don't know why, can't find in the manual.

Bug3:

Early Wakeup flag (EWIF bit) should be cleared when enabling the EWI, because the EWIF won't be cleared by hardware reset. If the flag is set, WWDG will reset the system immediately.

So the correct implementation of the function is like this:

HAL_StatusTypeDef HAL_WWDG_Start_IT(WWDG_HandleTypeDef *hwwdg)

{

  /* Process Locked */

  __HAL_LOCK(hwwdg); 

  /* Change WWDG peripheral state */  

  hwwdg->State = HAL_WWDG_STATE_BUSY;

  

  /* Enable the peripheral */

  __HAL_WWDG_ENABLE(hwwdg);

  

  /* Clear the WWDG Early Wakeup flag */

  __HAL_WWDG_CLEAR_FLAG(hwwdg, WWDG_FLAG_EWIF);

      

  /* Enable the Early Wakeup Interrupt */ 

  __HAL_WWDG_ENABLE_IT(hwwdg, WWDG_IT_EWI);

  /* Change WWDG peripheral state */    

  hwwdg->State = HAL_WWDG_STATE_READY; 

  

  /* Process Unlocked */

  __HAL_UNLOCK(hwwdg);

  

  /* Return function status */

  return HAL_OK;

}

The key codes of testing WWDG are listed below:

Step 1: Configure the WWDG in the main function

  /*♯♯♯-Step 1- Check if the system has resumed from WWDG reset ♯♯♯♯♯♯♯♯♯♯♯♯♯♯*/

  if (__HAL_RCC_GET_FLAG(RCC_FLAG_WWDGRST) != RESET)

  {

    /* WWDGRST flag set: send msg */

    printf(''** The system has resumed from a WWDG reset ** \r\n'');

    /* Clear reset flags */

    __HAL_RCC_CLEAR_RESET_FLAGS();

  }

  /*♯♯♯-Step 2- Set the WWDG clock ♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯*/

  /* WWDG clock counter = (PCLK1 (54MHz)/4096)/8) = 1648 Hz (~607 us) 

     WWDG Window value = 80 means that the WWDG counter should be refreshed only 

     when the counter is below 80 (and greater than 64) otherwise a reset will 

     be generated. 

     WWDG Counter value = 127, WWDG timeout = ~607 us * 64 = 25.5 ms */

  WwdgHandle.Instance = WWDG;

  WwdgHandle.Init.Prescaler = WWDG_PRESCALER_8;

  WwdgHandle.Init.Window    = 80;

  WwdgHandle.Init.Counter   = 127;

  if (HAL_WWDG_Init(&WwdgHandle) != HAL_OK)

  {

    /* Initialization Error */

    Error_Handler();

  }

  /*♯♯♯-Step 3- Start the WWDG ♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯♯*/

  /* Enable and set the WWDG Early Wakeup Interrupt to has higher priority than other used interrupts */

  HAL_NVIC_SetPriority(WWDG_IRQn, 0x0D, 0x00); // Priority Group 4

  HAL_NVIC_EnableIRQ(WWDG_IRQn);

  if (HAL_WWDG_Start_IT(&WwdgHandle) != HAL_OK)

  {

    Error_Handler();

  }

  

  /* Infinite loop */

  while (1)

  {

   /* Toggle LED1 */

    BSP_LED_Toggle(LED1);

    /* Insert 30 ms delay */

    HAL_Delay(30);

    /* Refresh WWDG: update counter value to 127, the refresh window is:

 between 28.5 ms (~607 * (127-80)) and 38.8 ms (~607 * (127-63)) */

    if (HAL_WWDG_Refresh(&WwdgHandle, 127) != HAL_OK)

    {

      Error_Handler();

    }

  }

  

Step 2: Add the interrupt handler and re-write the callback

void WWDG_IRQHandler(void)

{

  HAL_WWDG_IRQHandler(&WwdgHandle);

}

void HAL_WWDG_WakeupCallback(WWDG_HandleTypeDef* hwwdg)

{

  /* Reload the downcounter */

  if (HAL_WWDG_Refresh(&WwdgHandle, 127) != HAL_OK)

  {

    Error_Handler();

  }

  

  /* Do some safety operations, which should be within 38.8 ms in this case

 or the WWDG will reset the system again */

  printf(''** The system will be reset by WWDG ** \r\n'');

  

  /* I would rather let the WWDG reset the system gracefully,

 because the original dog feeding pace has interrupted, which should never happen.

 Or comment the infinite loop to let the code run back to normal */

  while(1)

  {

  }

}

Step 3: Simulate an software problem to trigger EWI

You can add a long delay in the user button interrupt handler, which will block the normal refresh of the WWDG.

#window-watchdog
3 REPLIES 3
AVI-crak
Senior
Posted on November 08, 2015 at 14:52

I think you have the wrong use of the watchdog. Checking / updating of the timer should be executed after a critical section with a very hard time reference. A critical section needs to have time to be executed at exactly the time allotted for it, start the section on hardware timer configured depending on the overall code.

For example comparing the channel update timer to generate PWM control of a powerful engine. Missing or incorrect data value can lead to burnout rather expensive keys, which will be included is not native time - they just burn the motor emf + weight.

In this situation it is necessary to save the equipment and reset handler register arms dump periphery to which does not reach the software reset.

Use a delay in the body of the watchdog timer is equivalent to the use of alcohol to disinfect - before the lethal injection of poison.

And yes, hal - evil, use a direct appeal to the registers

Мне кажет�?�? у ва�? неверное применение �?торожевого таймера. Проверка/обновление �?того таймера должно выполн�?т�?�? по�?ле критиче�?кой �?екции �? очень жё�?ткой прив�?зки по времени. Критиче�?ка�? �?екци�? должна у�?петь выполнить�?�? в точно отведённое дл�? неё врем�?, запу�?к �?екции по аппаратному таймеру, выполнение �? зави�?имо�?т�?ми от общего кода. 

�?апример обновление каналов �?равнени�? дл�? таймера, дл�? генерации шим управлени�? мощного двигател�?. От�?ут�?твие или некорректное значение данных может приве�?ти к выгоранию до�?таточно дорогих ключей, которые окажут�?�? включенными не в родное врем�?  - их про�?то �?ожжёт ЭДС двигател�?  + ма�?�?а. 

При такой �?итуации необходимо �?па�?ать оборудование, и в обработчике �?бро�?а пропи�?ать руками �?бро�? периферии, до которой не дот�?гивает�?�? программный ре�?ет.

И�?пользовать задержки в теле �?торожевого таймера  равно�?ильно и�?пользованию  �?пирта дл�? дезинфекции - перед �?мертельной инъекцией �?да. 

И да, hal  - зло, и�?пользуйте пр�?мое обращение в реги�?тры.
wenbin
Associate II
Posted on November 12, 2015 at 13:40

Hello, Thank you for the post.

I agree with you that safety operations should be carried out when the window watchdog is interrupted due to some error.

In this demonstration, the long delay is used to simulate software error to trigger WWDG interrupt. In the WWDG interrupt handler, the safety operations are done, and then I let it reset the system gracefully.

Walid FTITI_O
Senior II
Posted on July 15, 2016 at 17:03

Hi zhong.wenbin.001,

The WWDG driver has been reworked. Try to download the last STM32cube library package release.

-Hannibal-