Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sun May 14 23:18:57 2017 +0000
Revision:
18:6a4db94011d3
Publishing again

Who changed what in which revision?

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