71 lines
1.6 KiB
C
71 lines
1.6 KiB
C
#include <libopencm3/stm32/rcc.h>
|
|
#include <libopencm3/stm32/wwdg.h>
|
|
|
|
#include <libcommon/watchdog.h>
|
|
|
|
void watchdog_refresh(void)
|
|
{
|
|
/* set to the maximum a 7-bit counter supports */
|
|
WWDG_CR = 0x7f;
|
|
}
|
|
|
|
#ifdef DEBUG_WATCHDOG
|
|
void WWDG_IRQHandler(void)
|
|
{
|
|
WWDG_ClearFlag();
|
|
|
|
/* instead of triggering a reset, we hang in this endless loop to wait
|
|
* for openocd/gdb attach and investigation of the stack */
|
|
watchdog_fini();
|
|
printf("WWDG\r\n");
|
|
while(1) {}
|
|
}
|
|
#endif
|
|
|
|
void watchdog_fini(void)
|
|
{
|
|
/* documentation claims we cannot stop it. lol. */
|
|
watchdog_refresh();
|
|
rcc_periph_clock_disable(RCC_WWDG);
|
|
}
|
|
|
|
int watchdog_init(void)
|
|
{
|
|
#ifdef RCC_DBGMCU
|
|
/* make sure the watchdog stops during JTAG stop */
|
|
rcc_periph_clock_enable(RCC_DBGMCU);
|
|
DBGMCU_CR |= DBGMCU_CR_WWDG_STOP
|
|
#endif
|
|
|
|
rcc_periph_clock_enable(RCC_WWDG);
|
|
|
|
/* Set WWDG clock to (PCLK1/4096)/8 */
|
|
/* At 8 MHz PCLK1 this is 244.14 Hz */
|
|
WWDG_CFR = (WWDG_CFR & ~WWDG_CFR_WDGTB_LSB) | WWDG_CFR_WDGTB_CK_DIV8;
|
|
|
|
|
|
#ifdef DEBUG_WATCHDOG
|
|
NVIC_InitTypeDef nvic_init = {
|
|
.NVIC_IRQChannelPriority = 0,
|
|
.NVIC_IRQChannel = WWDG_IRQn,
|
|
.NVIC_IRQChannelCmd = ENABLE,
|
|
};
|
|
WWDG_EnableIT();
|
|
NVIC_Init(&nvic_init);
|
|
#endif
|
|
|
|
/* highest possible window value */
|
|
WWDG_CFR = (WWDG_CFR & WWDG_CFR_WDGTB_LSB) | 0x7f;
|
|
|
|
/* this means, that we have 0x80-0x40= 64 cycles of the 214.14Hz
|
|
* watchdog clock tore-fresh the counter, before it reaches
|
|
* 0x3F, at which point a reset will be issued to the CPU. If my
|
|
* calculations are correct, this is 0.262 seconds, i.e.
|
|
* refreshing every time the systick timer fires (and we return
|
|
* to the main loop) should be sufficient. */
|
|
|
|
WWDG_CR = WWDG_CR_WDGA | 0x7f;
|
|
|
|
return 0;
|
|
}
|