1 /**
2 * \file
3 *
4 * \brief SAM Brown Out Detector Driver
5 *
6 * Copyright (C) 2013-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46 #ifndef BOD_FEATURE_H_INCLUDED
47 #define BOD_FEATURE_H_INCLUDED
48
49
50 #ifdef __cplusplus
51 extern "C" {
52 #endif
53
54 /**
55 * \defgroup asfdoc_sam0_bod_group SAM Brown Out Detector (BOD) Driver
56 *
57 * This driver for Atmel® | SMART ARM®-based microcontrollers provides an interface for the configuration
58 * and management of the device's Brown Out Detector (BOD) modules, to detect
59 * and respond to under-voltage events and take an appropriate action.
60 *
61 * The following peripheral is used by this module:
62 * - SYSCTRL (System Control)
63 *
64 * The following devices can use this module:
65 * - Atmel | SMART SAM D20/D21
66 * - Atmel | SMART SAM R21
67 * - Atmel | SMART SAM D10/D11
68 * - Atmel | SMART SAM DA1
69 * - Atmel | SMART SAM HA1
70 *
71 * The outline of this documentation is as follows:
72 * - \ref asfdoc_sam0_bod_prerequisites
73 * - \ref asfdoc_sam0_bod_module_overview
74 * - \ref asfdoc_sam0_bod_special_considerations
75 * - \ref asfdoc_sam0_bod_extra_info
76 * - \ref asfdoc_sam0_bod_examples
77 * - \ref asfdoc_sam0_bod_api_overview
78 *
79 *
80 * \section asfdoc_sam0_bod_prerequisites Prerequisites
81 *
82 * There are no prerequisites for this module.
83 *
84 *
85 * \section asfdoc_sam0_bod_module_overview Module Overview
86 *
87 * The SAM devices contain a number of Brown Out Detector (BOD) modules.
88 * Each BOD monitors the supply voltage for any dips that go below the set
89 * threshold for the module. In case of a BOD detection the BOD will either
90 * reset the system or raise a hardware interrupt so that a safe power-down
91 * sequence can be attempted.
92 *
93 *
94 * \section asfdoc_sam0_bod_special_considerations Special Considerations
95 *
96 * The time between a BOD interrupt being raised and a failure of the processor
97 * to continue executing (in the case of a core power failure) is system
98 * specific; care must be taken that all critical BOD detection events can
99 * complete within the amount of time available.
100 *
101 * \section asfdoc_sam0_bod_extra_info Extra Information
102 *
103 * For extra information, see \ref asfdoc_sam0_bod_extra. This includes:
104 * - \ref asfdoc_sam0_bod_extra_acronyms
105 * - \ref asfdoc_sam0_bod_extra_dependencies
106 * - \ref asfdoc_sam0_bod_extra_errata
107 * - \ref asfdoc_sam0_bod_extra_history
108 *
109 *
110 * \section asfdoc_sam0_bod_examples Examples
111 *
112 * For a list of examples related to this driver, see
113 * \ref asfdoc_sam0_bod_exqsg.
114 *
115 *
116 * \section asfdoc_sam0_bod_api_overview API Overview
117 * @{
118 */
119
120 /**
121 * \brief Brown Out Detector hardware instance IDs.
122 *
123 * List of possible BOD controllers within the device.
124 */
125 enum bod {
126 /** BOD33 External I/O voltage */
127 BOD_BOD33,
128 };
129
130 /**
131 * \brief Brown Out Detector input clock prescale values.
132 *
133 * List of possible BOD controller prescaler values, to reduce the sampling
134 * speed of a BOD to lower the power consumption.
135 */
136 enum bod_prescale {
137 /** Divide input prescaler clock by 2 */
138 BOD_PRESCALE_DIV_2 = SYSCTRL_BOD33_PSEL(0),
139 /** Divide input prescaler clock by 4 */
140 BOD_PRESCALE_DIV_4 = SYSCTRL_BOD33_PSEL(1),
141 /** Divide input prescaler clock by 8 */
142 BOD_PRESCALE_DIV_8 = SYSCTRL_BOD33_PSEL(2),
143 /** Divide input prescaler clock by 16 */
144 BOD_PRESCALE_DIV_16 = SYSCTRL_BOD33_PSEL(3),
145 /** Divide input prescaler clock by 32*/
146 BOD_PRESCALE_DIV_32 = SYSCTRL_BOD33_PSEL(4),
147 /** Divide input prescaler clock by 64 */
148 BOD_PRESCALE_DIV_64 = SYSCTRL_BOD33_PSEL(5),
149 /** Divide input prescaler clock by 128 */
150 BOD_PRESCALE_DIV_128 = SYSCTRL_BOD33_PSEL(6),
151 /** Divide input prescaler clock by 256 */
152 BOD_PRESCALE_DIV_256 = SYSCTRL_BOD33_PSEL(7),
153 /** Divide input prescaler clock by 512 */
154 BOD_PRESCALE_DIV_512 = SYSCTRL_BOD33_PSEL(8),
155 /** Divide input prescaler clock by 1024 */
156 BOD_PRESCALE_DIV_1024 = SYSCTRL_BOD33_PSEL(9),
157 /** Divide input prescaler clock by 2048 */
158 BOD_PRESCALE_DIV_2048 = SYSCTRL_BOD33_PSEL(10),
159 /** Divide input prescaler clock by 4096 */
160 BOD_PRESCALE_DIV_4096 = SYSCTRL_BOD33_PSEL(11),
161 /** Divide input prescaler clock by 8192 */
162 BOD_PRESCALE_DIV_8192 = SYSCTRL_BOD33_PSEL(12),
163 /** Divide input prescaler clock by 16384 */
164 BOD_PRESCALE_DIV_16384 = SYSCTRL_BOD33_PSEL(13),
165 /** Divide input prescaler clock by 32768 */
166 BOD_PRESCALE_DIV_32768 = SYSCTRL_BOD33_PSEL(14),
167 /** Divide input prescaler clock by 65536 */
168 BOD_PRESCALE_DIV_65536 = SYSCTRL_BOD33_PSEL(15),
169 };
170
171 /**
172 * \brief Brown Out Detector detection actions.
173 *
174 * List of possible BOD actions when a BOD module detects a brown out condition.
175 */
176 enum bod_action {
177 /** A BOD detect will do nothing, and the BOD state can't be polled */
178 BOD_ACTION_NONE = SYSCTRL_BOD33_ACTION(0),
179 /** A BOD detect will reset the device */
180 BOD_ACTION_RESET = SYSCTRL_BOD33_ACTION(1),
181 /** A BOD detect will fire an interrupt */
182 BOD_ACTION_INTERRUPT = SYSCTRL_BOD33_ACTION(2),
183 };
184
185 /**
186 * \brief Brown Out Detector sampling modes.
187 *
188 * List of possible BOD module voltage sampling modes.
189 */
190 enum bod_mode {
191 /** BOD will sample the supply line continuously */
192 BOD_MODE_CONTINUOUS = 0,
193 /** BOD will use the BOD sampling clock (1KHz) to sample the supply line */
194 BOD_MODE_SAMPLED = SYSCTRL_BOD33_MODE,
195 };
196
197 /** Configuration structure for a BOD module. */
198 struct bod_config {
199 /** Input sampler clock prescaler factor, to reduce the 1KHz clock from the
200 * ULP32K to lower the sampling rate of the BOD */
201 enum bod_prescale prescaler;
202 /** Sampling configuration mode for the BOD */
203 enum bod_mode mode;
204 /** Action to perform when a low power detection is made */
205 enum bod_action action;
206 /** BOD level to trigger at (see electrical section of device datasheet) */
207 uint8_t level;
208 /** If \c true, enables detection hysteresis */
209 bool hysteresis;
210 /** If \c true, the BOD is kept enabled and sampled during device sleep */
211 bool run_in_standby;
212 };
213
214 /**
215 * \name Configuration and Initialization
216 * @{
217 */
218
219 /**
220 * \brief Get default BOD configuration.
221 *
222 * The default BOD configuration is:
223 * - Clock prescaler set to divide the input clock by two
224 * - Continuous mode
225 * - Reset on BOD detect
226 * - Hysteresis enabled
227 * - BOD level 0x12
228 * - BOD kept enabled during device sleep
229 *
230 * \param[out] conf BOD configuration struct to set to default settings
231 */
bod_get_config_defaults(struct bod_config * const conf)232 static inline void bod_get_config_defaults(
233 struct bod_config *const conf)
234 {
235 /* Sanity check arguments */
236 Assert(conf);
237
238 conf->prescaler = BOD_PRESCALE_DIV_2;
239 conf->mode = BOD_MODE_CONTINUOUS;
240 conf->action = BOD_ACTION_RESET;
241 conf->level = 0x27;
242 conf->hysteresis = true;
243 conf->run_in_standby = true;
244 }
245
246 enum status_code bod_set_config(
247 const enum bod bod_id,
248 struct bod_config *const conf);
249
250 /**
251 * \brief Enables a configured BOD module.
252 *
253 * Enables the specified BOD module that has been previously configured.
254 *
255 * \param[in] bod_id BOD module to enable
256 *
257 * \return Error code indicating the status of the enable operation.
258 *
259 * \retval STATUS_OK If the BOD was successfully enabled
260 * \retval STATUS_ERR_INVALID_ARG An invalid BOD was supplied
261 */
bod_enable(const enum bod bod_id)262 static inline enum status_code bod_enable(
263 const enum bod bod_id)
264 {
265 switch (bod_id) {
266 case BOD_BOD33:
267 SYSCTRL->BOD33.reg |= SYSCTRL_BOD33_ENABLE;
268 break;
269 default:
270 Assert(false);
271 return STATUS_ERR_INVALID_ARG;
272 }
273
274 return STATUS_OK;
275 }
276
277 /**
278 * \brief Disables an enabled BOD module.
279 *
280 * Disables the specified BOD module that was previously enabled.
281 *
282 * \param[in] bod_id BOD module to disable
283 *
284 * \return Error code indicating the status of the disable operation.
285 *
286 * \retval STATUS_OK If the BOD was successfully disabled
287 * \retval STATUS_ERR_INVALID_ARG An invalid BOD was supplied
288 */
bod_disable(const enum bod bod_id)289 static inline enum status_code bod_disable(
290 const enum bod bod_id)
291 {
292 switch (bod_id) {
293 case BOD_BOD33:
294 SYSCTRL->INTENCLR.reg = SYSCTRL_INTENCLR_BOD33RDY | SYSCTRL_INTENCLR_BOD33DET | SYSCTRL_INTENCLR_B33SRDY;
295 SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD33RDY | SYSCTRL_INTFLAG_BOD33DET | SYSCTRL_INTFLAG_B33SRDY;
296 SYSCTRL->BOD33.reg &= ~SYSCTRL_BOD33_ENABLE;
297 break;
298 default:
299 Assert(false);
300 return STATUS_ERR_INVALID_ARG;
301 }
302
303 return STATUS_OK;
304 }
305
306 /**
307 * \brief Checks if a specified BOD low voltage detection has occurred.
308 *
309 * Determines if a specified BOD has detected a voltage lower than its
310 * configured threshold.
311 *
312 * \param[in] bod_id BOD module to check
313 *
314 * \return Detection status of the specified BOD.
315 *
316 * \retval true If the BOD has detected a low voltage condition
317 * \retval false If the BOD has not detected a low voltage condition
318 */
bod_is_detected(const enum bod bod_id)319 static inline bool bod_is_detected(
320 const enum bod bod_id)
321 {
322 switch (bod_id) {
323 case BOD_BOD33:
324 return SYSCTRL->INTFLAG.bit.BOD33DET;
325 default:
326 Assert(false);
327 return false;
328 }
329 }
330
331 /**
332 * \brief Clears the low voltage detection state of a specified BOD.
333 *
334 * Clears the low voltage condition of a specified BOD module, so that new
335 * low voltage conditions can be detected.
336 *
337 * \param[in] bod_id BOD module to clear
338 */
bod_clear_detected(const enum bod bod_id)339 static inline void bod_clear_detected(
340 const enum bod bod_id)
341 {
342 switch (bod_id) {
343 case BOD_BOD33:
344 SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD33DET;
345 return;
346 default:
347 Assert(false);
348 return;
349 }
350 }
351
352 /** @} */
353
354 /**
355 * @}
356 */
357
358
359 /**
360 * \page asfdoc_sam0_bod_extra Extra Information for BOD Driver
361 *
362 * \section asfdoc_sam0_bod_extra_acronyms Acronyms
363 * Below is a table listing the acronyms used in this module, along with their
364 * intended meanings.
365 *
366 * <table>
367 * <tr>
368 * <th>Acronym</th>
369 * <th>Definition</th>
370 * </tr>
371 * <tr>
372 * <td>BOD</td>
373 * <td>Brown Out Detector</td>
374 * </tr>
375 * </table>
376 *
377 *
378 * \section asfdoc_sam0_bod_extra_dependencies Dependencies
379 * This driver has the following dependencies:
380 *
381 * - None
382 *
383 *
384 * \section asfdoc_sam0_bod_extra_errata Errata
385 * There are no errata related to this driver.
386 *
387 *
388 * \section asfdoc_sam0_bod_extra_history Module History
389 * An overview of the module history is presented in the table below, with
390 * details on the enhancements and fixes made to the module since its first
391 * release. The current version of this corresponds to the newest version in
392 * the table.
393 *
394 * <table>
395 * <tr>
396 * <th>Changelog</th>
397 * </tr>
398 * <tr>
399 * <td>Removed BOD12 reference</td>
400 * </tr>
401 * <tr>
402 * <td>Initial Release</td>
403 * </tr>
404 * </table>
405 */
406
407 /**
408 * \page asfdoc_sam0_bod_exqsg Examples for BOD Driver
409 *
410 * This is a list of the available Quick Start guides (QSGs) and example
411 * applications for \ref asfdoc_sam0_bod_group. QSGs are simple examples with
412 * step-by-step instructions to configure and use this driver in a selection of
413 * use cases. Note that QSGs can be compiled as a standalone application or be
414 * added to the user application.
415 *
416 * - \subpage asfdoc_sam0_bod_basic_use_case
417 *
418 * - \subpage asfdoc_sam0_bod_application_use_case
419 *
420 * \page asfdoc_sam0_bod_application_use_case Application Use Case for BOD - Application
421 * The preferred method of setting BOD33 levels and settings is through the fuses.
422 * When it is desirable to set it in software, see the below use case.
423 *
424 * In this use case, a new BOD33 level might be set in SW if the clock settings
425 * are adjusted up after a battery has charged to a higher level. When the battery
426 * discharges, the chip will reset when the battery level is below SW BOD33 level.
427 * Now the chip will run at a lower clock rate and the BOD33 level from fuse.
428 * The chip should always measure the voltage before adjusting the frequency up.
429 *
430 * \page asfdoc_sam0_bod_document_revision_history Document Revision History
431 *
432 * <table>
433 * <tr>
434 * <th>Doc. Rev.</th>
435 * <th>Date</th>
436 * <th>Comments</th>
437 * </tr>
438 * <tr>
439 * <td>42149E</td>
440 * <td>12/2015</td>
441 * <td>Added support for SAM DA1</td>
442 * </tr>
443 * <tr>
444 * <td>42149D</td>
445 * <td>12/2014</td>
446 * <td>Added support for SAM R21, and SAM D10/D11</td>
447 * </tr>
448 * <tr>
449 * <td>42149C</td>
450 * <td>01/2014</td>
451 * <td>Added support for SAM D21</td>
452 * </tr>
453 * <tr>
454 * <td>42149B</td>
455 * <td>06/2013</td>
456 * <td>Corrected documentation typos</td>
457 * </tr>
458 * <tr>
459 * <td>42149A</td>
460 * <td>06/2013</td>
461 * <td>Initial release</td>
462 * </tr>
463 * </table>
464 */
465
466 #ifdef __cplusplus
467 }
468 #endif
469
470 #endif /* BOD_FEATURE_H_INCLUDED */
471