aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Sarkies2012-06-13 22:14:53 +0930
committerKen Sarkies2012-06-13 22:14:53 +0930
commit2f4cd293248b012c87be34d4f45786b7f8c06770 (patch)
treea91108043e870a55094e566de2156acacced3d08
parent7011d47c70076f995e8470c59eeaa8f3efcc9f05 (diff)
Code for iwdg module STM32F series
-rw-r--r--include/libopencm3/stm32/iwdg.h8
-rw-r--r--lib/stm32/iwdg.c146
2 files changed, 152 insertions, 2 deletions
diff --git a/include/libopencm3/stm32/iwdg.h b/include/libopencm3/stm32/iwdg.h
index 2d24482..2a8ee9d 100644
--- a/include/libopencm3/stm32/iwdg.h
+++ b/include/libopencm3/stm32/iwdg.h
@@ -78,8 +78,12 @@
/* PVU: Watchdog prescaler value update */
#define IWDG_SR_PVU (1 << 0)
-/* --- IWDG funtion prototypes---------------------------------------------- */
+/* --- IWDG function prototypes---------------------------------------------- */
-/* TODO */
+void iwdg_start(void);
+void iwdg_set_period_ms(u32 period);
+bool iwdg_reload_busy(void);
+bool iwdg_prescaler_busy(void);
+void iwdg_reset(void);
#endif
diff --git a/lib/stm32/iwdg.c b/lib/stm32/iwdg.c
new file mode 100644
index 0000000..a4a15ec
--- /dev/null
+++ b/lib/stm32/iwdg.c
@@ -0,0 +1,146 @@
+/** @file
+
+@ingroup STM32F
+
+@brief <b>libopencm3 STM32F1xx Independent Watchdog Timer</b>
+
+@version 1.0.0
+
+@author @htmlonly &copy; @endhtmlonly 2012 Ken Sarkies ksarkies@internode.on.net
+
+@date 11 June 2012
+
+This library supports the Independent Watchdog Timer System in the STM32F1xx
+series of ARM Cortex Microcontrollers by ST Microelectronics.
+
+The watchdog timer uses the LSI (low speed internal) clock which is low power
+and continues to operate during stop and standby modes. Its frequency is
+nominally 32kHz (40kHz for the STM32F1xx series) but can vary from as low
+as 17kHz up to 60kHz (refer to datasheet electrical characteristics).
+
+Note that the User Configuration option byte provides a means of automatically
+enabling the IWDG timer at power on (with counter value 0xFFF). If the
+relevant bit is not set, the IWDG timer must be enabled by software.
+
+@bugs None known
+
+@note: Tested: CPU STM32F103RET6, Board ET-ARM Stamp STM32
+
+LGPL License Terms @ref lgpl_license
+ */
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libopencm3/stm32/iwdg.h>
+
+#define LSI_FREQUENCY 32000
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG Enable Watchdog Timer
+
+The watchdog timer is started. The timeout period defaults to 512 milliseconds
+unless it has been previously defined.
+
+*/
+
+void iwdg_start(void)
+{
+ IWDG_KR = IWDG_KR_START;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG Set Period in Milliseconds
+
+The countdown period is converted into count and prescale values. The maximum
+period is 32.76 seconds; values above this are truncated. Periods less than 1ms
+are not supported by this library.
+
+A delay of up to 5 clock cycles of the LSI clock (about 156 microseconds)
+can occasionally occur if the prescale or preload registers are currently busy
+loading a previous value.
+
+@param[in] u32 Period in milliseconds (< 32760) from a watchdog reset until
+a system reset is issued.
+*/
+
+#define COUNT_LENGTH 12
+#define COUNT_MASK ((1 << COUNT_LENGTH)-1)
+
+void iwdg_set_period_ms(u32 period)
+{
+u32 count, prescale, reload, exponent;
+/* Set the count to represent ticks of the 32kHz LSI clock */
+ count = (period << 5);
+/* Strip off the first 12 bits to get the prescale value required */
+ prescale = (count >> 12);
+ if (prescale > 256) {exponent = IWDG_PR_DIV256; reload = COUNT_MASK;}
+ else if (prescale > 128) {exponent = IWDG_PR_DIV256; reload = (count >> 8);}
+ else if (prescale > 64) {exponent = IWDG_PR_DIV128; reload = (count >> 7);}
+ else if (prescale > 32) {exponent = IWDG_PR_DIV64; reload = (count >> 6);}
+ else if (prescale > 16) {exponent = IWDG_PR_DIV32; reload = (count >> 5);}
+ else if (prescale > 8) {exponent = IWDG_PR_DIV16; reload = (count >> 4);}
+ else if (prescale > 4) {exponent = IWDG_PR_DIV8; reload = (count >> 3);}
+ else {exponent = IWDG_PR_DIV4; reload = (count >> 2);}
+/* Avoid the undefined situation of a zero count */
+ if (count == 0) count = 1;
+
+ while (iwdg_prescaler_busy());
+ IWDG_KR = IWDG_KR_UNLOCK;
+ IWDG_PR = exponent;
+ while (iwdg_reload_busy());
+ IWDG_KR = IWDG_KR_UNLOCK;
+ IWDG_RLR = (reload & COUNT_MASK);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG Get Reload Register Status
+
+@returns boolean: TRUE if the reload register is busy and unavailable for loading
+a new count value.
+*/
+
+bool iwdg_reload_busy(void)
+{
+ return (IWDG_SR & IWDG_SR_RVU);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG Get Prescaler Register Status
+
+@returns boolean: TRUE if the prescaler register is busy and unavailable for loading
+a new period value.
+*/
+
+bool iwdg_prescaler_busy(void)
+{
+ return (IWDG_SR & IWDG_SR_PVU);
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief IWDG reset Watchdog Timer
+
+The watchdog timer is reset. The counter restarts from the value in the reload
+register.
+*/
+
+void iwdg_reset(void)
+{
+ IWDG_KR = IWDG_KR_RESET;
+}
+