freqm.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /**
  2. * \file
  3. *
  4. * \brief SAM Frequency Meter (FREQM) Driver
  5. *
  6. * Copyright (C) 2015-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 FREQM_H_INCLUDED
  47. #define FREQM_H_INCLUDED
  48. /**
  49. * \defgroup asfdoc_sam0_freqm_group SAM Frequency Meter (FREQM) Driver
  50. *
  51. * This driver for Atmel&reg; | SMART ARM&reg;-based microcontrollers provides an interface for the configuration
  52. * and management of the device's Frequency Meter functionality.
  53. *
  54. * The following driver API modes are covered by this manual:
  55. * - Polled APIs
  56. * \if FREQM_CALLBACK_MODE
  57. * - Callback APIs
  58. * \endif
  59. *
  60. * The following peripheral is used by this module:
  61. * - FREQM (Frequency Meter)
  62. *
  63. * The following devices can use this module:
  64. * - Atmel | SMART SAM L22
  65. * - Atmel | SMART SAM C20
  66. * - Atmel | SMART SAM C21
  67. *
  68. * The outline of this documentation is as follows:
  69. * - \ref asfdoc_sam0_freqm_prerequisites
  70. * - \ref asfdoc_sam0_freqm_module_overview
  71. * - \ref asfdoc_sam0_freqm_special_considerations
  72. * - \ref asfdoc_sam0_freqm_extra_info
  73. * - \ref asfdoc_sam0_freqm_examples
  74. * - \ref asfdoc_sam0_freqm_api_overview
  75. *
  76. *
  77. * \section asfdoc_sam0_freqm_prerequisites Prerequisites
  78. *
  79. * There are no prerequisites for this module.
  80. *
  81. *
  82. * \section asfdoc_sam0_freqm_module_overview Module Overview
  83. *
  84. * The module accurately measures the frequency of a clock by comparing it to a
  85. * known reference clock as soon as the FREQM is enabled. Two generic clocks are
  86. * used by the FREQM. The frequency of the measured clock is:
  87. * \f[
  88. * f_{CLK\_MSR} = \frac{VALUE}{REFNUM} \times f_{CLK\_REF}
  89. * \f]
  90. * Ratio can be measured with 24-bit accuracy.
  91. *
  92. * The FREQM has one interrupt source, which generates when a frequency measurement
  93. * is done. It can be used to wake up the device from sleep modes.
  94. *
  95. * This driver provides an interface for the FREQM functions on the device.
  96. *
  97. * \section asfdoc_sam0_freqm_special_considerations Special Considerations
  98. *
  99. * There are no special considerations for this module.
  100. *
  101. *
  102. * \section asfdoc_sam0_freqm_extra_info Extra Information
  103. *
  104. * For extra information see \ref asfdoc_sam0_freqm_extra. This includes:
  105. * - \ref asfdoc_sam0_freqm_extra_acronyms
  106. * - \ref asfdoc_sam0_freqm_extra_dependencies
  107. * - \ref asfdoc_sam0_freqm_extra_errata
  108. * - \ref asfdoc_sam0_freqm_extra_history
  109. *
  110. *
  111. * \section asfdoc_sam0_freqm_examples Examples
  112. *
  113. * For a list of examples related to this driver, see
  114. * \ref asfdoc_sam0_freqm_exqsg.
  115. *
  116. *
  117. * \section asfdoc_sam0_freqm_api_overview API Overview
  118. * @{
  119. */
  120. #include <compiler.h>
  121. #include <system.h>
  122. #ifdef __cplusplus
  123. extern "C" {
  124. #endif
  125. #if FREQM_CALLBACK_MODE == true
  126. /** Forward declaration of struct */
  127. struct freqm_module;
  128. extern struct freqm_module *_freqm_instance;
  129. /** Type definition for a FREQM module callback function. */
  130. typedef void (*freqm_callback_t)(void);
  131. /** Enum for possible callback types for the FREQM module. */
  132. enum freqm_callback {
  133. /** Callback for measurement done */
  134. FREQM_CALLBACK_DONE = 0,
  135. /** Number of available callbacks */
  136. #if !defined(__DOXYGEN__)
  137. FREQM_CALLBACK_N,
  138. #endif
  139. };
  140. #endif
  141. /**
  142. * \brief FREQM software device instance structure.
  143. *
  144. * FREQM software instance structure, used to retain software state information
  145. * of an associated hardware module instance.
  146. *
  147. * \note The fields of this structure should not be altered by the user
  148. * application; they are reserved for module-internal use only.
  149. */
  150. struct freqm_module {
  151. #if !defined(__DOXYGEN__)
  152. /** Hardware module pointer of the associated FREQM peripheral */
  153. Freqm *hw;
  154. /** The frequency of reference clock in Hz*/
  155. uint32_t ref_clock_freq;
  156. # if FREQM_CALLBACK_MODE == true
  157. /** Array of callbacks */
  158. freqm_callback_t callback[FREQM_CALLBACK_N];
  159. # endif
  160. #endif
  161. };
  162. /** Enum for the possible status types for the FREQM module. */
  163. enum freqm_status {
  164. /** FREQM measurement is finish */
  165. FREQM_STATUS_MEASURE_DONE = 0,
  166. /** FREQM measurement is ongoing or not */
  167. FREQM_STATUS_MEASURE_BUSY = 1,
  168. /** FREQM sticky count value overflow */
  169. FREQM_STATUS_CNT_OVERFLOW = 2,
  170. };
  171. /**
  172. * \brief FREQM module configuration structure.
  173. *
  174. * Configuration structure for a Frequency Meter.
  175. */
  176. struct freqm_config {
  177. /** GCLK source select for measurement */
  178. enum gclk_generator msr_clock_source;
  179. /** GCLK source select for reference */
  180. enum gclk_generator ref_clock_source;
  181. /** Measurement duration in number of reference clock cycles. Range 1~255 */
  182. uint16_t ref_clock_circles;
  183. };
  184. /**
  185. * \brief Determines if the hardware module(s) are currently synchronizing to the bus.
  186. *
  187. * Checks to see if the underlying hardware peripheral module(s) are currently
  188. * synchronizing across multiple clock domains to the hardware bus. This
  189. * function can be used to delay further operations on a module until such time
  190. * that it is ready, to prevent blocking delays for synchronization in the
  191. * user application.
  192. *
  193. * \return Synchronization status of the underlying hardware module(s).
  194. *
  195. * \retval false If the module has completed synchronization
  196. * \retval true If the module synchronization is ongoing
  197. */
  198. static inline bool freqm_is_syncing(void)
  199. {
  200. Freqm *const freqm_module = FREQM;
  201. if (freqm_module->SYNCBUSY.reg) {
  202. return true;
  203. }
  204. return false;
  205. }
  206. /**
  207. * \name Driver Initialization and Configuration
  208. * @{
  209. */
  210. enum status_code freqm_init(
  211. struct freqm_module *const module_inst,
  212. Freqm *const hw,
  213. struct freqm_config *const config);
  214. /**
  215. * \brief Initializes all members of a FREQM configuration structure
  216. * to safe defaults.
  217. *
  218. * Initializes all members of a given Frequency Meter configuration
  219. * structure to safe known default values. This function should be called on
  220. * all new instances of these configuration structures before being modified
  221. * by the user application.
  222. *
  223. * The default configuration is as follows:
  224. * \li Measurement clock source is GCLK0
  225. * \li Reference clock source is GCLK1
  226. * \li Frequency Meter Reference Clock Cycles 127
  227. *
  228. * \param[in] config Configuration structure to initialize to default values
  229. */
  230. static inline void freqm_get_config_defaults(
  231. struct freqm_config *const config)
  232. {
  233. /* Sanity check arguments */
  234. Assert(config);
  235. /* Default configuration values */
  236. config->msr_clock_source = GCLK_GENERATOR_0;
  237. config->ref_clock_source = GCLK_GENERATOR_1;
  238. config->ref_clock_circles = 127;
  239. }
  240. /**
  241. * \brief Enables a FREQM that was previously configured.
  242. *
  243. * Enables Frequency Meter that was previously configured via a
  244. * call to \ref freqm_init().
  245. *
  246. * \param[in] module_inst Software instance for the Frequency Meter peripheral
  247. */
  248. static inline void freqm_enable(
  249. struct freqm_module *const module_inst)
  250. {
  251. /* Sanity check arguments */
  252. Assert(module_inst);
  253. Assert(module_inst->hw);
  254. Freqm *const freqm_module = module_inst->hw;
  255. /* Enable FREQM */
  256. freqm_module->CTRLA.reg |= FREQM_CTRLA_ENABLE;
  257. while (freqm_is_syncing()) {
  258. /* Wait for all hardware modules to complete synchronization */
  259. }
  260. }
  261. /**
  262. * \brief Disables a FREQM that was previously enabled.
  263. *
  264. * Disables Frequency Meter that was previously started via a call
  265. * to \ref freqm_enable().
  266. *
  267. * \param[in] module_inst Software instance for the Frequency Meter peripheral
  268. */
  269. static inline void freqm_disable(
  270. struct freqm_module *const module_inst)
  271. {
  272. /* Sanity check arguments */
  273. Assert(module_inst);
  274. Assert(module_inst->hw);
  275. Freqm *const freqm_module = module_inst->hw;
  276. /* Disbale interrupt */
  277. freqm_module->INTENCLR.reg = FREQM_INTENCLR_MASK;
  278. /* Clear interrupt flag */
  279. freqm_module->INTFLAG.reg = FREQM_INTFLAG_MASK;
  280. /* Disable FREQM */
  281. freqm_module->CTRLA.reg &= ~FREQM_CTRLA_ENABLE;
  282. while (freqm_is_syncing()) {
  283. /* Wait for all hardware modules to complete synchronization */
  284. }
  285. }
  286. /** @} */
  287. /**
  288. * \name Read FREQM Result
  289. * @{
  290. */
  291. /**
  292. * \brief Start a manual measurement process.
  293. *
  294. * \param[in] module Pointer to the FREQM software instance struct
  295. */
  296. static inline void freqm_start_measure(struct freqm_module *const module)
  297. {
  298. /* Sanity check arguments */
  299. Assert(module);
  300. Assert(module->hw);
  301. /* Trigger measurement */
  302. module->hw->CTRLB.reg |= FREQM_CTRLB_START;
  303. }
  304. /**
  305. * \brief Clears module overflow flag.
  306. *
  307. * Clears the overflow flag of the module.
  308. *
  309. * \param[in] module Pointer to the FREQM software instance struct
  310. */
  311. static inline void freqm_clear_overflow(struct freqm_module *const module)
  312. {
  313. /* Sanity check arguments */
  314. Assert(module);
  315. Assert(module->hw);
  316. /* Clear overflow flag */
  317. module->hw->STATUS.reg = FREQM_STATUS_OVF;
  318. }
  319. enum freqm_status freqm_get_result_value(
  320. struct freqm_module *const module_inst, uint32_t *result);
  321. /** @} */
  322. #ifdef __cplusplus
  323. }
  324. #endif
  325. /** @} */
  326. /**
  327. * \page asfdoc_sam0_freqm_extra Extra Information for FREQM Driver
  328. *
  329. * \section asfdoc_sam0_freqm_extra_acronyms Acronyms
  330. * Below is a table listing the acronyms used in this module, along with their
  331. * intended meanings.
  332. *
  333. * <table>
  334. * <tr>
  335. * <th>Acronym</th>
  336. * <th>Description</th>
  337. * </tr>
  338. * <tr>
  339. * <td>FREQM</td>
  340. * <td>Frequency Meter</td>
  341. * </tr>
  342. * </table>
  343. *
  344. *
  345. * \section asfdoc_sam0_freqm_extra_dependencies Dependencies
  346. * This driver has no dependencies.
  347. *
  348. *
  349. * \section asfdoc_sam0_freqm_extra_errata Errata
  350. * There are no errata related to this driver.
  351. *
  352. *
  353. * \section asfdoc_sam0_freqm_extra_history Module History
  354. * An overview of the module history is presented in the table below, with
  355. * details on the enhancements and fixes made to the module since its first
  356. * release. The current version of this corresponds to the newest version in
  357. * the table.
  358. *
  359. * <table>
  360. * <tr>
  361. * <th>Changelog</th>
  362. * </tr>
  363. * <tr>
  364. * <td>Initial Release</td>
  365. * </tr>
  366. * </table>
  367. */
  368. /**
  369. * \page asfdoc_sam0_freqm_exqsg Examples for FREQM Driver
  370. *
  371. * This is a list of the available Quick Start guides (QSGs) and example
  372. * applications for \ref asfdoc_sam0_freqm_group. QSGs are simple examples with
  373. * step-by-step instructions to configure and use this driver in a selection of
  374. * use cases. Note that a QSG can be compiled as a standalone application or be
  375. * added to the user application.
  376. *
  377. * - \subpage asfdoc_sam0_freqm_basic_use_case
  378. * \if FREQM_CALLBACK_MODE
  379. * - \subpage asfdoc_sam0_freqm_basic_use_case_callback
  380. * \endif
  381. *
  382. * \page asfdoc_sam0_freqm_document_revision_history Document Revision History
  383. *
  384. * <table>
  385. * <tr>
  386. * <th>Doc. Rev.</td>
  387. * <th>Date</td>
  388. * <th>Comments</td>
  389. * </tr>
  390. * <tr>
  391. * <td>42506A</td>
  392. * <td>08/2015</td>
  393. * <td>Initial document release</td>
  394. * </tr>
  395. * </table>
  396. */
  397. #endif /* FREQM_H_INCLUDED */