mbed library sources. Supersedes mbed-src.
Fork of mbed-dev by
targets/hal/TARGET_Atmel/TARGET_SAM_CortexM0P/drivers/system/clock/TARGET_SAML21/gclk.c@18:da299f395b9e, 2015-11-09 (annotated)
- Committer:
- mbed_official
- Date:
- Mon Nov 09 13:30:11 2015 +0000
- Revision:
- 18:da299f395b9e
Synchronized with git revision f605825f66bb2e462ff7dbc5fb4ed2dbe979d1c3
Full URL: https://github.com/mbedmicro/mbed/commit/f605825f66bb2e462ff7dbc5fb4ed2dbe979d1c3/
Added support for SAML21
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mbed_official | 18:da299f395b9e | 1 | /** |
mbed_official | 18:da299f395b9e | 2 | * \file |
mbed_official | 18:da299f395b9e | 3 | * |
mbed_official | 18:da299f395b9e | 4 | * \brief SAM L21 Generic Clock Driver |
mbed_official | 18:da299f395b9e | 5 | * |
mbed_official | 18:da299f395b9e | 6 | * Copyright (C) 2014-2015 Atmel Corporation. All rights reserved. |
mbed_official | 18:da299f395b9e | 7 | * |
mbed_official | 18:da299f395b9e | 8 | * \asf_license_start |
mbed_official | 18:da299f395b9e | 9 | * |
mbed_official | 18:da299f395b9e | 10 | * \page License |
mbed_official | 18:da299f395b9e | 11 | * |
mbed_official | 18:da299f395b9e | 12 | * Redistribution and use in source and binary forms, with or without |
mbed_official | 18:da299f395b9e | 13 | * modification, are permitted provided that the following conditions are met: |
mbed_official | 18:da299f395b9e | 14 | * |
mbed_official | 18:da299f395b9e | 15 | * 1. Redistributions of source code must retain the above copyright notice, |
mbed_official | 18:da299f395b9e | 16 | * this list of conditions and the following disclaimer. |
mbed_official | 18:da299f395b9e | 17 | * |
mbed_official | 18:da299f395b9e | 18 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
mbed_official | 18:da299f395b9e | 19 | * this list of conditions and the following disclaimer in the documentation |
mbed_official | 18:da299f395b9e | 20 | * and/or other materials provided with the distribution. |
mbed_official | 18:da299f395b9e | 21 | * |
mbed_official | 18:da299f395b9e | 22 | * 3. The name of Atmel may not be used to endorse or promote products derived |
mbed_official | 18:da299f395b9e | 23 | * from this software without specific prior written permission. |
mbed_official | 18:da299f395b9e | 24 | * |
mbed_official | 18:da299f395b9e | 25 | * 4. This software may only be redistributed and used in connection with an |
mbed_official | 18:da299f395b9e | 26 | * Atmel microcontroller product. |
mbed_official | 18:da299f395b9e | 27 | * |
mbed_official | 18:da299f395b9e | 28 | * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED |
mbed_official | 18:da299f395b9e | 29 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
mbed_official | 18:da299f395b9e | 30 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE |
mbed_official | 18:da299f395b9e | 31 | * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR |
mbed_official | 18:da299f395b9e | 32 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
mbed_official | 18:da299f395b9e | 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
mbed_official | 18:da299f395b9e | 34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
mbed_official | 18:da299f395b9e | 35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
mbed_official | 18:da299f395b9e | 36 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
mbed_official | 18:da299f395b9e | 37 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
mbed_official | 18:da299f395b9e | 38 | * POSSIBILITY OF SUCH DAMAGE. |
mbed_official | 18:da299f395b9e | 39 | * |
mbed_official | 18:da299f395b9e | 40 | * \asf_license_stop |
mbed_official | 18:da299f395b9e | 41 | * |
mbed_official | 18:da299f395b9e | 42 | */ |
mbed_official | 18:da299f395b9e | 43 | /* |
mbed_official | 18:da299f395b9e | 44 | * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a> |
mbed_official | 18:da299f395b9e | 45 | */ |
mbed_official | 18:da299f395b9e | 46 | |
mbed_official | 18:da299f395b9e | 47 | #include <gclk.h> |
mbed_official | 18:da299f395b9e | 48 | #include <clock.h> |
mbed_official | 18:da299f395b9e | 49 | #include <system_interrupt.h> |
mbed_official | 18:da299f395b9e | 50 | |
mbed_official | 18:da299f395b9e | 51 | |
mbed_official | 18:da299f395b9e | 52 | /** |
mbed_official | 18:da299f395b9e | 53 | * \brief Determines if the hardware module(s) are currently synchronizing to the bus. |
mbed_official | 18:da299f395b9e | 54 | * |
mbed_official | 18:da299f395b9e | 55 | * Checks to see if the underlying hardware peripheral module(s) are currently |
mbed_official | 18:da299f395b9e | 56 | * synchronizing across multiple clock domains to the hardware bus, This |
mbed_official | 18:da299f395b9e | 57 | * function can be used to delay further operations on a module until such time |
mbed_official | 18:da299f395b9e | 58 | * that it is ready, to prevent blocking delays for synchronization in the |
mbed_official | 18:da299f395b9e | 59 | * user application. |
mbed_official | 18:da299f395b9e | 60 | * \param[in] generator Generic Clock Generator index to sync |
mbed_official | 18:da299f395b9e | 61 | * |
mbed_official | 18:da299f395b9e | 62 | * \return Synchronization status of the underlying hardware module(s). |
mbed_official | 18:da299f395b9e | 63 | * |
mbed_official | 18:da299f395b9e | 64 | * \retval false if the module has completed synchronization |
mbed_official | 18:da299f395b9e | 65 | * \retval true if the module synchronization is ongoing |
mbed_official | 18:da299f395b9e | 66 | */ |
mbed_official | 18:da299f395b9e | 67 | static inline bool system_gclk_is_syncing(const uint8_t generator) |
mbed_official | 18:da299f395b9e | 68 | { |
mbed_official | 18:da299f395b9e | 69 | |
mbed_official | 18:da299f395b9e | 70 | if (GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL(1 << generator )) { |
mbed_official | 18:da299f395b9e | 71 | return true; |
mbed_official | 18:da299f395b9e | 72 | } |
mbed_official | 18:da299f395b9e | 73 | |
mbed_official | 18:da299f395b9e | 74 | return false; |
mbed_official | 18:da299f395b9e | 75 | } |
mbed_official | 18:da299f395b9e | 76 | |
mbed_official | 18:da299f395b9e | 77 | |
mbed_official | 18:da299f395b9e | 78 | /** |
mbed_official | 18:da299f395b9e | 79 | * \brief Initializes the GCLK driver. |
mbed_official | 18:da299f395b9e | 80 | * |
mbed_official | 18:da299f395b9e | 81 | * Initializes the Generic Clock module, disabling and resetting all active |
mbed_official | 18:da299f395b9e | 82 | * Generic Clock Generators and Channels to their power-on default values. |
mbed_official | 18:da299f395b9e | 83 | */ |
mbed_official | 18:da299f395b9e | 84 | void system_gclk_init(void) |
mbed_official | 18:da299f395b9e | 85 | { |
mbed_official | 18:da299f395b9e | 86 | /* Turn on the digital interface clock */ |
mbed_official | 18:da299f395b9e | 87 | system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, MCLK_APBAMASK_GCLK); |
mbed_official | 18:da299f395b9e | 88 | |
mbed_official | 18:da299f395b9e | 89 | /* Software reset the module to ensure it is re-initialized correctly */ |
mbed_official | 18:da299f395b9e | 90 | GCLK->CTRLA.reg = GCLK_CTRLA_SWRST; |
mbed_official | 18:da299f395b9e | 91 | while (GCLK->CTRLA.reg & GCLK_CTRLA_SWRST) { |
mbed_official | 18:da299f395b9e | 92 | /* Wait for reset to complete */ |
mbed_official | 18:da299f395b9e | 93 | } |
mbed_official | 18:da299f395b9e | 94 | } |
mbed_official | 18:da299f395b9e | 95 | |
mbed_official | 18:da299f395b9e | 96 | /** |
mbed_official | 18:da299f395b9e | 97 | * \brief Writes a Generic Clock Generator configuration to the hardware module. |
mbed_official | 18:da299f395b9e | 98 | * |
mbed_official | 18:da299f395b9e | 99 | * Writes out a given configuration of a Generic Clock Generator configuration |
mbed_official | 18:da299f395b9e | 100 | * to the hardware module. |
mbed_official | 18:da299f395b9e | 101 | * |
mbed_official | 18:da299f395b9e | 102 | * \note Changing the clock source on the fly (on a running |
mbed_official | 18:da299f395b9e | 103 | * generator) can take additional time if the clock source is configured |
mbed_official | 18:da299f395b9e | 104 | * to only run on-demand (ONDEMAND bit is set) and it is not currently |
mbed_official | 18:da299f395b9e | 105 | * running (no peripheral is requesting the clock source). In this case |
mbed_official | 18:da299f395b9e | 106 | * the GCLK will request the new clock while still keeping a request to |
mbed_official | 18:da299f395b9e | 107 | * the old clock source until the new clock source is ready. |
mbed_official | 18:da299f395b9e | 108 | * |
mbed_official | 18:da299f395b9e | 109 | * \note This function will not start a generator that is not already running; |
mbed_official | 18:da299f395b9e | 110 | * to start the generator, call \ref system_gclk_gen_enable() |
mbed_official | 18:da299f395b9e | 111 | * after configuring a generator. |
mbed_official | 18:da299f395b9e | 112 | * |
mbed_official | 18:da299f395b9e | 113 | * \param[in] generator Generic Clock Generator index to configure |
mbed_official | 18:da299f395b9e | 114 | * \param[in] config Configuration settings for the generator |
mbed_official | 18:da299f395b9e | 115 | */ |
mbed_official | 18:da299f395b9e | 116 | void system_gclk_gen_set_config( |
mbed_official | 18:da299f395b9e | 117 | const uint8_t generator, |
mbed_official | 18:da299f395b9e | 118 | struct system_gclk_gen_config *const config) |
mbed_official | 18:da299f395b9e | 119 | { |
mbed_official | 18:da299f395b9e | 120 | /* Sanity check arguments */ |
mbed_official | 18:da299f395b9e | 121 | Assert(config); |
mbed_official | 18:da299f395b9e | 122 | |
mbed_official | 18:da299f395b9e | 123 | /* Cache new register configurations to minimize sync requirements. */ |
mbed_official | 18:da299f395b9e | 124 | uint32_t new_genctrl_config ; |
mbed_official | 18:da299f395b9e | 125 | |
mbed_official | 18:da299f395b9e | 126 | |
mbed_official | 18:da299f395b9e | 127 | /* Select the requested source clock for the generator */ |
mbed_official | 18:da299f395b9e | 128 | new_genctrl_config = config->source_clock << GCLK_GENCTRL_SRC_Pos; |
mbed_official | 18:da299f395b9e | 129 | |
mbed_official | 18:da299f395b9e | 130 | /* Configure the clock to be either high or low when disabled */ |
mbed_official | 18:da299f395b9e | 131 | if (config->high_when_disabled) { |
mbed_official | 18:da299f395b9e | 132 | new_genctrl_config |= GCLK_GENCTRL_OOV; |
mbed_official | 18:da299f395b9e | 133 | } |
mbed_official | 18:da299f395b9e | 134 | |
mbed_official | 18:da299f395b9e | 135 | /* Configure if the clock output to I/O pin should be enabled. */ |
mbed_official | 18:da299f395b9e | 136 | if (config->output_enable) { |
mbed_official | 18:da299f395b9e | 137 | new_genctrl_config |= GCLK_GENCTRL_OE; |
mbed_official | 18:da299f395b9e | 138 | } |
mbed_official | 18:da299f395b9e | 139 | |
mbed_official | 18:da299f395b9e | 140 | /* Set division factor */ |
mbed_official | 18:da299f395b9e | 141 | if (config->division_factor > 1) { |
mbed_official | 18:da299f395b9e | 142 | /* Check if division is a power of two */ |
mbed_official | 18:da299f395b9e | 143 | if (((config->division_factor & (config->division_factor - 1)) == 0)) { |
mbed_official | 18:da299f395b9e | 144 | /* Determine the index of the highest bit set to get the |
mbed_official | 18:da299f395b9e | 145 | * division factor that must be loaded into the division |
mbed_official | 18:da299f395b9e | 146 | * register */ |
mbed_official | 18:da299f395b9e | 147 | |
mbed_official | 18:da299f395b9e | 148 | uint32_t div2_count = 0; |
mbed_official | 18:da299f395b9e | 149 | |
mbed_official | 18:da299f395b9e | 150 | uint32_t mask; |
mbed_official | 18:da299f395b9e | 151 | for (mask = (1UL << 1); mask < config->division_factor; |
mbed_official | 18:da299f395b9e | 152 | mask <<= 1) { |
mbed_official | 18:da299f395b9e | 153 | div2_count++; |
mbed_official | 18:da299f395b9e | 154 | } |
mbed_official | 18:da299f395b9e | 155 | |
mbed_official | 18:da299f395b9e | 156 | /* Set binary divider power of 2 division factor */ |
mbed_official | 18:da299f395b9e | 157 | new_genctrl_config |= div2_count << GCLK_GENCTRL_DIV_Pos; |
mbed_official | 18:da299f395b9e | 158 | new_genctrl_config |= GCLK_GENCTRL_DIVSEL; |
mbed_official | 18:da299f395b9e | 159 | } else { |
mbed_official | 18:da299f395b9e | 160 | /* Set integer division factor */ |
mbed_official | 18:da299f395b9e | 161 | |
mbed_official | 18:da299f395b9e | 162 | new_genctrl_config |= |
mbed_official | 18:da299f395b9e | 163 | (config->division_factor) << GCLK_GENCTRL_DIV_Pos; |
mbed_official | 18:da299f395b9e | 164 | |
mbed_official | 18:da299f395b9e | 165 | /* Enable non-binary division with increased duty cycle accuracy */ |
mbed_official | 18:da299f395b9e | 166 | new_genctrl_config |= GCLK_GENCTRL_IDC; |
mbed_official | 18:da299f395b9e | 167 | } |
mbed_official | 18:da299f395b9e | 168 | |
mbed_official | 18:da299f395b9e | 169 | } |
mbed_official | 18:da299f395b9e | 170 | |
mbed_official | 18:da299f395b9e | 171 | /* Enable or disable the clock in standby mode */ |
mbed_official | 18:da299f395b9e | 172 | if (config->run_in_standby) { |
mbed_official | 18:da299f395b9e | 173 | new_genctrl_config |= GCLK_GENCTRL_RUNSTDBY; |
mbed_official | 18:da299f395b9e | 174 | } |
mbed_official | 18:da299f395b9e | 175 | |
mbed_official | 18:da299f395b9e | 176 | while (system_gclk_is_syncing(generator)) { |
mbed_official | 18:da299f395b9e | 177 | /* Wait for synchronization */ |
mbed_official | 18:da299f395b9e | 178 | }; |
mbed_official | 18:da299f395b9e | 179 | |
mbed_official | 18:da299f395b9e | 180 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 181 | |
mbed_official | 18:da299f395b9e | 182 | GCLK->GENCTRL[generator].reg = new_genctrl_config | (GCLK->GENCTRL[generator].reg & GCLK_GENCTRL_GENEN); |
mbed_official | 18:da299f395b9e | 183 | |
mbed_official | 18:da299f395b9e | 184 | while (system_gclk_is_syncing(generator)) { |
mbed_official | 18:da299f395b9e | 185 | /* Wait for synchronization */ |
mbed_official | 18:da299f395b9e | 186 | }; |
mbed_official | 18:da299f395b9e | 187 | |
mbed_official | 18:da299f395b9e | 188 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 189 | } |
mbed_official | 18:da299f395b9e | 190 | |
mbed_official | 18:da299f395b9e | 191 | /** |
mbed_official | 18:da299f395b9e | 192 | * \brief Enables a Generic Clock Generator that was previously configured. |
mbed_official | 18:da299f395b9e | 193 | * |
mbed_official | 18:da299f395b9e | 194 | * Starts the clock generation of a Generic Clock Generator that was previously |
mbed_official | 18:da299f395b9e | 195 | * configured via a call to \ref system_gclk_gen_set_config(). |
mbed_official | 18:da299f395b9e | 196 | * |
mbed_official | 18:da299f395b9e | 197 | * \param[in] generator Generic Clock Generator index to enable |
mbed_official | 18:da299f395b9e | 198 | */ |
mbed_official | 18:da299f395b9e | 199 | void system_gclk_gen_enable( |
mbed_official | 18:da299f395b9e | 200 | const uint8_t generator) |
mbed_official | 18:da299f395b9e | 201 | { |
mbed_official | 18:da299f395b9e | 202 | while (system_gclk_is_syncing(generator)) { |
mbed_official | 18:da299f395b9e | 203 | /* Wait for synchronization */ |
mbed_official | 18:da299f395b9e | 204 | }; |
mbed_official | 18:da299f395b9e | 205 | |
mbed_official | 18:da299f395b9e | 206 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 207 | |
mbed_official | 18:da299f395b9e | 208 | /* Enable generator */ |
mbed_official | 18:da299f395b9e | 209 | GCLK->GENCTRL[generator].reg |= GCLK_GENCTRL_GENEN; |
mbed_official | 18:da299f395b9e | 210 | |
mbed_official | 18:da299f395b9e | 211 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 212 | } |
mbed_official | 18:da299f395b9e | 213 | |
mbed_official | 18:da299f395b9e | 214 | /** |
mbed_official | 18:da299f395b9e | 215 | * \brief Disables a Generic Clock Generator that was previously enabled. |
mbed_official | 18:da299f395b9e | 216 | * |
mbed_official | 18:da299f395b9e | 217 | * Stops the clock generation of a Generic Clock Generator that was previously |
mbed_official | 18:da299f395b9e | 218 | * started via a call to \ref system_gclk_gen_enable(). |
mbed_official | 18:da299f395b9e | 219 | * |
mbed_official | 18:da299f395b9e | 220 | * \param[in] generator Generic Clock Generator index to disable |
mbed_official | 18:da299f395b9e | 221 | */ |
mbed_official | 18:da299f395b9e | 222 | void system_gclk_gen_disable( |
mbed_official | 18:da299f395b9e | 223 | const uint8_t generator) |
mbed_official | 18:da299f395b9e | 224 | { |
mbed_official | 18:da299f395b9e | 225 | while (system_gclk_is_syncing(generator)) { |
mbed_official | 18:da299f395b9e | 226 | /* Wait for synchronization */ |
mbed_official | 18:da299f395b9e | 227 | }; |
mbed_official | 18:da299f395b9e | 228 | |
mbed_official | 18:da299f395b9e | 229 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 230 | |
mbed_official | 18:da299f395b9e | 231 | /* Disable generator */ |
mbed_official | 18:da299f395b9e | 232 | GCLK->GENCTRL[generator].reg &= ~GCLK_GENCTRL_GENEN; |
mbed_official | 18:da299f395b9e | 233 | while (GCLK->GENCTRL[generator].reg & GCLK_GENCTRL_GENEN) { |
mbed_official | 18:da299f395b9e | 234 | /* Wait for clock to become disabled */ |
mbed_official | 18:da299f395b9e | 235 | } |
mbed_official | 18:da299f395b9e | 236 | |
mbed_official | 18:da299f395b9e | 237 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 238 | } |
mbed_official | 18:da299f395b9e | 239 | |
mbed_official | 18:da299f395b9e | 240 | /** |
mbed_official | 18:da299f395b9e | 241 | * \brief Determins if the specified Generic Clock Generator is enabled. |
mbed_official | 18:da299f395b9e | 242 | * |
mbed_official | 18:da299f395b9e | 243 | * \param[in] generator Generic Clock Generator index to check |
mbed_official | 18:da299f395b9e | 244 | * |
mbed_official | 18:da299f395b9e | 245 | * \return The enabled status. |
mbed_official | 18:da299f395b9e | 246 | * \retval true The Generic Clock Generator is enabled |
mbed_official | 18:da299f395b9e | 247 | * \retval false The Generic Clock Generator is disabled |
mbed_official | 18:da299f395b9e | 248 | */ |
mbed_official | 18:da299f395b9e | 249 | bool system_gclk_gen_is_enabled( |
mbed_official | 18:da299f395b9e | 250 | const uint8_t generator) |
mbed_official | 18:da299f395b9e | 251 | { |
mbed_official | 18:da299f395b9e | 252 | bool enabled; |
mbed_official | 18:da299f395b9e | 253 | |
mbed_official | 18:da299f395b9e | 254 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 255 | |
mbed_official | 18:da299f395b9e | 256 | /* Obtain the enabled status */ |
mbed_official | 18:da299f395b9e | 257 | enabled = (GCLK->GENCTRL[generator].reg & GCLK_GENCTRL_GENEN); |
mbed_official | 18:da299f395b9e | 258 | |
mbed_official | 18:da299f395b9e | 259 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 260 | |
mbed_official | 18:da299f395b9e | 261 | return enabled; |
mbed_official | 18:da299f395b9e | 262 | } |
mbed_official | 18:da299f395b9e | 263 | |
mbed_official | 18:da299f395b9e | 264 | /** |
mbed_official | 18:da299f395b9e | 265 | * \brief Retrieves the clock frequency of a Generic Clock generator. |
mbed_official | 18:da299f395b9e | 266 | * |
mbed_official | 18:da299f395b9e | 267 | * Determines the clock frequency (in Hz) of a specified Generic Clock |
mbed_official | 18:da299f395b9e | 268 | * generator, used as a source to a Generic Clock Channel module. |
mbed_official | 18:da299f395b9e | 269 | * |
mbed_official | 18:da299f395b9e | 270 | * \param[in] generator Generic Clock Generator index |
mbed_official | 18:da299f395b9e | 271 | * |
mbed_official | 18:da299f395b9e | 272 | * \return The frequency of the generic clock generator, in Hz. |
mbed_official | 18:da299f395b9e | 273 | */ |
mbed_official | 18:da299f395b9e | 274 | uint32_t system_gclk_gen_get_hz( |
mbed_official | 18:da299f395b9e | 275 | const uint8_t generator) |
mbed_official | 18:da299f395b9e | 276 | { |
mbed_official | 18:da299f395b9e | 277 | while (system_gclk_is_syncing(generator)) { |
mbed_official | 18:da299f395b9e | 278 | /* Wait for synchronization */ |
mbed_official | 18:da299f395b9e | 279 | }; |
mbed_official | 18:da299f395b9e | 280 | |
mbed_official | 18:da299f395b9e | 281 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 282 | |
mbed_official | 18:da299f395b9e | 283 | /* Get the frequency of the source connected to the GCLK generator */ |
mbed_official | 18:da299f395b9e | 284 | uint32_t gen_input_hz = system_clock_source_get_hz( |
mbed_official | 18:da299f395b9e | 285 | (enum system_clock_source)GCLK->GENCTRL[generator].bit.SRC); |
mbed_official | 18:da299f395b9e | 286 | |
mbed_official | 18:da299f395b9e | 287 | uint8_t divsel = GCLK->GENCTRL[generator].bit.DIVSEL; |
mbed_official | 18:da299f395b9e | 288 | uint32_t divider = GCLK->GENCTRL[generator].bit.DIV; |
mbed_official | 18:da299f395b9e | 289 | |
mbed_official | 18:da299f395b9e | 290 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 291 | |
mbed_official | 18:da299f395b9e | 292 | /* Check if the generator is using fractional or binary division */ |
mbed_official | 18:da299f395b9e | 293 | if (!divsel && divider > 1) { |
mbed_official | 18:da299f395b9e | 294 | gen_input_hz /= divider; |
mbed_official | 18:da299f395b9e | 295 | } else if (divsel) { |
mbed_official | 18:da299f395b9e | 296 | gen_input_hz >>= (divider+1); |
mbed_official | 18:da299f395b9e | 297 | } |
mbed_official | 18:da299f395b9e | 298 | |
mbed_official | 18:da299f395b9e | 299 | return gen_input_hz; |
mbed_official | 18:da299f395b9e | 300 | } |
mbed_official | 18:da299f395b9e | 301 | |
mbed_official | 18:da299f395b9e | 302 | /** |
mbed_official | 18:da299f395b9e | 303 | * \brief Writes a Generic Clock configuration to the hardware module. |
mbed_official | 18:da299f395b9e | 304 | * |
mbed_official | 18:da299f395b9e | 305 | * Writes out a given configuration of a Generic Clock configuration to the |
mbed_official | 18:da299f395b9e | 306 | * hardware module. If the clock is currently running, it will be stopped. |
mbed_official | 18:da299f395b9e | 307 | * |
mbed_official | 18:da299f395b9e | 308 | * \note Once called the clock will not be running; to start the clock, |
mbed_official | 18:da299f395b9e | 309 | * call \ref system_gclk_chan_enable() after configuring a clock channel. |
mbed_official | 18:da299f395b9e | 310 | * |
mbed_official | 18:da299f395b9e | 311 | * \param[in] channel Generic Clock channel to configure |
mbed_official | 18:da299f395b9e | 312 | * \param[in] config Configuration settings for the clock |
mbed_official | 18:da299f395b9e | 313 | * |
mbed_official | 18:da299f395b9e | 314 | */ |
mbed_official | 18:da299f395b9e | 315 | void system_gclk_chan_set_config( |
mbed_official | 18:da299f395b9e | 316 | const uint8_t channel, |
mbed_official | 18:da299f395b9e | 317 | struct system_gclk_chan_config *const config) |
mbed_official | 18:da299f395b9e | 318 | { |
mbed_official | 18:da299f395b9e | 319 | /* Sanity check arguments */ |
mbed_official | 18:da299f395b9e | 320 | Assert(config); |
mbed_official | 18:da299f395b9e | 321 | |
mbed_official | 18:da299f395b9e | 322 | /* Disable generic clock channel */ |
mbed_official | 18:da299f395b9e | 323 | system_gclk_chan_disable(channel); |
mbed_official | 18:da299f395b9e | 324 | |
mbed_official | 18:da299f395b9e | 325 | /* Configure the peripheral channel */ |
mbed_official | 18:da299f395b9e | 326 | GCLK->PCHCTRL[channel].reg = GCLK_PCHCTRL_GEN(config->source_generator); |
mbed_official | 18:da299f395b9e | 327 | |
mbed_official | 18:da299f395b9e | 328 | |
mbed_official | 18:da299f395b9e | 329 | } |
mbed_official | 18:da299f395b9e | 330 | |
mbed_official | 18:da299f395b9e | 331 | /** |
mbed_official | 18:da299f395b9e | 332 | * \brief Enables a Generic Clock that was previously configured. |
mbed_official | 18:da299f395b9e | 333 | * |
mbed_official | 18:da299f395b9e | 334 | * Starts the clock generation of a Generic Clock that was previously |
mbed_official | 18:da299f395b9e | 335 | * configured via a call to \ref system_gclk_chan_set_config(). |
mbed_official | 18:da299f395b9e | 336 | * |
mbed_official | 18:da299f395b9e | 337 | * \param[in] channel Generic Clock channel to enable |
mbed_official | 18:da299f395b9e | 338 | */ |
mbed_official | 18:da299f395b9e | 339 | void system_gclk_chan_enable( |
mbed_official | 18:da299f395b9e | 340 | const uint8_t channel) |
mbed_official | 18:da299f395b9e | 341 | { |
mbed_official | 18:da299f395b9e | 342 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 343 | |
mbed_official | 18:da299f395b9e | 344 | /* Enable the peripheral channel */ |
mbed_official | 18:da299f395b9e | 345 | GCLK->PCHCTRL[channel].reg |= GCLK_PCHCTRL_CHEN; |
mbed_official | 18:da299f395b9e | 346 | |
mbed_official | 18:da299f395b9e | 347 | while (!(GCLK->PCHCTRL[channel].reg & GCLK_PCHCTRL_CHEN)) { |
mbed_official | 18:da299f395b9e | 348 | /* Wait for clock synchronization */ |
mbed_official | 18:da299f395b9e | 349 | } |
mbed_official | 18:da299f395b9e | 350 | |
mbed_official | 18:da299f395b9e | 351 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 352 | } |
mbed_official | 18:da299f395b9e | 353 | |
mbed_official | 18:da299f395b9e | 354 | /** |
mbed_official | 18:da299f395b9e | 355 | * \brief Disables a Generic Clock that was previously enabled. |
mbed_official | 18:da299f395b9e | 356 | * |
mbed_official | 18:da299f395b9e | 357 | * Stops the clock generation of a Generic Clock that was previously started |
mbed_official | 18:da299f395b9e | 358 | * via a call to \ref system_gclk_chan_enable(). |
mbed_official | 18:da299f395b9e | 359 | * |
mbed_official | 18:da299f395b9e | 360 | * \param[in] channel Generic Clock channel to disable |
mbed_official | 18:da299f395b9e | 361 | */ |
mbed_official | 18:da299f395b9e | 362 | void system_gclk_chan_disable( |
mbed_official | 18:da299f395b9e | 363 | const uint8_t channel) |
mbed_official | 18:da299f395b9e | 364 | { |
mbed_official | 18:da299f395b9e | 365 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 366 | |
mbed_official | 18:da299f395b9e | 367 | /* Sanity check WRTLOCK */ |
mbed_official | 18:da299f395b9e | 368 | Assert(!GCLK->PCHCTRL[channel].bit.WRTLOCK); |
mbed_official | 18:da299f395b9e | 369 | |
mbed_official | 18:da299f395b9e | 370 | /* Disable the peripheral channel */ |
mbed_official | 18:da299f395b9e | 371 | GCLK->PCHCTRL[channel].reg &= ~GCLK_PCHCTRL_CHEN; |
mbed_official | 18:da299f395b9e | 372 | |
mbed_official | 18:da299f395b9e | 373 | while (GCLK->PCHCTRL[channel].reg & GCLK_PCHCTRL_CHEN) { |
mbed_official | 18:da299f395b9e | 374 | /* Wait for clock synchronization */ |
mbed_official | 18:da299f395b9e | 375 | } |
mbed_official | 18:da299f395b9e | 376 | |
mbed_official | 18:da299f395b9e | 377 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 378 | } |
mbed_official | 18:da299f395b9e | 379 | |
mbed_official | 18:da299f395b9e | 380 | /** |
mbed_official | 18:da299f395b9e | 381 | * \brief Determins if the specified Generic Clock channel is enabled. |
mbed_official | 18:da299f395b9e | 382 | * |
mbed_official | 18:da299f395b9e | 383 | * \param[in] channel Generic Clock Channel index |
mbed_official | 18:da299f395b9e | 384 | * |
mbed_official | 18:da299f395b9e | 385 | * \return The enabled status. |
mbed_official | 18:da299f395b9e | 386 | * \retval true The Generic Clock channel is enabled |
mbed_official | 18:da299f395b9e | 387 | * \retval false The Generic Clock channel is disabled |
mbed_official | 18:da299f395b9e | 388 | */ |
mbed_official | 18:da299f395b9e | 389 | bool system_gclk_chan_is_enabled( |
mbed_official | 18:da299f395b9e | 390 | const uint8_t channel) |
mbed_official | 18:da299f395b9e | 391 | { |
mbed_official | 18:da299f395b9e | 392 | bool enabled; |
mbed_official | 18:da299f395b9e | 393 | |
mbed_official | 18:da299f395b9e | 394 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 395 | |
mbed_official | 18:da299f395b9e | 396 | /* Select the requested generic clock channel */ |
mbed_official | 18:da299f395b9e | 397 | enabled = GCLK->PCHCTRL[channel].bit.CHEN; |
mbed_official | 18:da299f395b9e | 398 | |
mbed_official | 18:da299f395b9e | 399 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 400 | |
mbed_official | 18:da299f395b9e | 401 | return enabled; |
mbed_official | 18:da299f395b9e | 402 | } |
mbed_official | 18:da299f395b9e | 403 | |
mbed_official | 18:da299f395b9e | 404 | /** |
mbed_official | 18:da299f395b9e | 405 | * \brief Locks a Generic Clock channel from further configuration writes. |
mbed_official | 18:da299f395b9e | 406 | * |
mbed_official | 18:da299f395b9e | 407 | * Locks a generic clock channel from further configuration writes. It is only |
mbed_official | 18:da299f395b9e | 408 | * possible to unlock the channel configuration through a power on reset. |
mbed_official | 18:da299f395b9e | 409 | * |
mbed_official | 18:da299f395b9e | 410 | * \param[in] channel Generic Clock channel to enable |
mbed_official | 18:da299f395b9e | 411 | */ |
mbed_official | 18:da299f395b9e | 412 | void system_gclk_chan_lock( |
mbed_official | 18:da299f395b9e | 413 | const uint8_t channel) |
mbed_official | 18:da299f395b9e | 414 | { |
mbed_official | 18:da299f395b9e | 415 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 416 | |
mbed_official | 18:da299f395b9e | 417 | GCLK->PCHCTRL[channel].reg |= GCLK_PCHCTRL_WRTLOCK; |
mbed_official | 18:da299f395b9e | 418 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 419 | } |
mbed_official | 18:da299f395b9e | 420 | |
mbed_official | 18:da299f395b9e | 421 | /** |
mbed_official | 18:da299f395b9e | 422 | * \brief Determins if the specified Generic Clock channel is locked. |
mbed_official | 18:da299f395b9e | 423 | * |
mbed_official | 18:da299f395b9e | 424 | * \param[in] channel Generic Clock Channel index |
mbed_official | 18:da299f395b9e | 425 | * |
mbed_official | 18:da299f395b9e | 426 | * \return The lock status. |
mbed_official | 18:da299f395b9e | 427 | * \retval true The Generic Clock channel is locked |
mbed_official | 18:da299f395b9e | 428 | * \retval false The Generic Clock channel is not locked |
mbed_official | 18:da299f395b9e | 429 | */ |
mbed_official | 18:da299f395b9e | 430 | bool system_gclk_chan_is_locked( |
mbed_official | 18:da299f395b9e | 431 | const uint8_t channel) |
mbed_official | 18:da299f395b9e | 432 | { |
mbed_official | 18:da299f395b9e | 433 | bool locked; |
mbed_official | 18:da299f395b9e | 434 | |
mbed_official | 18:da299f395b9e | 435 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 436 | locked = GCLK->PCHCTRL[channel].bit.WRTLOCK; |
mbed_official | 18:da299f395b9e | 437 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 438 | |
mbed_official | 18:da299f395b9e | 439 | return locked; |
mbed_official | 18:da299f395b9e | 440 | } |
mbed_official | 18:da299f395b9e | 441 | |
mbed_official | 18:da299f395b9e | 442 | /** |
mbed_official | 18:da299f395b9e | 443 | * \brief Retrieves the clock frequency of a Generic Clock channel. |
mbed_official | 18:da299f395b9e | 444 | * |
mbed_official | 18:da299f395b9e | 445 | * Determines the clock frequency (in Hz) of a specified Generic Clock |
mbed_official | 18:da299f395b9e | 446 | * channel, used as a source to a device peripheral module. |
mbed_official | 18:da299f395b9e | 447 | * |
mbed_official | 18:da299f395b9e | 448 | * \param[in] channel Generic Clock Channel index |
mbed_official | 18:da299f395b9e | 449 | * |
mbed_official | 18:da299f395b9e | 450 | * \return The frequency of the generic clock channel, in Hz. |
mbed_official | 18:da299f395b9e | 451 | */ |
mbed_official | 18:da299f395b9e | 452 | uint32_t system_gclk_chan_get_hz( |
mbed_official | 18:da299f395b9e | 453 | const uint8_t channel) |
mbed_official | 18:da299f395b9e | 454 | { |
mbed_official | 18:da299f395b9e | 455 | uint8_t gen_id; |
mbed_official | 18:da299f395b9e | 456 | |
mbed_official | 18:da299f395b9e | 457 | system_interrupt_enter_critical_section(); |
mbed_official | 18:da299f395b9e | 458 | /* Select the requested generic clock channel */ |
mbed_official | 18:da299f395b9e | 459 | gen_id = GCLK->PCHCTRL[channel].bit.GEN; |
mbed_official | 18:da299f395b9e | 460 | system_interrupt_leave_critical_section(); |
mbed_official | 18:da299f395b9e | 461 | |
mbed_official | 18:da299f395b9e | 462 | /* Return the clock speed of the associated GCLK generator */ |
mbed_official | 18:da299f395b9e | 463 | return system_gclk_gen_get_hz(gen_id); |
mbed_official | 18:da299f395b9e | 464 | } |