diff options
-rw-r--r-- | libmaple/iwdg.c | 41 | ||||
-rw-r--r-- | libmaple/iwdg.h | 85 |
2 files changed, 88 insertions, 38 deletions
diff --git a/libmaple/iwdg.c b/libmaple/iwdg.c index 82a0151..3d67ee8 100644 --- a/libmaple/iwdg.c +++ b/libmaple/iwdg.c @@ -23,34 +23,37 @@ *****************************************************************************/ /** - * @file iwdg.c - * - * @brief Independent watchdog support + * @file iwdg.c + * @brief Independent watchdog (IWDG) support */ -#include "libmaple.h" #include "iwdg.h" -#define IWDG_UNLOCK 0x5555 -#define IWDG_START 0xCCCC -#define IWDG_FEED 0xAAAA - /** - * @brief Initialise and start the watchdog + * @brief Initialise and start the watchdog + * + * The prescaler and reload set the timeout. A prescaler of 3 divides + * the 40 kHz clock by 32 and gives roughly 1 ms per reload. * - * The prescaler and reload set the timeout. A prescaler of 3 divides - * the 40 kHz clock by 32 and gives roughly 1 ms per reload. + * @param prescaler Prescaler for the 40 KHz IWDG clock. + * @param reload Independent watchdog counter reload value. */ -void iwdg_init(uint8 prescaler, uint16 reload) { - __write(IWDG_KR, IWDG_UNLOCK); - __write(IWDG_PR, prescaler); - __write(IWDG_RLR, reload); +void iwdg_init(iwdg_prescaler prescaler, uint16 reload) { + IWDG_BASE->KR = IWDG_KR_UNLOCK; + IWDG_BASE->PR = prescaler; + IWDG_BASE->RLR = reload; - /* Start things off */ - __write(IWDG_KR, IWDG_START); - __write(IWDG_KR, IWDG_FEED); + /* Start things off */ + IWDG_BASE->KR = IWDG_KR_START; + iwdg_feed(); } +/** + * @brief Reset the IWDG counter. + * + * Calling this function will cause the IWDG counter to be reset to + * its reload value. + */ void iwdg_feed(void) { - __write(IWDG_KR, IWDG_FEED); + IWDG_BASE->KR = IWDG_KR_FEED; } diff --git a/libmaple/iwdg.h b/libmaple/iwdg.h index 4ab0ddf..81f0fdb 100644 --- a/libmaple/iwdg.h +++ b/libmaple/iwdg.h @@ -23,35 +23,82 @@ *****************************************************************************/ /** - * @file iwdg.h + * @file iwdg.h + * @author Michael Hope, Marti Bolivar <mbolivar@leaflabs.com> + * @brief Independent watchdog support. * - * @brief Independent watchdog support + * To use the independent watchdog, first call iwdg_init() with the + * appropriate prescaler and IWDG counter reload values for your + * application. Afterwards, you must periodically call iwdg_feed() + * before the IWDG counter reaches 0 to reset the counter to its + * reload value. If you do not, the chip will reset. + * + * Once started, the independent watchdog cannot be turned off. */ #ifndef _IWDG_H_ #define _IWDG_H_ +#include "libmaple_types.h" + #ifdef __cplusplus extern "C"{ #endif -#define IWDG_BASE 0x40003000 -#define IWDG_KR (IWDG_BASE + 0x0) -#define IWDG_PR (IWDG_BASE + 0x4) -#define IWDG_RLR (IWDG_BASE + 0x8) -#define IWDG_SR (IWDG_BASE + 0xC) - -enum { - IWDG_PRE_4, - IWDG_PRE_8, - IWDG_PRE_16, - IWDG_PRE_32, - IWDG_PRE_64, - IWDG_PRE_128, - IWDG_PRE_256 -}; - -void iwdg_init(uint8 prescaler, uint16 reload); +/* + * Register map + */ + +/** Independent watchdog register map type. */ +typedef struct iwdg_reg_map { + __io uint32 KR; /**< Key register. */ + __io uint32 PR; /**< Prescaler register. */ + __io uint32 RLR; /**< Reload register. */ + __io uint32 SR; /**< Status register */ +} iwdg_reg_map; + +#define IWDG_BASE ((struct iwdg_reg_map*)0x40003000) + +/* + * Register bit definitions + */ + +/* Key register */ + +#define IWDG_KR_UNLOCK 0x5555 +#define IWDG_KR_FEED 0xAAAA +#define IWDG_KR_START 0xCCCC + +/* Prescaler register */ + +#define IWDG_PR_DIV_4 0x0 +#define IWDG_PR_DIV_8 0x1 +#define IWDG_PR_DIV_16 0x2 +#define IWDG_PR_DIV_32 0x3 +#define IWDG_PR_DIV_64 0x4 +#define IWDG_PR_DIV_128 0x5 +#define IWDG_PR_DIV_256 0x6 + +/* Status register */ + +#define IWDG_SR_RVU_BIT 1 +#define IWDG_SR_PVU_BIT 0 + +#define IWDG_SR_RVU BIT(IWDG_SR_RVU_BIT) +#define IWDG_SR_PVU BIT(IWDG_SR_PVU_BIT) + +/** Independent watchdog prescalers */ +typedef enum { + IWDG_PRE_4 = IWDG_PR_DIV_4, + IWDG_PRE_8 = IWDG_PR_DIV_8, + IWDG_PRE_16 = IWDG_PR_DIV_16, + IWDG_PRE_32 = IWDG_PR_DIV_32, + IWDG_PRE_64 = IWDG_PR_DIV_64, + IWDG_PRE_128 = IWDG_PR_DIV_128, + IWDG_PRE_256 = IWDG_PR_DIV_256 +} iwdg_prescaler; + +void iwdg_init(iwdg_prescaler prescaler, uint16 reload); void iwdg_feed(void); #ifdef __cplusplus |