/* Reflow Oven Controller * * Copyright (C) 2020 Mario Hüttel * * This file is part of the Reflow Oven Controller Project. * * The reflow oven controller is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * The Reflow Oven Control Firmware is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the reflow oven controller project. * If not, see . */ /** * @addtogroup watchdog * @{ */ #include #include /** * @brief This key is expected by hardware to be written to the IWDG_KR register in order to reset the watchdog */ #define STM32_WATCHDOG_RESET_KEY 0xAAAA /** * @brief This key is expected by hardware to be written to the IWDG_KR register in order to enable the watchdog */ #define STM32_WATCHDOG_ENABLE_KEY 0xCCCC /** * @brief This key is expected by hardware to be written to the IWDG_KR register in order to enable access to config * registers */ #define STM32_WATCHDOG_REGISTER_ACCESS_KEY 0x5555 int watchdog_setup(uint16_t prescaler, uint16_t reload_value) { uint32_t prescaler_reg_val; int ret = 0; /** - Activate the LSI oscillator */ RCC->CSR |= RCC_CSR_LSION; __DSB(); /** - Wait for the oscillator to be ready */ while (!(RCC->CSR & RCC_CSR_LSIRDY)) ; if (prescaler == 4U) { prescaler_reg_val = 0UL; } else if (prescaler == 8U) { prescaler_reg_val = 1UL; } else if (prescaler == 16U) { prescaler_reg_val = 2UL; } else if (prescaler == 32U) { prescaler_reg_val = 3UL; } else if (prescaler == 64U) { prescaler_reg_val = 4UL; } else if (prescaler == 128U) { prescaler_reg_val = 5UL; } else if (prescaler == 256U) { prescaler_reg_val = 6UL; } else { prescaler_reg_val = 6UL; ret = -1; } /** - (De)activate the watchdog during debug access according to @ref WATCHDOG_HALT_DEBUG */ if (WATCHDOG_HALT_DEBUG) DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_IWDG_STOP; else DBGMCU->APB1FZ &= ~DBGMCU_APB1_FZ_DBG_IWDG_STOP; /** - Unlock registers */ IWDG->KR = STM32_WATCHDOG_REGISTER_ACCESS_KEY; /** - Wait until prescaler can be written */ while (IWDG->SR & IWDG_SR_PVU) ; /** - Write prescaler value */ IWDG->PR = prescaler_reg_val; /* - Wait until reload value can be written */ while (IWDG->SR & IWDG_SR_RVU) ; /** - Set reload value */ if (reload_value > 0xFFFu) { reload_value = 0xFFFFu; ret = -2; } IWDG->RLR = reload_value; /** - Write enable key */ IWDG->KR = STM32_WATCHDOG_ENABLE_KEY; /** - Do a first reset of the counter. This also locks the config regs */ watchdog_ack(WATCHDOG_MAGIC_KEY); return ret; } int watchdog_ack(uint32_t magic) { int ret = -1; /** - Check if magic key is correct */ if (magic == WATCHDOG_MAGIC_KEY) { /** - Write reset key to watchdog */ IWDG->KR = STM32_WATCHDOG_RESET_KEY; ret = 0; } return ret; } /** @} */