/************************************************************************** * * Copyright (c) 2019-2019 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file WatchdogMgmt.c * * @date 20-Sep-2019 * @author S. Nash * * @brief Monitor for the off and stop buttons. * **************************************************************************/ #include "Common.h" #include "CPLD.h" #include "Timers.h" #include "WatchdogMgmt.h" // ********** private definitions ********** #define MIN_WATCHDOG_PET_INTERVAL_MS 45 typedef enum Button_Self_Test_States { WATCHDOG_SELF_TEST_STATE_START = 0, WATCHDOG_SELF_TEST_STATE_IN_PROGRESS, WATCHDOG_SELF_TEST_STATE_COMPLETE, NUM_OF_WATCHDOG_SELF_TEST_STATES } WATCHDOG_SELF_TEST_STATE_T; #define WATCHDOG_POST_TIMEOUT_MS 100 // ms // ********** private data ********** static BOOL watchdogExpired = FALSE; static U32 lastWatchdogPetTime = 0; static BOOL watchdogTaskCheckedIn[NUM_OF_TASKS]; static WATCHDOG_SELF_TEST_STATE_T watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_START; static U32 watchdogSelfTestTimerCount = 0; // ********** private function prototypes ********** static void resetWDTaskCheckIns( void ); static BOOL haveAllTasksCheckedIn( void ); static void petWatchdog( void ); /************************************************************************* * @brief initWatchdogMgmt * The initWatchdogMgmt function initializes the watchdog mgmt. module. * @details * Inputs : none * Outputs : Watchdog mgmt. module initialized. * @param none * @return none *************************************************************************/ void initWatchdogMgmt( void ) { watchdogExpired = FALSE; lastWatchdogPetTime = getMSTimerCount(); watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_START; watchdogSelfTestTimerCount = 0; resetWDTaskCheckIns(); } /************************************************************************* * @brief execWatchdogMgmt * The execWatchdogMgmt function executes thewatchdog mgmt. service. * @details * Inputs : none * Outputs : * @param none * @return none *************************************************************************/ void execWatchdogMgmt( void ) { BOOL allTasksCheckedIn; // called by background task, so give bg task credit for checking in checkInWithWatchdogMgmt( TASK_BG ); // check to see if all monitored tasks have checked in allTasksCheckedIn = haveAllTasksCheckedIn(); // if all monitored tasks checked in, pet watchdog and clear the slate if ( ( TRUE == allTasksCheckedIn ) && ( didTimeout( lastWatchdogPetTime, MIN_WATCHDOG_PET_INTERVAL_MS ) ) ) { petWatchdog(); resetWDTaskCheckIns(); } // check to see if watchdog has expired if ( getCPLDWatchdogExpired() == PIN_SIGNAL_HIGH ) { watchdogExpired = TRUE; } } /************************************************************************* * @brief checkInWithWatchdogMgmt * The checkInWithWatchdogMgmt function checks a given task in with the \n * watchdog mgmt. service. * @details * Inputs : none * Outputs : task is checked in with the watchdog mgmt.. * @param task : the task that is checking in with the watchdog mgmt. * @return none *************************************************************************/ void checkInWithWatchdogMgmt( TASK_T task ) { if ( task < NUM_OF_TASKS ) { watchdogTaskCheckedIn[task] = TRUE; } } /************************************************************************* * @brief hasWatchdogExpired * The hasWatchdogExpired function determines whether the watchdog has /n * expired. * @details * Inputs : watchdogExpired * Outputs : none * @param none * @return TRUE if watchdog has expired, FALSE if not. *************************************************************************/ BOOL hasWatchdogExpired( void ) { return watchdogExpired; } /************************************************************************* * @brief execWatchdogTest * The execWatchdogTest function executes the watchdog test. \n * This function should be called periodically until a pass or fail \n * result is returned. * @details * Inputs : * Outputs : * @param none * @return in progress, passed, or failed *************************************************************************/ SELF_TEST_STATUS_T execWatchdogTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; switch ( watchdogSelfTestState ) { case WATCHDOG_SELF_TEST_STATE_START: watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_IN_PROGRESS; watchdogSelfTestTimerCount = getMSTimerCount(); // no break here so we pass through directly to in progress processing case WATCHDOG_SELF_TEST_STATE_IN_PROGRESS: while ( FALSE == didTimeout( watchdogSelfTestTimerCount, WATCHDOG_POST_TIMEOUT_MS ) ) { // waiting here for w.d. test period to prevent this task from checking in - watchdog should expire } if ( getCPLDWatchdogExpired() == PIN_SIGNAL_HIGH ) { result = SELF_TEST_STATUS_PASSED; } else { result = SELF_TEST_STATUS_FAILED; // TODO - trigger watchdog POST failure } watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_COMPLETE; break; case WATCHDOG_SELF_TEST_STATE_COMPLETE: // if we get called in this state, assume we're doing self test again watchdogSelfTestState = WATCHDOG_SELF_TEST_STATE_START; break; default: result = SELF_TEST_STATUS_FAILED; // TODO - s/w fault break; } return result; } /************************************************************************* * @brief resetWDTaskCheckIns * The resetWDTaskCheckIns function resets the task check-ins with the watchdog. * @details * Inputs : none * Outputs : watchdogTaskCheckedIn[] array reset to all false. * @param none * @return none *************************************************************************/ static void resetWDTaskCheckIns( void ) { U32 i; // initialize task check-ins to false for ( i = 0; i < NUM_OF_TASKS; i++ ) { watchdogTaskCheckedIn[i] = FALSE; } } /************************************************************************* * @brief haveAllTasksCheckedIn * The haveAllTasksCheckedIn function determines whether all tasks have /n * checked in with watchdog mgmt. * @details * Inputs : watchdogTaskCheckedIn[] * Outputs : none * @param none * @return TRUE if all tasks have checked in since last watchdog pet, FALSE if not. *************************************************************************/ static BOOL haveAllTasksCheckedIn( void ) { BOOL result = TRUE; U32 i; // check that each task has checked in for ( i = 0; i < NUM_OF_TASKS; i++ ) { if ( FALSE == watchdogTaskCheckedIn[i] ) { result = FALSE; break; } } return result; } /************************************************************************* * @brief petWatchdog * The petWatchdog function pets the watchdog by pulsing the CPLD WD pet /n * signal. * @details * Inputs : none * Outputs : CPLD WD pet signal is pulsed * @param none * @return none *************************************************************************/ static void petWatchdog( void ) { // pulse the watchdog signal toggleCPLDWatchdog(); // remember when we last pet the watchdog lastWatchdogPetTime = getMSTimerCount(); }