mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

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 }