1 /***************************************************************************//**
2 * @file
3 * @brief Watchdog (WDOG) peripheral API
4 * devices.
5 * @author Energy Micro AS
6 * @version 3.0.0
7 *******************************************************************************
8 * @section License
9 * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
10 *******************************************************************************
11 *
12 * Permission is granted to anyone to use this software for any purpose,
13 * including commercial applications, and to alter it and redistribute it
14 * freely, subject to the following restrictions:
15 *
16 * 1. The origin of this software must not be misrepresented; you must not
17 * claim that you wrote the original software.
18 * 2. Altered source versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software.
20 * 3. This notice may not be removed or altered from any source distribution.
21 *
22 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
23 * obligation to support this Software. Energy Micro AS is providing the
24 * Software "AS IS", with no express or implied warranties of any kind,
25 * including, but not limited to, any implied warranties of merchantability
26 * or fitness for any particular purpose or warranties against infringement
27 * of any proprietary rights of a third party.
28 *
29 * Energy Micro AS will not be liable for any consequential, incidental, or
30 * special damages, or any other relief, or for any claim by any third party,
31 * arising from your use of this Software.
32 *
33 ******************************************************************************/
34 #include "em_wdog.h"
35 #include "em_bitband.h"
36
37 /***************************************************************************//**
38 * @addtogroup EM_Library
39 * @{
40 ******************************************************************************/
41
42 /***************************************************************************//**
43 * @addtogroup WDOG
44 * @brief Watchdog (WDOG) Peripheral API
45 * @{
46 ******************************************************************************/
47
48 /*******************************************************************************
49 ************************** GLOBAL FUNCTIONS *******************************
50 ******************************************************************************/
51
52 /***************************************************************************//**
53 * @brief
54 * Enable/disable the watchdog timer.
55 *
56 * @note
57 * This function modifies the WDOG CTRL register which requires
58 * synchronization into the low frequency domain. If this register is modified
59 * before a previous update to the same register has completed, this function
60 * will stall until the previous synchronization has completed.
61 *
62 * @param[in] enable
63 * true to enable watchdog, false to disable. Watchdog cannot be disabled if
64 * watchdog has been locked.
65 ******************************************************************************/
WDOG_Enable(bool enable)66 void WDOG_Enable(bool enable)
67 {
68 if (!enable)
69 {
70 /* Wait for any pending previous write operation to have been completed in */
71 /* low frequency domain */
72 while (WDOG->SYNCBUSY & WDOG_SYNCBUSY_CTRL)
73 ;
74 }
75 BITBAND_Peripheral(&(WDOG->CTRL), _WDOG_CTRL_EN_SHIFT, (unsigned int)enable);
76 }
77
78
79 /***************************************************************************//**
80 * @brief
81 * Feed the watchdog.
82 *
83 * @details
84 * When the watchdog is activated, it must be fed (ie clearing the counter)
85 * before it reaches the defined timeout period. Otherwise, the watchdog
86 * will generate a reset.
87 ******************************************************************************/
WDOG_Feed(void)88 void WDOG_Feed(void)
89 {
90 /* If a previous clearing is being synchronized to LF domain, then there */
91 /* is no point in waiting for it to complete before clearing over again. */
92 /* This avoids stalling the core in the typical use case where some idle loop */
93 /* keeps clearing the watchdog. */
94 if (WDOG->SYNCBUSY & WDOG_SYNCBUSY_CMD)
95 return;
96
97 WDOG->CMD = WDOG_CMD_CLEAR;
98 }
99
100
101 /***************************************************************************//**
102 * @brief
103 * Initialize watchdog (assuming the watchdog configuration has not been
104 * locked).
105 *
106 * @note
107 * This function modifies the WDOG CTRL register which requires
108 * synchronization into the low frequency domain. If this register is modified
109 * before a previous update to the same register has completed, this function
110 * will stall until the previous synchronization has completed.
111 *
112 * @param[in] init
113 * Structure holding watchdog configuration. A default setting
114 * #WDOG_INIT_DEFAULT is available for init.
115 ******************************************************************************/
WDOG_Init(const WDOG_Init_TypeDef * init)116 void WDOG_Init(const WDOG_Init_TypeDef *init)
117 {
118 uint32_t setting;
119
120 if (init->enable)
121 {
122 setting = WDOG_CTRL_EN;
123 }
124 else
125 {
126 setting = 0;
127 }
128
129 if (init->debugRun)
130 {
131 setting |= WDOG_CTRL_DEBUGRUN;
132 }
133
134 if (init->em2Run)
135 {
136 setting |= WDOG_CTRL_EM2RUN;
137 }
138
139 if (init->em3Run)
140 {
141 setting |= WDOG_CTRL_EM3RUN;
142 }
143
144 if (init->em4Block)
145 {
146 setting |= WDOG_CTRL_EM4BLOCK;
147 }
148
149 if (init->swoscBlock)
150 {
151 setting |= WDOG_CTRL_SWOSCBLOCK;
152 }
153
154 setting |= ((uint32_t)(init->clkSel) << _WDOG_CTRL_CLKSEL_SHIFT) |
155 ((uint32_t)(init->perSel) << _WDOG_CTRL_PERSEL_SHIFT);
156
157 /* Wait for any pending previous write operation to have been completed in */
158 /* low frequency domain */
159 while (WDOG->SYNCBUSY & WDOG_SYNCBUSY_CTRL)
160 ;
161
162 WDOG->CTRL = setting;
163
164 /* Optional register locking */
165 if (init->lock)
166 {
167 if (init->enable)
168 {
169 WDOG_Lock();
170 }
171 else
172 {
173 BITBAND_Peripheral(&(WDOG->CTRL), _WDOG_CTRL_LOCK_SHIFT, 1);
174 }
175 }
176 }
177
178
179 /***************************************************************************//**
180 * @brief
181 * Lock the watchdog configuration.
182 *
183 * @details
184 * This prevents errors from overwriting the watchdog configuration, possibly
185 * disabling it. Only a reset can unlock the watchdog config, once locked.
186 *
187 * If the LFRCO or LFXO clocks are used to clock the watchdog, one should
188 * consider using the option of inhibiting those clocks to be disabled,
189 * please see the WDOG_Enable() init structure.
190 *
191 * @note
192 * This function modifies the WDOG CTRL register which requires
193 * synchronization into the low frequency domain. If this register is modified
194 * before a previous update to the same register has completed, this function
195 * will stall until the previous synchronization has completed.
196 ******************************************************************************/
WDOG_Lock(void)197 void WDOG_Lock(void)
198 {
199 /* Wait for any pending previous write operation to have been completed in */
200 /* low frequency domain */
201 while (WDOG->SYNCBUSY & WDOG_SYNCBUSY_CTRL)
202 ;
203
204 /* Disable writing to the control register */
205 BITBAND_Peripheral(&(WDOG->CTRL), _WDOG_CTRL_LOCK_SHIFT, 1);
206 }
207
208
209 /** @} (end addtogroup WDOG) */
210 /** @} (end addtogroup EM_Library) */
211