A module-bsp/board/linux/watchdog/software_watchdog.cpp => module-bsp/board/linux/watchdog/software_watchdog.cpp +59 -0
@@ 0,0 1,59 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "software_watchdog.hpp"
+#include <module-os/RTOSWrapper/include/critical.hpp>
+#include <module-os/RTOSWrapper/include/ticks.hpp>
+#include <module-sys/Service/Common.hpp>
+#include <module-utils/log/log.hpp>
+#include <cstdlib>
+
+namespace bsp::watchdog
+{
+ using namespace cpp_freertos;
+
+ static constexpr uint16_t stackDepthWords = 256;
+
+ SoftwareWatchdog::SoftwareWatchdog()
+ : Thread("SW_Watchdog", stackDepthWords, static_cast<UBaseType_t>(sys::ServicePriority::Realtime))
+ {}
+
+ bool SoftwareWatchdog::init(TickType_t timeoutPeriodMs)
+ {
+#ifdef DISABLE_WATCHDOG
+ return true;
+#else
+ timeoutPeriod = pdMS_TO_TICKS(timeoutPeriodMs);
+ const auto started = Start();
+
+ if (started) {
+ refresh();
+ }
+
+ return started;
+#endif
+ }
+
+ void SoftwareWatchdog::refresh()
+ {
+#ifndef DISABLE_WATCHDOG
+ // Critical section not required (atomic 32-bit writes)
+ lastRefreshTimestamp = Ticks::GetTicks();
+#endif
+ }
+
+ void SoftwareWatchdog::Run()
+ {
+ TickType_t lastTimeoutTimestamp = xTaskGetTickCount();
+
+ while (true) {
+ vTaskDelayUntil(&lastTimeoutTimestamp, timeoutPeriod);
+
+ // Critical section not required (atomic 32-bit reads)
+ if (lastTimeoutTimestamp - lastRefreshTimestamp >= timeoutPeriod) {
+ LOG_FATAL("!!! Software watchdog timeout, exiting !!!");
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+} // namespace bsp::watchdog
A module-bsp/board/linux/watchdog/software_watchdog.hpp => module-bsp/board/linux/watchdog/software_watchdog.hpp +28 -0
@@ 0,0 1,28 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <module-os/RTOSWrapper/include/thread.hpp>
+
+namespace bsp::watchdog
+{
+ class SoftwareWatchdog : private cpp_freertos::Thread
+ {
+ public:
+ SoftwareWatchdog();
+ SoftwareWatchdog(const SoftwareWatchdog &) = delete;
+ SoftwareWatchdog(SoftwareWatchdog &&) = delete;
+ SoftwareWatchdog &operator=(const SoftwareWatchdog &) = delete;
+ SoftwareWatchdog &operator=(SoftwareWatchdog &&) = delete;
+
+ bool init(TickType_t timeoutPeriodMs);
+ void refresh();
+
+ private:
+ void Run() final;
+
+ TickType_t timeoutPeriod = 0;
+ TickType_t lastRefreshTimestamp = 0;
+ };
+} // namespace bsp::watchdog
M module-bsp/board/linux/watchdog/watchdog.cpp => module-bsp/board/linux/watchdog/watchdog.cpp +12 -9
@@ 1,18 1,21 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include "bsp/watchdog/watchdog.hpp"
+#include "software_watchdog.hpp"
#include <bsp/watchdog/watchdog.hpp>
namespace bsp::watchdog
{
- __attribute__((weak)) void init()
- {}
- __attribute__((weak)) void system_reset()
- {}
- __attribute__((weak)) void pet()
- {}
- __attribute__((weak)) std::string reset_cause()
+ static SoftwareWatchdog swWatchdog;
+
+ bool init(unsigned int timeoutMs)
+ {
+ return swWatchdog.init(static_cast<TickType_t>(timeoutMs));
+ }
+
+ void refresh()
{
- return {};
+ swWatchdog.refresh();
}
} // namespace bsp::watchdog
M module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp => module-bsp/board/rt1051/bsp/lpm/RT1051LPM.cpp +1 -2
@@ 40,8 40,7 @@ namespace bsp
int32_t RT1051LPM::Reboot()
{
- bsp::watchdog::init();
- bsp::watchdog::system_reset();
+ NVIC_SystemReset();
return 0;
}
M module-bsp/board/rt1051/bsp/watchdog/watchdog.cpp => module-bsp/board/rt1051/bsp/watchdog/watchdog.cpp +29 -34
@@ 1,50 1,45 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "bsp/watchdog/watchdog.hpp"
extern "C"
{
-#include "../../common/fsl_drivers/fsl_wdog.h"
+#include "fsl_rtwdog.h"
}
-#include <log/log.hpp>
-
-#define WDOG_1_BASE WDOG1
-#define DEMO_WDOG_IRQHandler RTWDOG
+#include <limits>
namespace bsp::watchdog
{
- void init()
- {
- wdog_config_t config;
- WDOG_GetDefaultConfig(&config);
- config.timeoutValue = 0xFF; /* Timeout value is (0xFF + 1)/2 = 125 sec. */
- WDOG_Init(WDOG_1_BASE, &config);
- LOG_INFO("wdog init done-");
- }
- void system_reset()
+ bool init(unsigned int timeoutMs)
{
- LOG_DEBUG("request system reset to watchdog");
- WDOG_TriggerSystemSoftwareReset(WDOG_1_BASE);
- }
+ // 32.768kHz source clock divided by 256 prescaler
+ static constexpr unsigned int clockFreqHz = 32768 / 256;
- void pet()
- {
- WDOG_Refresh(WDOG_1_BASE);
+ const unsigned int timeoutValueTicks = timeoutMs * clockFreqHz / 1000;
+ if (timeoutValueTicks > std::numeric_limits<uint16_t>::max()) {
+ return false;
+ }
+
+ rtwdog_config_t config = {0};
+ config.enableRtwdog = true;
+ config.clockSource = kRTWDOG_ClockSource1; // LPO_CLK clock (32.768kHz)
+ config.prescaler = kRTWDOG_ClockPrescalerDivide256; // 256 prescaler (effectively 128Hz clock)
+ config.workMode.enableWait = false;
+ config.workMode.enableStop = false;
+ config.workMode.enableDebug = false; // If true, RTWDOG will run when target is halted
+ config.testMode = kRTWDOG_TestModeDisabled;
+ config.enableUpdate = true;
+ config.enableInterrupt = false;
+ config.enableWindowMode = false;
+ config.windowValue = 0;
+ config.timeoutValue = static_cast<uint16_t>(timeoutValueTicks);
+ RTWDOG_Init(RTWDOG, &config);
+
+ return true;
}
- // taken straight from example wdog.c in NXP mcuxpresso
- std::string reset_cause()
+ void refresh()
{
- auto resetFlag = WDOG_GetStatusFlags(WDOG_1_BASE);
- switch (resetFlag & (kWDOG_PowerOnResetFlag | kWDOG_TimeoutResetFlag | kWDOG_SoftwareResetFlag)) {
- case kWDOG_PowerOnResetFlag:
- return ("Power On Reset");
- case kWDOG_TimeoutResetFlag:
- return ("Time Out Reset!");
- case kWDOG_SoftwareResetFlag:
- return ("Software Reset!");
- default:
- return ("Error status!");
- }
+ RTWDOG_Refresh(RTWDOG);
}
} // namespace bsp::watchdog
A module-bsp/board/rt1051/common/fsl_drivers/fsl_rtwdog.c => module-bsp/board/rt1051/common/fsl_drivers/fsl_rtwdog.c +151 -0
@@ 0,0 1,151 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2019 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "fsl_rtwdog.h"
+
+/* Component ID definition, used by tools. */
+#ifndef FSL_COMPONENT_ID
+#define FSL_COMPONENT_ID "platform.drivers.rtwdog"
+#endif
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+/*!
+ * brief Clears the RTWDOG flag.
+ *
+ * This function clears the RTWDOG status flag.
+ *
+ * Example to clear an interrupt flag:
+ * code
+ * RTWDOG_ClearStatusFlags(wdog_base,kRTWDOG_InterruptFlag);
+ * endcode
+ * param base RTWDOG peripheral base address.
+ * param mask The status flags to clear.
+ * The parameter can be any combination of the following values:
+ * arg kRTWDOG_InterruptFlag
+ */
+void RTWDOG_ClearStatusFlags(RTWDOG_Type *base, uint32_t mask)
+{
+ if ((mask & (uint32_t)kRTWDOG_InterruptFlag) != 0U)
+ {
+ base->CS |= RTWDOG_CS_FLG_MASK;
+ }
+}
+
+/*!
+ * brief Initializes the RTWDOG configuration structure.
+ *
+ * This function initializes the RTWDOG configuration structure to default values. The default
+ * values are:
+ * code
+ * rtwdogConfig->enableRtwdog = true;
+ * rtwdogConfig->clockSource = kRTWDOG_ClockSource1;
+ * rtwdogConfig->prescaler = kRTWDOG_ClockPrescalerDivide1;
+ * rtwdogConfig->workMode.enableWait = true;
+ * rtwdogConfig->workMode.enableStop = false;
+ * rtwdogConfig->workMode.enableDebug = false;
+ * rtwdogConfig->testMode = kRTWDOG_TestModeDisabled;
+ * rtwdogConfig->enableUpdate = true;
+ * rtwdogConfig->enableInterrupt = false;
+ * rtwdogConfig->enableWindowMode = false;
+ * rtwdogConfig->windowValue = 0U;
+ * rtwdogConfig->timeoutValue = 0xFFFFU;
+ * endcode
+ *
+ * param config Pointer to the RTWDOG configuration structure.
+ * see rtwdog_config_t
+ */
+void RTWDOG_GetDefaultConfig(rtwdog_config_t *config)
+{
+ assert(config != NULL);
+
+ /* Initializes the configure structure to zero. */
+ (void)memset(config, 0, sizeof(*config));
+
+ config->enableRtwdog = true;
+ config->clockSource = kRTWDOG_ClockSource1;
+ config->prescaler = kRTWDOG_ClockPrescalerDivide1;
+ config->workMode.enableWait = true;
+ config->workMode.enableStop = false;
+ config->workMode.enableDebug = false;
+ config->testMode = kRTWDOG_TestModeDisabled;
+ config->enableUpdate = true;
+ config->enableInterrupt = false;
+ config->enableWindowMode = false;
+ config->windowValue = 0U;
+ config->timeoutValue = 0xFFFFU;
+}
+
+/*!
+ * brief Initializes the RTWDOG module.
+ *
+ * This function initializes the RTWDOG.
+ * To reconfigure the RTWDOG without forcing a reset first, enableUpdate must be set to true
+ * in the configuration.
+ *
+ * Example:
+ * code
+ * rtwdog_config_t config;
+ * RTWDOG_GetDefaultConfig(&config);
+ * config.timeoutValue = 0x7ffU;
+ * config.enableUpdate = true;
+ * RTWDOG_Init(wdog_base,&config);
+ * endcode
+ *
+ * param base RTWDOG peripheral base address.
+ * param config The configuration of the RTWDOG.
+ */
+void RTWDOG_Init(RTWDOG_Type *base, const rtwdog_config_t *config)
+{
+ assert(NULL != config);
+
+ uint32_t value = 0U;
+ uint32_t primaskValue = 0U;
+
+ value = RTWDOG_CS_EN(config->enableRtwdog) | RTWDOG_CS_CLK(config->clockSource) |
+ RTWDOG_CS_INT(config->enableInterrupt) | RTWDOG_CS_WIN(config->enableWindowMode) |
+ RTWDOG_CS_UPDATE(config->enableUpdate) | RTWDOG_CS_DBG(config->workMode.enableDebug) |
+ RTWDOG_CS_STOP(config->workMode.enableStop) | RTWDOG_CS_WAIT(config->workMode.enableWait) |
+ RTWDOG_CS_PRES(config->prescaler) | RTWDOG_CS_CMD32EN(1U) | RTWDOG_CS_TST(config->testMode);
+
+ /* Disable the global interrupts. Otherwise, an interrupt could effectively invalidate the unlock sequence
+ * and the WCT may expire. After the configuration finishes, re-enable the global interrupts. */
+ primaskValue = DisableGlobalIRQ();
+ RTWDOG_Unlock(base);
+ base->WIN = config->windowValue;
+ base->TOVAL = config->timeoutValue;
+ base->CS = value;
+ while ((base->CS & RTWDOG_CS_RCS_MASK) == 0U)
+ {
+ }
+ EnableGlobalIRQ(primaskValue);
+}
+
+/*!
+ * brief De-initializes the RTWDOG module.
+ *
+ * This function shuts down the RTWDOG.
+ * Ensure that the WDOG_CS.UPDATE is 1, which means that the register update is enabled.
+ *
+ * param base RTWDOG peripheral base address.
+ */
+void RTWDOG_Deinit(RTWDOG_Type *base)
+{
+ uint32_t primaskValue = 0U;
+
+ /* Disable the global interrupts */
+ primaskValue = DisableGlobalIRQ();
+ RTWDOG_Unlock(base);
+ RTWDOG_Disable(base);
+ EnableGlobalIRQ(primaskValue);
+}
A module-bsp/board/rt1051/common/fsl_drivers/fsl_rtwdog.h => module-bsp/board/rt1051/common/fsl_drivers/fsl_rtwdog.h +425 -0
@@ 0,0 1,425 @@
+/*
+ * Copyright (c) 2016, Freescale Semiconductor, Inc.
+ * Copyright 2016-2020 NXP
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#ifndef _FSL_RTWDOG_H_
+#define _FSL_RTWDOG_H_
+
+#include "fsl_common.h"
+
+/*!
+ * @addtogroup rtwdog
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ *******************************************************************************/
+/*! @name Unlock sequence */
+/*@{*/
+#define WDOG_FIRST_WORD_OF_UNLOCK (RTWDOG_UPDATE_KEY & 0xFFFFU) /*!< First word of unlock sequence */
+#define WDOG_SECOND_WORD_OF_UNLOCK ((RTWDOG_UPDATE_KEY >> 16U) & 0xFFFFU) /*!< Second word of unlock sequence */
+/*@}*/
+
+/*! @name Refresh sequence */
+/*@{*/
+#define WDOG_FIRST_WORD_OF_REFRESH (RTWDOG_REFRESH_KEY & 0xFFFFU) /*!< First word of refresh sequence */
+#define WDOG_SECOND_WORD_OF_REFRESH ((RTWDOG_REFRESH_KEY >> 16U) & 0xFFFFU) /*!< Second word of refresh sequence */
+/*@}*/
+/*! @name Driver version */
+/*@{*/
+/*! @brief RTWDOG driver version 2.1.2. */
+#define FSL_RTWDOG_DRIVER_VERSION (MAKE_VERSION(2, 1, 2))
+/*@}*/
+
+/*! @brief Describes RTWDOG clock source. */
+typedef enum _rtwdog_clock_source
+{
+ kRTWDOG_ClockSource0 = 0U, /*!< Clock source 0 */
+ kRTWDOG_ClockSource1 = 1U, /*!< Clock source 1 */
+ kRTWDOG_ClockSource2 = 2U, /*!< Clock source 2 */
+ kRTWDOG_ClockSource3 = 3U, /*!< Clock source 3 */
+} rtwdog_clock_source_t;
+
+/*! @brief Describes the selection of the clock prescaler. */
+typedef enum _rtwdog_clock_prescaler
+{
+ kRTWDOG_ClockPrescalerDivide1 = 0x0U, /*!< Divided by 1 */
+ kRTWDOG_ClockPrescalerDivide256 = 0x1U, /*!< Divided by 256 */
+} rtwdog_clock_prescaler_t;
+
+/*! @brief Defines RTWDOG work mode. */
+typedef struct _rtwdog_work_mode
+{
+ bool enableWait; /*!< Enables or disables RTWDOG in wait mode */
+ bool enableStop; /*!< Enables or disables RTWDOG in stop mode */
+ bool enableDebug; /*!< Enables or disables RTWDOG in debug mode */
+} rtwdog_work_mode_t;
+
+/*! @brief Describes RTWDOG test mode. */
+typedef enum _rtwdog_test_mode
+{
+ kRTWDOG_TestModeDisabled = 0U, /*!< Test Mode disabled */
+ kRTWDOG_UserModeEnabled = 1U, /*!< User Mode enabled */
+ kRTWDOG_LowByteTest = 2U, /*!< Test Mode enabled, only low byte is used */
+ kRTWDOG_HighByteTest = 3U, /*!< Test Mode enabled, only high byte is used */
+} rtwdog_test_mode_t;
+
+/*! @brief Describes RTWDOG configuration structure. */
+typedef struct _rtwdog_config
+{
+ bool enableRtwdog; /*!< Enables or disables RTWDOG */
+ rtwdog_clock_source_t clockSource; /*!< Clock source select */
+ rtwdog_clock_prescaler_t prescaler; /*!< Clock prescaler value */
+ rtwdog_work_mode_t workMode; /*!< Configures RTWDOG work mode in debug stop and wait mode */
+ rtwdog_test_mode_t testMode; /*!< Configures RTWDOG test mode */
+ bool enableUpdate; /*!< Update write-once register enable */
+ bool enableInterrupt; /*!< Enables or disables RTWDOG interrupt */
+ bool enableWindowMode; /*!< Enables or disables RTWDOG window mode */
+ uint16_t windowValue; /*!< Window value */
+ uint16_t timeoutValue; /*!< Timeout value */
+} rtwdog_config_t;
+
+/*!
+ * @brief RTWDOG interrupt configuration structure.
+ *
+ * This structure contains the settings for all of the RTWDOG interrupt configurations.
+ */
+enum _rtwdog_interrupt_enable_t
+{
+ kRTWDOG_InterruptEnable = RTWDOG_CS_INT_MASK, /*!< Interrupt is generated before forcing a reset */
+};
+
+/*!
+ * @brief RTWDOG status flags.
+ *
+ * This structure contains the RTWDOG status flags for use in the RTWDOG functions.
+ */
+enum _rtwdog_status_flags_t
+{
+ kRTWDOG_RunningFlag = RTWDOG_CS_EN_MASK, /*!< Running flag, set when RTWDOG is enabled */
+ kRTWDOG_InterruptFlag = RTWDOG_CS_FLG_MASK, /*!< Interrupt flag, set when interrupt occurs */
+};
+
+/*******************************************************************************
+ * API
+ *******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus */
+
+/*!
+ * @name RTWDOG Initialization and De-initialization
+ * @{
+ */
+
+/*!
+ * @brief Initializes the RTWDOG configuration structure.
+ *
+ * This function initializes the RTWDOG configuration structure to default values. The default
+ * values are:
+ * @code
+ * rtwdogConfig->enableRtwdog = true;
+ * rtwdogConfig->clockSource = kRTWDOG_ClockSource1;
+ * rtwdogConfig->prescaler = kRTWDOG_ClockPrescalerDivide1;
+ * rtwdogConfig->workMode.enableWait = true;
+ * rtwdogConfig->workMode.enableStop = false;
+ * rtwdogConfig->workMode.enableDebug = false;
+ * rtwdogConfig->testMode = kRTWDOG_TestModeDisabled;
+ * rtwdogConfig->enableUpdate = true;
+ * rtwdogConfig->enableInterrupt = false;
+ * rtwdogConfig->enableWindowMode = false;
+ * rtwdogConfig->windowValue = 0U;
+ * rtwdogConfig->timeoutValue = 0xFFFFU;
+ * @endcode
+ *
+ * @param config Pointer to the RTWDOG configuration structure.
+ * @see rtwdog_config_t
+ */
+void RTWDOG_GetDefaultConfig(rtwdog_config_t *config);
+
+/*!
+ * @brief Initializes the RTWDOG module.
+ *
+ * This function initializes the RTWDOG.
+ * To reconfigure the RTWDOG without forcing a reset first, enableUpdate must be set to true
+ * in the configuration.
+ *
+ * Example:
+ * @code
+ * rtwdog_config_t config;
+ * RTWDOG_GetDefaultConfig(&config);
+ * config.timeoutValue = 0x7ffU;
+ * config.enableUpdate = true;
+ * RTWDOG_Init(wdog_base,&config);
+ * @endcode
+ *
+ * @param base RTWDOG peripheral base address.
+ * @param config The configuration of the RTWDOG.
+ */
+
+#if defined(DOXYGEN_OUTPUT) && DOXYGEN_OUTPUT
+void RTWDOG_Init(RTWDOG_Type *base, const rtwdog_config_t *config);
+#else
+AT_QUICKACCESS_SECTION_CODE(void RTWDOG_Init(RTWDOG_Type *base, const rtwdog_config_t *config));
+#endif
+
+/*!
+ * @brief De-initializes the RTWDOG module.
+ *
+ * This function shuts down the RTWDOG.
+ * Ensure that the WDOG_CS.UPDATE is 1, which means that the register update is enabled.
+ *
+ * @param base RTWDOG peripheral base address.
+ */
+void RTWDOG_Deinit(RTWDOG_Type *base);
+
+/* @} */
+
+/*!
+ * @name RTWDOG functional Operation
+ * @{
+ */
+
+/*!
+ * @brief Enables the RTWDOG module.
+ *
+ * This function writes a value into the WDOG_CS register to enable the RTWDOG.
+ * The WDOG_CS register is a write-once register. Ensure that the WCT window is still open and
+ * this register has not been written in this WCT while the function is called.
+ *
+ * @param base RTWDOG peripheral base address.
+ */
+static inline void RTWDOG_Enable(RTWDOG_Type *base)
+{
+ base->CS |= RTWDOG_CS_EN_MASK;
+}
+
+/*!
+ * @brief Disables the RTWDOG module.
+ *
+ * This function writes a value into the WDOG_CS register to disable the RTWDOG.
+ * The WDOG_CS register is a write-once register. Ensure that the WCT window is still open and
+ * this register has not been written in this WCT while the function is called.
+ *
+ * @param base RTWDOG peripheral base address
+ */
+static inline void RTWDOG_Disable(RTWDOG_Type *base)
+{
+ base->CS &= ~RTWDOG_CS_EN_MASK;
+}
+
+/*!
+ * @brief Enables the RTWDOG interrupt.
+ *
+ * This function writes a value into the WDOG_CS register to enable the RTWDOG interrupt.
+ * The WDOG_CS register is a write-once register. Ensure that the WCT window is still open and
+ * this register has not been written in this WCT while the function is called.
+ *
+ * @param base RTWDOG peripheral base address.
+ * @param mask The interrupts to enable.
+ * The parameter can be a combination of the following source if defined:
+ * @arg kRTWDOG_InterruptEnable
+ */
+static inline void RTWDOG_EnableInterrupts(RTWDOG_Type *base, uint32_t mask)
+{
+ base->CS |= mask;
+}
+
+/*!
+ * @brief Disables the RTWDOG interrupt.
+ *
+ * This function writes a value into the WDOG_CS register to disable the RTWDOG interrupt.
+ * The WDOG_CS register is a write-once register. Ensure that the WCT window is still open and
+ * this register has not been written in this WCT while the function is called.
+ *
+ * @param base RTWDOG peripheral base address.
+ * @param mask The interrupts to disabled.
+ * The parameter can be a combination of the following source if defined:
+ * @arg kRTWDOG_InterruptEnable
+ */
+static inline void RTWDOG_DisableInterrupts(RTWDOG_Type *base, uint32_t mask)
+{
+ base->CS &= ~mask;
+}
+
+/*!
+ * @brief Gets the RTWDOG all status flags.
+ *
+ * This function gets all status flags.
+ *
+ * Example to get the running flag:
+ * @code
+ * uint32_t status;
+ * status = RTWDOG_GetStatusFlags(wdog_base) & kRTWDOG_RunningFlag;
+ * @endcode
+ * @param base RTWDOG peripheral base address
+ * @return State of the status flag: asserted (true) or not-asserted (false). @see _rtwdog_status_flags_t
+ * - true: related status flag has been set.
+ * - false: related status flag is not set.
+ */
+static inline uint32_t RTWDOG_GetStatusFlags(RTWDOG_Type *base)
+{
+ return (base->CS & (RTWDOG_CS_EN_MASK | RTWDOG_CS_FLG_MASK));
+}
+
+/*!
+ * @brief Enables/disables the window mode.
+ *
+ * @param base RTWDOG peripheral base address.
+ * @param enable Enables(true) or disables(false) the feature.
+ */
+static inline void RTWDOG_EnableWindowMode(RTWDOG_Type *base, bool enable)
+{
+ if (enable)
+ {
+ base->CS |= RTWDOG_CS_WIN_MASK;
+ }
+ else
+ {
+ base->CS &= ~RTWDOG_CS_WIN_MASK;
+ }
+}
+
+/*!
+ * @brief Converts raw count value to millisecond.
+ *
+ * Note that if the clock frequency is too high the timeout period can be less than 1 ms.
+ * In this case this api will return 0 value.
+ *
+ * @param base RTWDOG peripheral base address.
+ * @param count Raw count value.
+ * @param clockFreqInHz The frequency of the clock source RTWDOG uses.
+ */
+static inline uint32_t RTWDOG_CountToMesec(RTWDOG_Type *base, uint32_t count, uint32_t clockFreqInHz)
+{
+ if ((base->CS & RTWDOG_CS_PRES_MASK) != 0U)
+ {
+ clockFreqInHz /= 256U;
+ }
+ return count * 1000U / clockFreqInHz;
+}
+
+/*!
+ * @brief Clears the RTWDOG flag.
+ *
+ * This function clears the RTWDOG status flag.
+ *
+ * Example to clear an interrupt flag:
+ * @code
+ * RTWDOG_ClearStatusFlags(wdog_base,kRTWDOG_InterruptFlag);
+ * @endcode
+ * @param base RTWDOG peripheral base address.
+ * @param mask The status flags to clear.
+ * The parameter can be any combination of the following values:
+ * @arg kRTWDOG_InterruptFlag
+ */
+void RTWDOG_ClearStatusFlags(RTWDOG_Type *base, uint32_t mask);
+
+/*!
+ * @brief Sets the RTWDOG timeout value.
+ *
+ * This function writes a timeout value into the WDOG_TOVAL register.
+ * The WDOG_TOVAL register is a write-once register. Ensure that the WCT window is still open and
+ * this register has not been written in this WCT while the function is called.
+ *
+ * @param base RTWDOG peripheral base address
+ * @param timeoutCount RTWDOG timeout value, count of RTWDOG clock ticks.
+ */
+static inline void RTWDOG_SetTimeoutValue(RTWDOG_Type *base, uint16_t timeoutCount)
+{
+ base->TOVAL = timeoutCount;
+}
+
+/*!
+ * @brief Sets the RTWDOG window value.
+ *
+ * This function writes a window value into the WDOG_WIN register.
+ * The WDOG_WIN register is a write-once register. Ensure that the WCT window is still open and
+ * this register has not been written in this WCT while the function is called.
+ *
+ * @param base RTWDOG peripheral base address.
+ * @param windowValue RTWDOG window value.
+ */
+static inline void RTWDOG_SetWindowValue(RTWDOG_Type *base, uint16_t windowValue)
+{
+ base->WIN = windowValue;
+}
+
+/*!
+ * @brief Unlocks the RTWDOG register written.
+ *
+ * This function unlocks the RTWDOG register written.
+ *
+ * Before starting the unlock sequence and following the configuration, disable the global interrupts.
+ * Otherwise, an interrupt could effectively invalidate the unlock sequence and the WCT may expire.
+ * After the configuration finishes, re-enable the global interrupts.
+ *
+ * @param base RTWDOG peripheral base address
+ */
+__STATIC_FORCEINLINE void RTWDOG_Unlock(RTWDOG_Type *base)
+{
+ if (((base->CS) & RTWDOG_CS_CMD32EN_MASK) != 0U)
+ {
+ base->CNT = RTWDOG_UPDATE_KEY;
+ }
+ else
+ {
+ base->CNT = WDOG_FIRST_WORD_OF_UNLOCK;
+ base->CNT = WDOG_SECOND_WORD_OF_UNLOCK;
+ }
+ while ((base->CS & RTWDOG_CS_ULK_MASK) == 0U)
+ {
+ }
+}
+
+/*!
+ * @brief Refreshes the RTWDOG timer.
+ *
+ * This function feeds the RTWDOG.
+ * This function should be called before the Watchdog timer is in timeout. Otherwise, a reset is asserted.
+ *
+ * @param base RTWDOG peripheral base address
+ */
+static inline void RTWDOG_Refresh(RTWDOG_Type *base)
+{
+ uint32_t primaskValue = 0U;
+ primaskValue = DisableGlobalIRQ();
+ if (((base->CS) & RTWDOG_CS_CMD32EN_MASK) != 0U)
+ {
+ base->CNT = RTWDOG_REFRESH_KEY;
+ }
+ else
+ {
+ base->CNT = WDOG_FIRST_WORD_OF_REFRESH;
+ base->CNT = WDOG_SECOND_WORD_OF_REFRESH;
+ }
+ EnableGlobalIRQ(primaskValue);
+}
+
+/*!
+ * @brief Gets the RTWDOG counter value.
+ *
+ * This function gets the RTWDOG counter value.
+ *
+ * @param base RTWDOG peripheral base address.
+ * @return Current RTWDOG counter value.
+ */
+static inline uint16_t RTWDOG_GetCounterValue(RTWDOG_Type *base)
+{
+ return (uint16_t)base->CNT;
+}
+
+/*@}*/
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
+
+/*! @}*/
+
+#endif /* _FSL_RTWDOG_H_ */
M module-bsp/board/rt1051/common/startup_mimxrt1052.cpp => module-bsp/board/rt1051/common/startup_mimxrt1052.cpp +8 -44
@@ 1,6 1,3 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
//*****************************************************************************
// MIMXRT1052 startup code for use with MCUXpresso IDE
//
@@ 72,17 69,15 @@ extern "C"
{
#endif
-//*****************************************************************************
-// Variable to store CRP value in. Will be placed automatically
-// by the linker when "Enable Code Read Protect" selected.
-// See crp.h header for more information
-//*****************************************************************************
-//*****************************************************************************
-// Declaration of external SystemInit function
-//*****************************************************************************
-#if defined(__USE_CMSIS)
+ //*****************************************************************************
+ // Variable to store CRP value in. Will be placed automatically
+ // by the linker when "Enable Code Read Protect" selected.
+ // See crp.h header for more information
+ //*****************************************************************************
+ //*****************************************************************************
+ // Declaration of external SystemInit function
+ //*****************************************************************************
extern void SystemInit(void);
-#endif // (__USE_CMSIS)
//*****************************************************************************
// Forward declaration of the core exception handlers.
@@ 703,24 698,7 @@ __attribute__((section(".after_vectors.reset"))) void ResetISR(void)
// Disable interrupts
__asm volatile("cpsid i");
-#if defined(__USE_CMSIS)
- // If __USE_CMSIS defined, then call CMSIS SystemInit code
SystemInit();
-#else
- // Disable Watchdog
- volatile unsigned int *WDOG1_WCR = (unsigned int *)0x400B8000;
- *WDOG1_WCR = *WDOG1_WCR & ~(1 << 2);
- volatile unsigned int *WDOG2_WCR = (unsigned int *)0x400D0000;
- *WDOG2_WCR = *WDOG2_WCR & ~(1 << 2);
- // Write watchdog update key to unlock
- *((volatile unsigned int *)0x400BC004) = 0xD928C520;
- // Set timeout value
- *((volatile unsigned int *)0x400BC008) = 0xFFFF;
- // Now disable watchdog via control register
- volatile unsigned int *RTWDOG_CS = (unsigned int *)0x400BC000;
- *RTWDOG_CS = (*RTWDOG_CS & ~(1 << 7)) | (1 << 5);
-
-#endif // (__USE_CMSIS)
unsigned int LoadAddr, ExeAddr, SectionLen;
unsigned int *SectionTableAddr;
@@ 747,20 725,6 @@ __attribute__((section(".after_vectors.reset"))) void ResetISR(void)
bss_init(ExeAddr, SectionLen);
}
-#if !defined(__USE_CMSIS)
- // Assume that if __USE_CMSIS defined, then CMSIS SystemInit code
- // will setup the VTOR register
-
- // Check to see if we are running the code from a non-zero
- // address (eg RAM, external flash), in which case we need
- // to modify the VTOR register to tell the CPU that the
- // vector table is located at a non-0x0 address.
- unsigned int *pSCB_VTOR = (unsigned int *)0xE000ED08;
- if ((unsigned int *)g_pfnVectors != (unsigned int *)0x00000000) {
- *pSCB_VTOR = (unsigned int)g_pfnVectors;
- }
-#endif // (__USE_CMSIS)
-
#if defined(__cplusplus)
//
// Call C++ library initialisation
M module-bsp/board/rt1051/common/system_MIMXRT1051.c => module-bsp/board/rt1051/common/system_MIMXRT1051.c +22 -7
@@ 1,3 1,6 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
/*
** ###################################################################
** Processors: MIMXRT1051CVJ5B
@@ 96,23 99,35 @@ void SystemInit(void)
extern uint32_t g_pfnVectors[]; // Vector table defined in startup code
SCB->VTOR = (uint32_t)g_pfnVectors;
- /* Disable Watchdog Power Down Counter */
+ // Disable WDOGx Power Down Counter
WDOG1->WMCR &= ~WDOG_WMCR_PDE_MASK;
WDOG2->WMCR &= ~WDOG_WMCR_PDE_MASK;
- /* Watchdog disable */
-
-#if (DISABLE_WDOG)
+ // Disable WDOGx watchdogs timers
if (WDOG1->WCR & WDOG_WCR_WDE_MASK) {
WDOG1->WCR &= ~WDOG_WCR_WDE_MASK;
}
if (WDOG2->WCR & WDOG_WCR_WDE_MASK) {
WDOG2->WCR &= ~WDOG_WCR_WDE_MASK;
}
- RTWDOG->CNT = 0xD928C520U; /* 0xD928C520U is the update key */
+
+#if defined(DISABLE_WATCHDOG)
+ // Write watchdog update key to unlock
+ RTWDOG->CNT = 0xD928C520U;
+ // Disable RTWDOG and allow configuration updates
RTWDOG->TOVAL = 0xFFFF;
- RTWDOG->CS = (uint32_t)((RTWDOG->CS) & ~RTWDOG_CS_EN_MASK) | RTWDOG_CS_UPDATE_MASK;
-#endif /* (DISABLE_WDOG) */
+ RTWDOG->CS = (uint32_t)(((RTWDOG->CS) & ~RTWDOG_CS_EN_MASK) | RTWDOG_CS_UPDATE_MASK);
+#else
+ //
+ // Perform preliminary RTWDOG configuration
+ //
+ // Write RTWDOG update key to unlock
+ RTWDOG->CNT = 0xD928C520U;
+ // Set timeout value (16s, assuming 128Hz clock - 32.768kHz after 256 prescaler)
+ RTWDOG->TOVAL = 2048;
+ // Enable RTWDOG, set 256 clock prescaler and allow configuration updates
+ RTWDOG->CS = (uint32_t)((RTWDOG->CS) | RTWDOG_CS_EN_MASK | RTWDOG_CS_UPDATE_MASK | RTWDOG_CS_PRES_MASK);
+#endif // (DISABLE_WATCHDOG)
/* Disable Systick which might be enabled by bootrom */
if (SysTick->CTRL & SysTick_CTRL_ENABLE_Msk) {
M module-bsp/board/rt1051/common/system_MIMXRT1051.h => module-bsp/board/rt1051/common/system_MIMXRT1051.h +3 -4
@@ 1,3 1,6 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
/*
** ###################################################################
** Processors: MIMXRT1051CVJ5B
@@ 84,10 87,6 @@ extern "C"
#include <stdint.h>
-#ifndef DISABLE_WDOG
-#define DISABLE_WDOG 1
-#endif
-
/* Define clock source values */
#define CPU_XTAL_CLK_HZ 24000000UL /* Value of the external crystal or oscillator clock frequency in Hz */
M module-bsp/bsp/watchdog/watchdog.hpp => module-bsp/bsp/watchdog/watchdog.hpp +5 -14
@@ 1,19 1,10 @@
-#pragma once
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include <string>
+#pragma once
namespace bsp::watchdog
{
- /// initializes and starts watchdog
- /// - for linux - does nothing
- /// - for rt1051 debug - initializes with maximum value (125 sec)
- /// - for rt1051 release - initializes with maximum value (125 sec)
- void init();
- /// resets system
- /// - for linux - does nothing - consider just exit(0)
- void system_reset();
- /// update watchdog, so that it won't kick us
- void pet();
- /// get watchdog reset cause
- std::string reset_cause();
+ bool init(unsigned int timeoutMs);
+ void refresh();
}
D module-bsp/bsp/watchdog/watchdog_weak.cpp => module-bsp/bsp/watchdog/watchdog_weak.cpp +0 -0
M module-bsp/targets/Target_Linux.cmake => module-bsp/targets/Target_Linux.cmake +2 -0
@@ 30,6 30,8 @@ set(BOARD_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/board/linux/light_sensor/light_sensor.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/board/linux/watchdog/software_watchdog.cpp"
+
"${CMAKE_CURRENT_SOURCE_DIR}/board/linux/watchdog/watchdog.cpp"
CACHE INTERNAL "")
M module-bsp/targets/Target_RT1051.cmake => module-bsp/targets/Target_RT1051.cmake +1 -0
@@ 32,6 32,7 @@ set(BOARD_SOURCES ${BOARD_SOURCES}
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/fsl_drivers/fsl_dmamux.c"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/fsl_drivers/fsl_edma.c"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/fsl_drivers/fsl_wdog.c"
+ "${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/fsl_drivers/fsl_rtwdog.c"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/fsl_drivers/fsl_pwm.c"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/irq/irq_gpio.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/board/rt1051/common/audio.cpp"
M module-sys/CMakeLists.txt => module-sys/CMakeLists.txt +1 -0
@@ 23,6 23,7 @@ set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/DeviceManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/CpuGovernor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SystemManager/graph/TopologicalSort.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/SystemWatchdog/SystemWatchdog.cpp
)
M module-sys/Service/BusProxy.cpp => module-sys/Service/BusProxy.cpp +14 -3
@@ 7,7 7,8 @@
namespace sys
{
- BusProxy::BusProxy(Service *owner) : owner{owner}, busImpl{std::make_unique<Bus>()}
+ BusProxy::BusProxy(Service *owner, Watchdog &watchdog)
+ : owner{owner}, watchdog{watchdog}, busImpl{std::make_unique<Bus>()}
{
channels.push_back(BusChannel::System); // Mandatory for each service.
}
@@ 16,22 17,32 @@ namespace sys
bool BusProxy::sendUnicast(std::shared_ptr<Message> message, const std::string &targetName)
{
- return busImpl->SendUnicast(std::move(message), targetName, owner);
+ auto ret = busImpl->SendUnicast(std::move(message), targetName, owner);
+ if (ret) {
+ watchdog.refresh();
+ }
+ return ret;
}
SendResult BusProxy::sendUnicast(std::shared_ptr<Message> message, const std::string &targetName, uint32_t timeout)
{
- return busImpl->SendUnicast(std::move(message), targetName, owner, timeout);
+ auto ret = busImpl->SendUnicast(std::move(message), targetName, owner, timeout);
+ if (ret.first != ReturnCodes::Failure) {
+ watchdog.refresh();
+ }
+ return ret;
}
void BusProxy::sendMulticast(std::shared_ptr<Message> message, BusChannel channel)
{
busImpl->SendMulticast(std::move(message), channel, owner);
+ watchdog.refresh();
}
void BusProxy::sendBroadcast(std::shared_ptr<Message> message)
{
busImpl->SendBroadcast(std::move(message), owner);
+ watchdog.refresh();
}
void BusProxy::sendResponse(std::shared_ptr<Message> response, std::shared_ptr<Message> request)
M module-sys/Service/BusProxy.hpp => module-sys/Service/BusProxy.hpp +3 -1
@@ 4,6 4,7 @@
#pragma once
#include "Message.hpp"
+#include "Watchdog.hpp"
#include <cstdint>
#include <memory>
@@ 31,13 32,14 @@ namespace sys
private:
friend class Service;
- explicit BusProxy(Service *owner);
+ explicit BusProxy(Service *owner, Watchdog &watchdog);
void sendResponse(std::shared_ptr<Message> response, std::shared_ptr<Message> request);
void connect();
void disconnect();
Service *owner;
+ Watchdog &watchdog;
std::unique_ptr<Bus> busImpl;
};
} // namespace sys
M module-sys/Service/Service.cpp => module-sys/Service/Service.cpp +6 -5
@@ 49,11 49,12 @@ namespace sys
using namespace cpp_freertos;
using namespace std;
- Service::Service(std::string name, std::string parent, uint32_t stackDepth, ServicePriority priority)
+ Service::Service(
+ std::string name, std::string parent, uint32_t stackDepth, ServicePriority priority, Watchdog &watchdog)
: cpp_freertos::Thread(name, stackDepth / 4 /* Stack depth in bytes */, static_cast<UBaseType_t>(priority)),
- parent(parent), bus{this}, mailbox(this), pingTimestamp(UINT32_MAX), isReady(false), enableRunLoop(false)
- {
- }
+ parent(parent), bus(this, watchdog), mailbox(this), watchdog(watchdog), pingTimestamp(UINT32_MAX),
+ isReady(false), enableRunLoop(false)
+ {}
Service::~Service()
{
@@ 148,7 149,7 @@ namespace sys
bool Service::connect(const type_info &type, MessageHandler handler)
{
- auto idx = type_index(type);
+ auto idx = type_index(type);
if (message_handlers.find(idx) == message_handlers.end()) {
LOG_DEBUG("Registering new message handler on %s", type.name());
message_handlers[idx] = handler;
M module-sys/Service/Service.hpp => module-sys/Service/Service.hpp +18 -13
@@ 9,18 9,20 @@
#include "Mailbox.hpp" // for Mailbox
#include "Message.hpp" // for MessagePointer
#include "ServiceManifest.hpp"
-#include "thread.hpp" // for Thread
-#include <algorithm> // for find, max
-#include <cstdint> // for uint32_t, uint64_t
-#include <functional> // for function
-#include <iterator> // for end
-#include <map> // for map
-#include <memory> // for allocator, shared_ptr, enable_shared_from_this
-#include <string> // for string
-#include <typeindex> // for type_index
-#include <utility> // for pair
-#include <vector> // for vector<>::iterator, vector
-#include <typeinfo> // for connect by type
+#include "Watchdog.hpp"
+#include "thread.hpp" // for Thread
+#include <module-sys/SystemWatchdog/SystemWatchdog.hpp> // for SystemWatchdog
+#include <algorithm> // for find, max
+#include <cstdint> // for uint32_t, uint64_t
+#include <functional> // for function
+#include <iterator> // for end
+#include <map> // for map
+#include <memory> // for allocator, shared_ptr, enable_shared_from_this
+#include <string> // for string
+#include <typeindex> // for type_index
+#include <utility> // for pair
+#include <vector> // for vector<>::iterator, vector
+#include <typeinfo> // for connect by type
namespace sys
{
@@ 41,7 43,8 @@ namespace sys
Service(std::string name,
std::string parent = "",
uint32_t stackDepth = 4096,
- ServicePriority priority = ServicePriority::Idle);
+ ServicePriority priority = ServicePriority::Idle,
+ Watchdog &watchdog = SystemWatchdog::getInstance());
~Service() override;
@@ 77,6 80,8 @@ namespace sys
Mailbox<std::shared_ptr<Message>> mailbox;
+ Watchdog &watchdog;
+
uint32_t pingTimestamp;
bool isReady;
A module-sys/Service/Watchdog.hpp => module-sys/Service/Watchdog.hpp +13 -0
@@ 0,0 1,13 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+namespace sys
+{
+ class Watchdog
+ {
+ public:
+ virtual void refresh() = 0;
+ };
+} // namespace sys
M module-sys/Service/details/bus/Bus.cpp => module-sys/Service/details/bus/Bus.cpp +1 -0
@@ 7,6 7,7 @@
#include "Bus.hpp"
#include "module-sys/Service/Service.hpp"
+#include "module-sys/SystemWatchdog/SystemWatchdog.hpp"
#include "module-os/CriticalSectionGuard.hpp"
#include "ticks.hpp"
A module-sys/SystemWatchdog/SystemWatchdog.cpp => module-sys/SystemWatchdog/SystemWatchdog.cpp +75 -0
@@ 0,0 1,75 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "SystemWatchdog.hpp"
+#include "Service/Common.hpp"
+#include "critical.hpp"
+#include "ticks.hpp"
+#include "bsp/watchdog/watchdog.hpp"
+#include "log/log.hpp"
+
+namespace sys
+{
+ using namespace cpp_freertos;
+
+ static constexpr uint16_t stackDepthWords = 256;
+
+ SystemWatchdog::SystemWatchdog()
+ : Thread(threadName, stackDepthWords, static_cast<UBaseType_t>(ServicePriority::High))
+ {}
+
+ SystemWatchdog &SystemWatchdog::getInstance()
+ {
+ static SystemWatchdog watchdog;
+ return watchdog;
+ }
+
+ bool SystemWatchdog::init()
+ {
+#ifdef DISABLE_WATCHDOG
+ return true;
+#else
+ if (!bsp::watchdog::init(watchdogTimeoutPeriod)) {
+ return false;
+ }
+ bsp::watchdog::refresh();
+
+ if (!Start()) {
+ return false;
+ }
+
+ refresh();
+
+ return true;
+#endif
+ }
+
+ void SystemWatchdog::refresh()
+ {
+#ifndef DISABLE_WATCHDOG
+ // Critical section not required (atomic 32-bit writes)
+ lastRefreshTimestamp = Ticks::GetTicks();
+#endif
+ }
+
+ void SystemWatchdog::Run()
+ {
+ while (true) {
+ vTaskDelay(checkPeriod);
+
+ if (timeout_occurred) {
+ continue;
+ }
+
+ // Critical section not required (atomic 32-bit reads)
+ if (Ticks::GetTicks() - lastRefreshTimestamp >= refreshTimeoutPeriod) {
+ // Allow HW watchdog timeout to occur
+ timeout_occurred = true;
+ LOG_FATAL("!!! System watchdog timeout, system will be resetted soon !!!");
+ }
+ else {
+ bsp::watchdog::refresh();
+ }
+ }
+ }
+} // namespace sys
A module-sys/SystemWatchdog/SystemWatchdog.hpp => module-sys/SystemWatchdog/SystemWatchdog.hpp +59 -0
@@ 0,0 1,59 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <module-sys/Service/Watchdog.hpp>
+#include "thread.hpp"
+
+namespace sys
+{
+ //
+ // System watchdog
+ //
+ // System watchdog works in cooperation with an actual watchdog
+ // (HW or simulated). After initialization, it expects to be continually
+ // refreshed within a certain period of time.
+ //
+ // As long as its timing requirements are satisfied, it takes care
+ // of refreshing the actual watchdog so a reset will not occur. Otherwise,
+ // it will allow the actual watchdog to timeout causing a system reset.
+ //
+ class SystemWatchdog : public Watchdog, private cpp_freertos::Thread
+ {
+ public:
+ static constexpr auto threadName = "System_Watchdog";
+
+ SystemWatchdog(const SystemWatchdog &) = delete;
+ SystemWatchdog(SystemWatchdog &&) = delete;
+ SystemWatchdog &operator=(const SystemWatchdog &) = delete;
+ SystemWatchdog &operator=(SystemWatchdog &&) = delete;
+
+ static SystemWatchdog &getInstance();
+
+ // Initialize the actual watchdog and start the thread
+ bool init();
+
+ void refresh() override;
+
+ private:
+ SystemWatchdog();
+
+ // Timeout period for refresh
+ static constexpr TickType_t refreshTimeoutPeriod = pdMS_TO_TICKS(90000);
+ // Timeout period for the actual watchdog
+ static constexpr TickType_t watchdogTimeoutPeriod = pdMS_TO_TICKS(16000);
+ // Period of actual watchdog refresh
+ static constexpr TickType_t checkPeriod = pdMS_TO_TICKS(8000);
+
+ void Run() final;
+
+ TickType_t lastRefreshTimestamp = 0;
+ bool timeout_occurred = false;
+
+ static_assert(sizeof(lastRefreshTimestamp) == 4 && alignof(decltype(lastRefreshTimestamp)) == 4,
+ "SystemWatchdog::lastRefreshTimestamp must be 32-bit long and properly aligned otherwise data "
+ "races may occur");
+ };
+
+} // namespace sys
M source/main.cpp => source/main.cpp +8 -0
@@ 51,6 51,7 @@
#include <phonenumbers/phonenumberutil.h>
#include <source/version.hpp>
#include <SystemManager/SystemManager.hpp>
+#include <SystemWatchdog/SystemWatchdog.hpp>
#include <thread.hpp>
#include <vfs.hpp>
@@ 73,6 74,13 @@ int main()
bsp::BoardInit();
+ if (!sys::SystemWatchdog::getInstance().init()) {
+ LOG_ERROR("System watchdog failed to initialize");
+ // wait for the hardware watchdog (initialized in reset ISR) to reset the system
+ while (1)
+ ;
+ }
+
std::vector<std::unique_ptr<sys::BaseServiceCreator>> systemServices;
systemServices.emplace_back(sys::CreatorFor<EventManager>());
#if ENABLE_FILEINDEXER_SERVICE