mbed library sources. Supersedes mbed-src.

Fork of mbed-dev by mbed official

Committer:
mbed_official
Date:
Wed Nov 04 16:30:11 2015 +0000
Revision:
15:a81a8d6c1dfe
Synchronized with git revision 46af745ef4405614c3fa49abbd9a706a362ea514

Full URL: https://github.com/mbedmicro/mbed/commit/46af745ef4405614c3fa49abbd9a706a362ea514/

Renamed TARGET_SAM_CortexM0+ to TARGET_SAM_CortexM0P for compatiblity with online compiler

Who changed what in which revision?

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