mbed library sources

Fork of mbed-src by mbed official

Committer:
mbed_official
Date:
Wed Jul 01 09:45:11 2015 +0100
Revision:
579:53297373a894
Child:
592:a274ee790e56
Synchronized with git revision d5b4d2ab9c47edb4dc5776e7177b0c2263459081

Full URL: https://github.com/mbedmicro/mbed/commit/d5b4d2ab9c47edb4dc5776e7177b0c2263459081/

Initial version of drivers for SAMR21

Who changed what in which revision?

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