lpc_enable_irq();
}
-static void (*wdt_callback)(void) = NULL;
+/* Return 0 if flag is not set, or LPC_WDT_TIMEOUT_FLAG if flag is set.
+ * This function does not clear the flag
+ */
+uint32_t watchdog_check_timeout_flag(void)
+{
+ struct lpc_watchdog* wdt = LPC_WDT;
+ return (wdt->mode & LPC_WDT_TIMEOUT_FLAG);
+}
+
+/* Clear the timeout flag.
+ * No checks performed, clear even if flag is not set
+ */
+void watchdog_clear_timeout_flag(void)
+{
+ struct lpc_watchdog* wdt = LPC_WDT;
+ wdt->mode |= LPC_WDT_TIMEOUT_FLAG;
+}
+
+/* Return current watchdog timer value */
+uint32_t watchdog_get_timer_val(void)
+{
+ struct lpc_watchdog* wdt = LPC_WDT;
+ return wdt->timer_value;
+}
+
+/* Change the watchdog timer value, if not protected */
+void watchdog_set_timer_val(uint32_t nb_clk)
+{
+ struct lpc_watchdog* wdt = LPC_WDT;
+
+ if (!(wdt->mode & LPC_WDT_TIMER_VAL_PROTECT)) {
+ wdt->timer_const = ((nb_clk >> 2) & LPC_WDT_TIMER_MAX);
+ }
+}
+
+
+/***************************************************************************** */
+static void (*wdt_callback)(void) = NULL;
/* With no callback, the watchdog interupt may be used to wake up by generating an interrupt */
void WDT_Handler(void)
}
}
+/***************************************************************************** */
/* Lock the watchdog clock source power.
* Once locked, writes to the current watchdog clock power bits in powerdown_*_cfg will
wdt->mode |= LPC_WDT_TIMER_VAL_PROTECT;
}
-/* Change the watchdog timer value, if not protected */
-void watchdog_set_timer_val(uint32_t nb_clk)
-{
- struct lpc_watchdog* wdt = LPC_WDT;
-
- if (!(wdt->mode & LPC_WDT_TIMER_VAL_PROTECT)) {
- wdt->timer_const = ((nb_clk >> 2) & LPC_WDT_TIMER_MAX);
- }
-}
-
/* Lock the watchdog and all related features.
* Calls all the other watchdog_lock_* functions (clk_src, clk_src_power, timer_val, enable).
*/
watchdog_lock_clk_src_power();
}
+
+
+/***************************************************************************** */
+
/*
* Configure the watchdog.
- * clk_sel is either 0 (IRC) or 1 (WDTCLK). The corresponding clock source will be powered on.
- * Note : only WDTCLK is running in deep power down mode
- * Note : protecting the clock source power will prevent turning off the IRC for power saving
- * if it is selected as main clock source.
+ * The clock to the Watchdog timer is set to 1MHz
*/
void watchdog_config(const struct wdt_config* wd_conf)
{
struct lpc_watchdog* wdt = LPC_WDT;
NVIC_DisableIRQ(WDT_IRQ);
+
/* Power wadchdog block before changing it's configuration */
subsystem_power(LPC_SYS_AHB_CLK_CTRL_Watchdog, 1);
+ /* Configure the watchdog clock source frequency */
+ sys_config->WDT_osc_ctrl = LPC_WDT_CLK_DIVIDER(4) | LPC_WDT_FREQSEL_4MHz; /* 1MHz */
+ /* Power ON Watchdog clock */
+ sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_WDT_OSC);
+
/* Configure watchdog timeout for normal operation */
wdt->timer_const = ((wd_conf->nb_clk >> 2) & LPC_WDT_TIMER_MAX);
+
/* If intr_mode_only is set, a watchdog timeout will trigger an interrupt instead of a reset */
if (wd_conf->intr_mode_only == 1) {
wdt->mode = LPC_WDT_EN;
} else {
wdt->mode = LPC_WDT_EN | LPC_WDT_RESET_ON_TIMEOUT;
}
+
/* Register the callback for the interrupt */
wdt_callback = wd_conf->callback;
- /* Power ON Watchdog clock */
- sys_config->powerdown_run_cfg &= ~(LPC_POWER_DOWN_WDT_OSC);
+
/* Use the windows functionnality ? */
if (wd_conf->wdt_window > 0x100) {
wdt->window_compare = (wd_conf->wdt_window & LPC_WDT_TIMER_MAX);
} else {
wdt->window_compare = LPC_WDT_TIMER_MAX;
}
+
/* Warning interrupt ? */
if (wd_conf->wdt_warn != 0) {
if (wd_conf->wdt_warn > LPC_WDT_WARNINT_MAXVAL) {
wdt->warning_int_compare = wd_conf->wdt_warn;
}
}
+
+ /* Feed sequence to validate the configuration */
+ watchdog_feed();
+
+ /* FIXME : Always enable the interupt ? */
+ NVIC_EnableIRQ(WDT_IRQ);
+
+ /* Wait for watchdog to start before locking (if requested) */
+ do { } while (wdt->timer_value == 0x0000ff);
+
/* Protect any of the watchdog functions now ? */
+ /* FIXME : not working - not tested */
if (wd_conf->locks != 0) {
uint32_t mode = wdt->mode;
if (wd_conf->locks & WDT_CLK_POWER_LOCK) {
if (wd_conf->locks & WDT_TIMER_VAL_LOCK) {
mode |= LPC_WDT_TIMER_VAL_PROTECT;
}
+ /* Wait at least 6 Watchdog clocks before locking */
+ /* FIXME : sleep set to an arbitrary value */
+ usleep(100);
wdt->mode = mode;
}
- /* Feed sequence to validate the configuration */
- watchdog_feed();
- NVIC_EnableIRQ(WDT_IRQ);
}
#include "core/lpc_regs.h"
+
#define WDT_CLK_POWER_LOCK (0x01 << 0)
-#define WDT_EN_LOCK (0x01 << 1)
+#define WDT_EN_LOCK (0x01 << 1) /* Unused for LPC82x */
#define WDT_TIMER_VAL_LOCK (0x01 << 2)
+
+/* NOTE : The clock to the Watchdog timer is set to 1MHz */
+
struct wdt_config {
uint8_t clk_sel; /* Unused, only here for API compatibility */
uint8_t intr_mode_only; /* If set to 1, a watchdog timeout will trigger an interrupt instead of a reset */
void (*callback)(void);
- uint32_t locks; /* Bitfield from WDT_*_LOCK defined in watchdog.h */
+ uint32_t locks; /* Bitfield from WDT_*_LOCK defined above this struct */
/* Number of clk_src clocks before the watchdog timer times out. Will be divided by 4 to give
* the watchdog reload value */
uint32_t nb_clk; /* 0x3FF to 0x03FFFFFF */
uint16_t wdt_warn; /* 0x00 to 0x3FF */
};
+
+
/***************************************************************************** */
void watchdog_feed(void);
+/***************************************************************************** */
+/* Return 0 if flag is not set, or LPC_WDT_TIMEOUT_FLAG if flag is set.
+ * This function does not clear the flag
+ */
+uint32_t watchdog_check_timeout_flag(void);
+
+/* Clear the timeout flag.
+ * No checks performed, clear even if flag is not set
+ */
+void watchdog_clear_timeout_flag(void);
+
+/* Return current watchdog timer value */
+uint32_t watchdog_get_timer_val(void);
+
+/* Change the watchdog timer value, if not protected */
+void watchdog_set_timer_val(uint32_t nb_clk);
+
+
+/***************************************************************************** */
/* Lock the watchdog clock source power.
* Once locked, writes to the current watchdog clock power bits in powerdown_*_cfg will
* have no effect.
/* Lock the watchdog timer value */
void watchdog_lock_timer_val(void);
-/* Change the watchdog timer value, if not protected */
-void watchdog_set_timer_val(uint32_t nb_clk);
-
/* Lock the watchdog and all related features.
* Calls all the other watchdog_lock_* functions (clk_src, clk_src_power, timer_val, enable).
*/
void watchdog_lock_full(void);
+
+/***************************************************************************** */
/*
* Configure the watchdog.
- * clk_sel is either 0 (IRC) or 1 (WDTCLK). The corresponding clock source will be powered on.
- * Note : only WDTCLK is running in deep power down mode
- * Note : protecting the clock source power will prevent turning off the IRC for power saving
- * if it is selected as main clock source.
+ * The clock to the Watchdog timer is set to 1MHz
*/
void watchdog_config(const struct wdt_config* wd_conf);
-
/*
* Stop the watchdog
* This function can be used during system operation to stop the watchdog if it has not
*/
int stop_watchdog(void);
-
/*
* Disable the watchdog
* This function can be used upon system startup to disable watchdog operation