Mouse code for the MacroRat

Dependencies:   ITG3200 QEI

Committer:
sahilmgandhi
Date:
Sat Jun 03 00:22:44 2017 +0000
Revision:
46:b156ef445742
Parent:
18:6a4db94011d3
Final code for internal battlebot competition.

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 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 #include <clock.h>
sahilmgandhi 18:6a4db94011d3 47 #include <conf_clocks.h>
sahilmgandhi 18:6a4db94011d3 48 #include <system.h>
sahilmgandhi 18:6a4db94011d3 49
sahilmgandhi 18:6a4db94011d3 50 #ifndef SYSCTRL_FUSES_OSC32K_ADDR
sahilmgandhi 18:6a4db94011d3 51 #if (SAMR21) || (SAMD)
sahilmgandhi 18:6a4db94011d3 52 # define SYSCTRL_FUSES_OSC32K_ADDR FUSES_OSC32K_CAL_ADDR
sahilmgandhi 18:6a4db94011d3 53 # define SYSCTRL_FUSES_OSC32K_Pos FUSES_OSC32K_CAL_Pos
sahilmgandhi 18:6a4db94011d3 54 #elif (SAML21)
sahilmgandhi 18:6a4db94011d3 55 # define SYSCTRL_FUSES_OSC32K_ADDR NVMCTRL_OTP4
sahilmgandhi 18:6a4db94011d3 56 # define SYSCTRL_FUSES_OSC32K_Pos 6
sahilmgandhi 18:6a4db94011d3 57
sahilmgandhi 18:6a4db94011d3 58 #else
sahilmgandhi 18:6a4db94011d3 59 # define SYSCTRL_FUSES_OSC32K_ADDR SYSCTRL_FUSES_OSC32K_CAL_ADDR
sahilmgandhi 18:6a4db94011d3 60 # define SYSCTRL_FUSES_OSC32K_Pos SYSCTRL_FUSES_OSC32K_CAL_Pos
sahilmgandhi 18:6a4db94011d3 61 #endif
sahilmgandhi 18:6a4db94011d3 62 #endif
sahilmgandhi 18:6a4db94011d3 63
sahilmgandhi 18:6a4db94011d3 64 /**
sahilmgandhi 18:6a4db94011d3 65 * \internal
sahilmgandhi 18:6a4db94011d3 66 * \brief DFLL-specific data container.
sahilmgandhi 18:6a4db94011d3 67 */
sahilmgandhi 18:6a4db94011d3 68 struct _system_clock_dfll_config {
sahilmgandhi 18:6a4db94011d3 69 uint32_t control;
sahilmgandhi 18:6a4db94011d3 70 uint32_t val;
sahilmgandhi 18:6a4db94011d3 71 uint32_t mul;
sahilmgandhi 18:6a4db94011d3 72 };
sahilmgandhi 18:6a4db94011d3 73
sahilmgandhi 18:6a4db94011d3 74 /**
sahilmgandhi 18:6a4db94011d3 75 * \internal
sahilmgandhi 18:6a4db94011d3 76 * \brief DPLL-specific data container.
sahilmgandhi 18:6a4db94011d3 77 */
sahilmgandhi 18:6a4db94011d3 78 struct _system_clock_dpll_config {
sahilmgandhi 18:6a4db94011d3 79 uint32_t frequency;
sahilmgandhi 18:6a4db94011d3 80 };
sahilmgandhi 18:6a4db94011d3 81
sahilmgandhi 18:6a4db94011d3 82
sahilmgandhi 18:6a4db94011d3 83 /**
sahilmgandhi 18:6a4db94011d3 84 * \internal
sahilmgandhi 18:6a4db94011d3 85 * \brief XOSC-specific data container.
sahilmgandhi 18:6a4db94011d3 86 */
sahilmgandhi 18:6a4db94011d3 87 struct _system_clock_xosc_config {
sahilmgandhi 18:6a4db94011d3 88 uint32_t frequency;
sahilmgandhi 18:6a4db94011d3 89 };
sahilmgandhi 18:6a4db94011d3 90
sahilmgandhi 18:6a4db94011d3 91 /**
sahilmgandhi 18:6a4db94011d3 92 * \internal
sahilmgandhi 18:6a4db94011d3 93 * \brief System clock module data container.
sahilmgandhi 18:6a4db94011d3 94 */
sahilmgandhi 18:6a4db94011d3 95 struct _system_clock_module {
sahilmgandhi 18:6a4db94011d3 96 volatile struct _system_clock_dfll_config dfll;
sahilmgandhi 18:6a4db94011d3 97
sahilmgandhi 18:6a4db94011d3 98 #ifdef FEATURE_SYSTEM_CLOCK_DPLL
sahilmgandhi 18:6a4db94011d3 99 volatile struct _system_clock_dpll_config dpll;
sahilmgandhi 18:6a4db94011d3 100 #endif
sahilmgandhi 18:6a4db94011d3 101
sahilmgandhi 18:6a4db94011d3 102 volatile struct _system_clock_xosc_config xosc;
sahilmgandhi 18:6a4db94011d3 103 volatile struct _system_clock_xosc_config xosc32k;
sahilmgandhi 18:6a4db94011d3 104 };
sahilmgandhi 18:6a4db94011d3 105
sahilmgandhi 18:6a4db94011d3 106 /**
sahilmgandhi 18:6a4db94011d3 107 * \internal
sahilmgandhi 18:6a4db94011d3 108 * \brief Internal module instance to cache configuration values.
sahilmgandhi 18:6a4db94011d3 109 */
sahilmgandhi 18:6a4db94011d3 110 static struct _system_clock_module _system_clock_inst = {
sahilmgandhi 18:6a4db94011d3 111 .dfll = {
sahilmgandhi 18:6a4db94011d3 112 .control = 0,
sahilmgandhi 18:6a4db94011d3 113 .val = 0,
sahilmgandhi 18:6a4db94011d3 114 .mul = 0,
sahilmgandhi 18:6a4db94011d3 115 },
sahilmgandhi 18:6a4db94011d3 116
sahilmgandhi 18:6a4db94011d3 117 #ifdef FEATURE_SYSTEM_CLOCK_DPLL
sahilmgandhi 18:6a4db94011d3 118 .dpll = {
sahilmgandhi 18:6a4db94011d3 119 .frequency = 0,
sahilmgandhi 18:6a4db94011d3 120 },
sahilmgandhi 18:6a4db94011d3 121 #endif
sahilmgandhi 18:6a4db94011d3 122 .xosc = {
sahilmgandhi 18:6a4db94011d3 123 .frequency = 0,
sahilmgandhi 18:6a4db94011d3 124 },
sahilmgandhi 18:6a4db94011d3 125 .xosc32k = {
sahilmgandhi 18:6a4db94011d3 126 .frequency = 0,
sahilmgandhi 18:6a4db94011d3 127 },
sahilmgandhi 18:6a4db94011d3 128 };
sahilmgandhi 18:6a4db94011d3 129
sahilmgandhi 18:6a4db94011d3 130 /**
sahilmgandhi 18:6a4db94011d3 131 * \internal
sahilmgandhi 18:6a4db94011d3 132 * \brief Wait for sync to the DFLL control registers.
sahilmgandhi 18:6a4db94011d3 133 */
sahilmgandhi 18:6a4db94011d3 134 static inline void _system_dfll_wait_for_sync(void)
sahilmgandhi 18:6a4db94011d3 135 {
sahilmgandhi 18:6a4db94011d3 136 while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY)) {
sahilmgandhi 18:6a4db94011d3 137 /* Wait for DFLL sync */
sahilmgandhi 18:6a4db94011d3 138 }
sahilmgandhi 18:6a4db94011d3 139 }
sahilmgandhi 18:6a4db94011d3 140
sahilmgandhi 18:6a4db94011d3 141 /**
sahilmgandhi 18:6a4db94011d3 142 * \internal
sahilmgandhi 18:6a4db94011d3 143 * \brief Wait for sync to the OSC32K control registers.
sahilmgandhi 18:6a4db94011d3 144 */
sahilmgandhi 18:6a4db94011d3 145 static inline void _system_osc32k_wait_for_sync(void)
sahilmgandhi 18:6a4db94011d3 146 {
sahilmgandhi 18:6a4db94011d3 147 while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC32KRDY)) {
sahilmgandhi 18:6a4db94011d3 148 /* Wait for OSC32K sync */
sahilmgandhi 18:6a4db94011d3 149 }
sahilmgandhi 18:6a4db94011d3 150 }
sahilmgandhi 18:6a4db94011d3 151
sahilmgandhi 18:6a4db94011d3 152 static inline void _system_clock_source_dfll_set_config_errata_9905(void)
sahilmgandhi 18:6a4db94011d3 153 {
sahilmgandhi 18:6a4db94011d3 154
sahilmgandhi 18:6a4db94011d3 155 /* Disable ONDEMAND mode while writing configurations */
sahilmgandhi 18:6a4db94011d3 156 SYSCTRL->DFLLCTRL.reg = _system_clock_inst.dfll.control & ~SYSCTRL_DFLLCTRL_ONDEMAND;
sahilmgandhi 18:6a4db94011d3 157 _system_dfll_wait_for_sync();
sahilmgandhi 18:6a4db94011d3 158
sahilmgandhi 18:6a4db94011d3 159 SYSCTRL->DFLLMUL.reg = _system_clock_inst.dfll.mul;
sahilmgandhi 18:6a4db94011d3 160 SYSCTRL->DFLLVAL.reg = _system_clock_inst.dfll.val;
sahilmgandhi 18:6a4db94011d3 161
sahilmgandhi 18:6a4db94011d3 162 /* Write full configuration to DFLL control register */
sahilmgandhi 18:6a4db94011d3 163 SYSCTRL->DFLLCTRL.reg = _system_clock_inst.dfll.control;
sahilmgandhi 18:6a4db94011d3 164 }
sahilmgandhi 18:6a4db94011d3 165
sahilmgandhi 18:6a4db94011d3 166 /**
sahilmgandhi 18:6a4db94011d3 167 * \brief Retrieve the frequency of a clock source.
sahilmgandhi 18:6a4db94011d3 168 *
sahilmgandhi 18:6a4db94011d3 169 * Determines the current operating frequency of a given clock source.
sahilmgandhi 18:6a4db94011d3 170 *
sahilmgandhi 18:6a4db94011d3 171 * \param[in] clock_source Clock source to get the frequency
sahilmgandhi 18:6a4db94011d3 172 *
sahilmgandhi 18:6a4db94011d3 173 * \returns Frequency of the given clock source, in Hz.
sahilmgandhi 18:6a4db94011d3 174 */
sahilmgandhi 18:6a4db94011d3 175 uint32_t system_clock_source_get_hz(
sahilmgandhi 18:6a4db94011d3 176 const enum system_clock_source clock_source)
sahilmgandhi 18:6a4db94011d3 177 {
sahilmgandhi 18:6a4db94011d3 178 switch (clock_source) {
sahilmgandhi 18:6a4db94011d3 179 case SYSTEM_CLOCK_SOURCE_XOSC:
sahilmgandhi 18:6a4db94011d3 180 return _system_clock_inst.xosc.frequency;
sahilmgandhi 18:6a4db94011d3 181
sahilmgandhi 18:6a4db94011d3 182 case SYSTEM_CLOCK_SOURCE_OSC8M:
sahilmgandhi 18:6a4db94011d3 183 return 8000000UL >> SYSCTRL->OSC8M.bit.PRESC;
sahilmgandhi 18:6a4db94011d3 184
sahilmgandhi 18:6a4db94011d3 185 case SYSTEM_CLOCK_SOURCE_OSC32K:
sahilmgandhi 18:6a4db94011d3 186 return 32768UL;
sahilmgandhi 18:6a4db94011d3 187
sahilmgandhi 18:6a4db94011d3 188 case SYSTEM_CLOCK_SOURCE_ULP32K:
sahilmgandhi 18:6a4db94011d3 189 return 32768UL;
sahilmgandhi 18:6a4db94011d3 190
sahilmgandhi 18:6a4db94011d3 191 case SYSTEM_CLOCK_SOURCE_XOSC32K:
sahilmgandhi 18:6a4db94011d3 192 return _system_clock_inst.xosc32k.frequency;
sahilmgandhi 18:6a4db94011d3 193
sahilmgandhi 18:6a4db94011d3 194 case SYSTEM_CLOCK_SOURCE_DFLL:
sahilmgandhi 18:6a4db94011d3 195
sahilmgandhi 18:6a4db94011d3 196 /* Check if the DFLL has been configured */
sahilmgandhi 18:6a4db94011d3 197 if (!(_system_clock_inst.dfll.control & SYSCTRL_DFLLCTRL_ENABLE))
sahilmgandhi 18:6a4db94011d3 198 return 0;
sahilmgandhi 18:6a4db94011d3 199
sahilmgandhi 18:6a4db94011d3 200 /* Make sure that the DFLL module is ready */
sahilmgandhi 18:6a4db94011d3 201 _system_dfll_wait_for_sync();
sahilmgandhi 18:6a4db94011d3 202
sahilmgandhi 18:6a4db94011d3 203 /* Check if operating in closed loop mode */
sahilmgandhi 18:6a4db94011d3 204 if (_system_clock_inst.dfll.control & SYSCTRL_DFLLCTRL_MODE) {
sahilmgandhi 18:6a4db94011d3 205 return system_gclk_chan_get_hz(SYSCTRL_GCLK_ID_DFLL48) *
sahilmgandhi 18:6a4db94011d3 206 (_system_clock_inst.dfll.mul & 0xffff);
sahilmgandhi 18:6a4db94011d3 207 }
sahilmgandhi 18:6a4db94011d3 208
sahilmgandhi 18:6a4db94011d3 209 return 48000000UL;
sahilmgandhi 18:6a4db94011d3 210
sahilmgandhi 18:6a4db94011d3 211 #ifdef FEATURE_SYSTEM_CLOCK_DPLL
sahilmgandhi 18:6a4db94011d3 212 case SYSTEM_CLOCK_SOURCE_DPLL:
sahilmgandhi 18:6a4db94011d3 213 if (!(SYSCTRL->DPLLSTATUS.reg & SYSCTRL_DPLLSTATUS_ENABLE)) {
sahilmgandhi 18:6a4db94011d3 214 return 0;
sahilmgandhi 18:6a4db94011d3 215 }
sahilmgandhi 18:6a4db94011d3 216
sahilmgandhi 18:6a4db94011d3 217 return _system_clock_inst.dpll.frequency;
sahilmgandhi 18:6a4db94011d3 218 #endif
sahilmgandhi 18:6a4db94011d3 219
sahilmgandhi 18:6a4db94011d3 220 default:
sahilmgandhi 18:6a4db94011d3 221 return 0;
sahilmgandhi 18:6a4db94011d3 222 }
sahilmgandhi 18:6a4db94011d3 223 }
sahilmgandhi 18:6a4db94011d3 224
sahilmgandhi 18:6a4db94011d3 225 /**
sahilmgandhi 18:6a4db94011d3 226 * \brief Configure the internal OSC8M oscillator clock source.
sahilmgandhi 18:6a4db94011d3 227 *
sahilmgandhi 18:6a4db94011d3 228 * Configures the 8MHz (nominal) internal RC oscillator with the given
sahilmgandhi 18:6a4db94011d3 229 * configuration settings.
sahilmgandhi 18:6a4db94011d3 230 *
sahilmgandhi 18:6a4db94011d3 231 * \param[in] config OSC8M configuration structure containing the new config
sahilmgandhi 18:6a4db94011d3 232 */
sahilmgandhi 18:6a4db94011d3 233 void system_clock_source_osc8m_set_config(
sahilmgandhi 18:6a4db94011d3 234 struct system_clock_source_osc8m_config *const config)
sahilmgandhi 18:6a4db94011d3 235 {
sahilmgandhi 18:6a4db94011d3 236 SYSCTRL_OSC8M_Type temp = SYSCTRL->OSC8M;
sahilmgandhi 18:6a4db94011d3 237
sahilmgandhi 18:6a4db94011d3 238 /* Use temporary struct to reduce register access */
sahilmgandhi 18:6a4db94011d3 239 temp.bit.PRESC = config->prescaler;
sahilmgandhi 18:6a4db94011d3 240 temp.bit.ONDEMAND = config->on_demand;
sahilmgandhi 18:6a4db94011d3 241 temp.bit.RUNSTDBY = config->run_in_standby;
sahilmgandhi 18:6a4db94011d3 242
sahilmgandhi 18:6a4db94011d3 243 SYSCTRL->OSC8M = temp;
sahilmgandhi 18:6a4db94011d3 244 }
sahilmgandhi 18:6a4db94011d3 245
sahilmgandhi 18:6a4db94011d3 246 /**
sahilmgandhi 18:6a4db94011d3 247 * \brief Configure the internal OSC32K oscillator clock source.
sahilmgandhi 18:6a4db94011d3 248 *
sahilmgandhi 18:6a4db94011d3 249 * Configures the 32KHz (nominal) internal RC oscillator with the given
sahilmgandhi 18:6a4db94011d3 250 * configuration settings.
sahilmgandhi 18:6a4db94011d3 251 *
sahilmgandhi 18:6a4db94011d3 252 * \param[in] config OSC32K configuration structure containing the new config
sahilmgandhi 18:6a4db94011d3 253 */
sahilmgandhi 18:6a4db94011d3 254 void system_clock_source_osc32k_set_config(
sahilmgandhi 18:6a4db94011d3 255 struct system_clock_source_osc32k_config *const config)
sahilmgandhi 18:6a4db94011d3 256 {
sahilmgandhi 18:6a4db94011d3 257 SYSCTRL_OSC32K_Type temp = SYSCTRL->OSC32K;
sahilmgandhi 18:6a4db94011d3 258
sahilmgandhi 18:6a4db94011d3 259 /* Update settings via a temporary struct to reduce register access */
sahilmgandhi 18:6a4db94011d3 260 temp.bit.EN1K = config->enable_1khz_output;
sahilmgandhi 18:6a4db94011d3 261 temp.bit.EN32K = config->enable_32khz_output;
sahilmgandhi 18:6a4db94011d3 262 temp.bit.STARTUP = config->startup_time;
sahilmgandhi 18:6a4db94011d3 263 temp.bit.ONDEMAND = config->on_demand;
sahilmgandhi 18:6a4db94011d3 264 temp.bit.RUNSTDBY = config->run_in_standby;
sahilmgandhi 18:6a4db94011d3 265 temp.bit.WRTLOCK = config->write_once;
sahilmgandhi 18:6a4db94011d3 266
sahilmgandhi 18:6a4db94011d3 267 SYSCTRL->OSC32K = temp;
sahilmgandhi 18:6a4db94011d3 268 }
sahilmgandhi 18:6a4db94011d3 269
sahilmgandhi 18:6a4db94011d3 270 /**
sahilmgandhi 18:6a4db94011d3 271 * \brief Configure the external oscillator clock source.
sahilmgandhi 18:6a4db94011d3 272 *
sahilmgandhi 18:6a4db94011d3 273 * Configures the external oscillator clock source with the given configuration
sahilmgandhi 18:6a4db94011d3 274 * settings.
sahilmgandhi 18:6a4db94011d3 275 *
sahilmgandhi 18:6a4db94011d3 276 * \param[in] config External oscillator configuration structure containing
sahilmgandhi 18:6a4db94011d3 277 * the new config
sahilmgandhi 18:6a4db94011d3 278 */
sahilmgandhi 18:6a4db94011d3 279 void system_clock_source_xosc_set_config(
sahilmgandhi 18:6a4db94011d3 280 struct system_clock_source_xosc_config *const config)
sahilmgandhi 18:6a4db94011d3 281 {
sahilmgandhi 18:6a4db94011d3 282 SYSCTRL_XOSC_Type temp = SYSCTRL->XOSC;
sahilmgandhi 18:6a4db94011d3 283
sahilmgandhi 18:6a4db94011d3 284 temp.bit.STARTUP = config->startup_time;
sahilmgandhi 18:6a4db94011d3 285
sahilmgandhi 18:6a4db94011d3 286 if (config->external_clock == SYSTEM_CLOCK_EXTERNAL_CRYSTAL) {
sahilmgandhi 18:6a4db94011d3 287 temp.bit.XTALEN = 1;
sahilmgandhi 18:6a4db94011d3 288 } else {
sahilmgandhi 18:6a4db94011d3 289 temp.bit.XTALEN = 0;
sahilmgandhi 18:6a4db94011d3 290 }
sahilmgandhi 18:6a4db94011d3 291
sahilmgandhi 18:6a4db94011d3 292 temp.bit.AMPGC = config->auto_gain_control;
sahilmgandhi 18:6a4db94011d3 293
sahilmgandhi 18:6a4db94011d3 294 /* Set gain if automatic gain control is not selected */
sahilmgandhi 18:6a4db94011d3 295 if (!config->auto_gain_control) {
sahilmgandhi 18:6a4db94011d3 296 if (config->frequency <= 2000000) {
sahilmgandhi 18:6a4db94011d3 297 temp.bit.GAIN = 0;
sahilmgandhi 18:6a4db94011d3 298 } else if (config->frequency <= 4000000) {
sahilmgandhi 18:6a4db94011d3 299 temp.bit.GAIN = 1;
sahilmgandhi 18:6a4db94011d3 300 } else if (config->frequency <= 8000000) {
sahilmgandhi 18:6a4db94011d3 301 temp.bit.GAIN = 2;
sahilmgandhi 18:6a4db94011d3 302 } else if (config->frequency <= 16000000) {
sahilmgandhi 18:6a4db94011d3 303 temp.bit.GAIN = 3;
sahilmgandhi 18:6a4db94011d3 304 } else if (config->frequency <= 30000000) {
sahilmgandhi 18:6a4db94011d3 305 temp.bit.GAIN = 4;
sahilmgandhi 18:6a4db94011d3 306 }
sahilmgandhi 18:6a4db94011d3 307
sahilmgandhi 18:6a4db94011d3 308 }
sahilmgandhi 18:6a4db94011d3 309
sahilmgandhi 18:6a4db94011d3 310 temp.bit.ONDEMAND = config->on_demand;
sahilmgandhi 18:6a4db94011d3 311 temp.bit.RUNSTDBY = config->run_in_standby;
sahilmgandhi 18:6a4db94011d3 312
sahilmgandhi 18:6a4db94011d3 313 /* Store XOSC frequency for internal use */
sahilmgandhi 18:6a4db94011d3 314 _system_clock_inst.xosc.frequency = config->frequency;
sahilmgandhi 18:6a4db94011d3 315
sahilmgandhi 18:6a4db94011d3 316 SYSCTRL->XOSC = temp;
sahilmgandhi 18:6a4db94011d3 317 }
sahilmgandhi 18:6a4db94011d3 318
sahilmgandhi 18:6a4db94011d3 319 /**
sahilmgandhi 18:6a4db94011d3 320 * \brief Configure the XOSC32K external 32KHz oscillator clock source.
sahilmgandhi 18:6a4db94011d3 321 *
sahilmgandhi 18:6a4db94011d3 322 * Configures the external 32KHz oscillator clock source with the given
sahilmgandhi 18:6a4db94011d3 323 * configuration settings.
sahilmgandhi 18:6a4db94011d3 324 *
sahilmgandhi 18:6a4db94011d3 325 * \param[in] config XOSC32K configuration structure containing the new config
sahilmgandhi 18:6a4db94011d3 326 */
sahilmgandhi 18:6a4db94011d3 327 void system_clock_source_xosc32k_set_config(
sahilmgandhi 18:6a4db94011d3 328 struct system_clock_source_xosc32k_config *const config)
sahilmgandhi 18:6a4db94011d3 329 {
sahilmgandhi 18:6a4db94011d3 330 SYSCTRL_XOSC32K_Type temp = SYSCTRL->XOSC32K;
sahilmgandhi 18:6a4db94011d3 331
sahilmgandhi 18:6a4db94011d3 332 temp.bit.STARTUP = config->startup_time;
sahilmgandhi 18:6a4db94011d3 333
sahilmgandhi 18:6a4db94011d3 334 if (config->external_clock == SYSTEM_CLOCK_EXTERNAL_CRYSTAL) {
sahilmgandhi 18:6a4db94011d3 335 temp.bit.XTALEN = 1;
sahilmgandhi 18:6a4db94011d3 336 } else {
sahilmgandhi 18:6a4db94011d3 337 temp.bit.XTALEN = 0;
sahilmgandhi 18:6a4db94011d3 338 }
sahilmgandhi 18:6a4db94011d3 339
sahilmgandhi 18:6a4db94011d3 340 temp.bit.AAMPEN = config->auto_gain_control;
sahilmgandhi 18:6a4db94011d3 341 temp.bit.EN1K = config->enable_1khz_output;
sahilmgandhi 18:6a4db94011d3 342 temp.bit.EN32K = config->enable_32khz_output;
sahilmgandhi 18:6a4db94011d3 343
sahilmgandhi 18:6a4db94011d3 344 temp.bit.ONDEMAND = config->on_demand;
sahilmgandhi 18:6a4db94011d3 345 temp.bit.RUNSTDBY = config->run_in_standby;
sahilmgandhi 18:6a4db94011d3 346 temp.bit.WRTLOCK = config->write_once;
sahilmgandhi 18:6a4db94011d3 347
sahilmgandhi 18:6a4db94011d3 348 /* Cache the new frequency in case the user needs to check the current
sahilmgandhi 18:6a4db94011d3 349 * operating frequency later */
sahilmgandhi 18:6a4db94011d3 350 _system_clock_inst.xosc32k.frequency = config->frequency;
sahilmgandhi 18:6a4db94011d3 351
sahilmgandhi 18:6a4db94011d3 352 SYSCTRL->XOSC32K = temp;
sahilmgandhi 18:6a4db94011d3 353 }
sahilmgandhi 18:6a4db94011d3 354
sahilmgandhi 18:6a4db94011d3 355 /**
sahilmgandhi 18:6a4db94011d3 356 * \brief Configure the DFLL clock source.
sahilmgandhi 18:6a4db94011d3 357 *
sahilmgandhi 18:6a4db94011d3 358 * Configures the Digital Frequency Locked Loop clock source with the given
sahilmgandhi 18:6a4db94011d3 359 * configuration settings.
sahilmgandhi 18:6a4db94011d3 360 *
sahilmgandhi 18:6a4db94011d3 361 * \note The DFLL will be running when this function returns, as the DFLL module
sahilmgandhi 18:6a4db94011d3 362 * needs to be enabled in order to perform the module configuration.
sahilmgandhi 18:6a4db94011d3 363 *
sahilmgandhi 18:6a4db94011d3 364 * \param[in] config DFLL configuration structure containing the new config
sahilmgandhi 18:6a4db94011d3 365 */
sahilmgandhi 18:6a4db94011d3 366 void system_clock_source_dfll_set_config(
sahilmgandhi 18:6a4db94011d3 367 struct system_clock_source_dfll_config *const config)
sahilmgandhi 18:6a4db94011d3 368 {
sahilmgandhi 18:6a4db94011d3 369 _system_clock_inst.dfll.val =
sahilmgandhi 18:6a4db94011d3 370 SYSCTRL_DFLLVAL_COARSE(config->coarse_value) |
sahilmgandhi 18:6a4db94011d3 371 SYSCTRL_DFLLVAL_FINE(config->fine_value);
sahilmgandhi 18:6a4db94011d3 372
sahilmgandhi 18:6a4db94011d3 373 _system_clock_inst.dfll.control =
sahilmgandhi 18:6a4db94011d3 374 (uint32_t)config->wakeup_lock |
sahilmgandhi 18:6a4db94011d3 375 (uint32_t)config->stable_tracking |
sahilmgandhi 18:6a4db94011d3 376 (uint32_t)config->quick_lock |
sahilmgandhi 18:6a4db94011d3 377 (uint32_t)config->chill_cycle |
sahilmgandhi 18:6a4db94011d3 378 ((uint32_t)config->on_demand << SYSCTRL_DFLLCTRL_ONDEMAND_Pos);
sahilmgandhi 18:6a4db94011d3 379
sahilmgandhi 18:6a4db94011d3 380 if (config->loop_mode == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) {
sahilmgandhi 18:6a4db94011d3 381
sahilmgandhi 18:6a4db94011d3 382 _system_clock_inst.dfll.mul =
sahilmgandhi 18:6a4db94011d3 383 SYSCTRL_DFLLMUL_CSTEP(config->coarse_max_step) |
sahilmgandhi 18:6a4db94011d3 384 SYSCTRL_DFLLMUL_FSTEP(config->fine_max_step) |
sahilmgandhi 18:6a4db94011d3 385 SYSCTRL_DFLLMUL_MUL(config->multiply_factor);
sahilmgandhi 18:6a4db94011d3 386
sahilmgandhi 18:6a4db94011d3 387 /* Enable the closed loop mode */
sahilmgandhi 18:6a4db94011d3 388 _system_clock_inst.dfll.control |= config->loop_mode;
sahilmgandhi 18:6a4db94011d3 389 }
sahilmgandhi 18:6a4db94011d3 390 if (config->loop_mode == SYSTEM_CLOCK_DFLL_LOOP_MODE_USB_RECOVERY) {
sahilmgandhi 18:6a4db94011d3 391
sahilmgandhi 18:6a4db94011d3 392 _system_clock_inst.dfll.mul =
sahilmgandhi 18:6a4db94011d3 393 SYSCTRL_DFLLMUL_MUL(config->multiply_factor);
sahilmgandhi 18:6a4db94011d3 394
sahilmgandhi 18:6a4db94011d3 395 /* Enable the USB recovery mode */
sahilmgandhi 18:6a4db94011d3 396 _system_clock_inst.dfll.control |= config->loop_mode |
sahilmgandhi 18:6a4db94011d3 397 SYSCTRL_DFLLCTRL_BPLCKC;
sahilmgandhi 18:6a4db94011d3 398 }
sahilmgandhi 18:6a4db94011d3 399 }
sahilmgandhi 18:6a4db94011d3 400
sahilmgandhi 18:6a4db94011d3 401 #ifdef FEATURE_SYSTEM_CLOCK_DPLL
sahilmgandhi 18:6a4db94011d3 402 /**
sahilmgandhi 18:6a4db94011d3 403 * \brief Configure the DPLL clock source.
sahilmgandhi 18:6a4db94011d3 404 *
sahilmgandhi 18:6a4db94011d3 405 * Configures the Digital Phase-Locked Loop clock source with the given
sahilmgandhi 18:6a4db94011d3 406 * configuration settings.
sahilmgandhi 18:6a4db94011d3 407 *
sahilmgandhi 18:6a4db94011d3 408 * \note The DPLL will be running when this function returns, as the DPLL module
sahilmgandhi 18:6a4db94011d3 409 * needs to be enabled in order to perform the module configuration.
sahilmgandhi 18:6a4db94011d3 410 *
sahilmgandhi 18:6a4db94011d3 411 * \param[in] config DPLL configuration structure containing the new config
sahilmgandhi 18:6a4db94011d3 412 */
sahilmgandhi 18:6a4db94011d3 413 void system_clock_source_dpll_set_config(
sahilmgandhi 18:6a4db94011d3 414 struct system_clock_source_dpll_config *const config)
sahilmgandhi 18:6a4db94011d3 415 {
sahilmgandhi 18:6a4db94011d3 416
sahilmgandhi 18:6a4db94011d3 417 uint32_t tmpldr;
sahilmgandhi 18:6a4db94011d3 418 uint8_t tmpldrfrac;
sahilmgandhi 18:6a4db94011d3 419 uint32_t refclk;
sahilmgandhi 18:6a4db94011d3 420
sahilmgandhi 18:6a4db94011d3 421 refclk = config->reference_frequency;
sahilmgandhi 18:6a4db94011d3 422
sahilmgandhi 18:6a4db94011d3 423 /* Only reference clock REF1 can be divided */
sahilmgandhi 18:6a4db94011d3 424 if (config->reference_clock == SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_XOSC) {
sahilmgandhi 18:6a4db94011d3 425 refclk = refclk / (2 * (config->reference_divider + 1));
sahilmgandhi 18:6a4db94011d3 426 }
sahilmgandhi 18:6a4db94011d3 427
sahilmgandhi 18:6a4db94011d3 428 /* Calculate LDRFRAC and LDR */
sahilmgandhi 18:6a4db94011d3 429 tmpldr = (config->output_frequency << 4) / refclk;
sahilmgandhi 18:6a4db94011d3 430 tmpldrfrac = tmpldr & 0x0f;
sahilmgandhi 18:6a4db94011d3 431 tmpldr = (tmpldr >> 4) - 1;
sahilmgandhi 18:6a4db94011d3 432
sahilmgandhi 18:6a4db94011d3 433 SYSCTRL->DPLLCTRLA.reg =
sahilmgandhi 18:6a4db94011d3 434 ((uint32_t)config->on_demand << SYSCTRL_DPLLCTRLA_ONDEMAND_Pos) |
sahilmgandhi 18:6a4db94011d3 435 ((uint32_t)config->run_in_standby << SYSCTRL_DPLLCTRLA_RUNSTDBY_Pos);
sahilmgandhi 18:6a4db94011d3 436
sahilmgandhi 18:6a4db94011d3 437 SYSCTRL->DPLLRATIO.reg =
sahilmgandhi 18:6a4db94011d3 438 SYSCTRL_DPLLRATIO_LDRFRAC(tmpldrfrac) |
sahilmgandhi 18:6a4db94011d3 439 SYSCTRL_DPLLRATIO_LDR(tmpldr);
sahilmgandhi 18:6a4db94011d3 440
sahilmgandhi 18:6a4db94011d3 441 SYSCTRL->DPLLCTRLB.reg =
sahilmgandhi 18:6a4db94011d3 442 SYSCTRL_DPLLCTRLB_DIV(config->reference_divider) |
sahilmgandhi 18:6a4db94011d3 443 ((uint32_t)config->lock_bypass << SYSCTRL_DPLLCTRLB_LBYPASS_Pos) |
sahilmgandhi 18:6a4db94011d3 444 SYSCTRL_DPLLCTRLB_LTIME(config->lock_time) |
sahilmgandhi 18:6a4db94011d3 445 SYSCTRL_DPLLCTRLB_REFCLK(config->reference_clock) |
sahilmgandhi 18:6a4db94011d3 446 ((uint32_t)config->wake_up_fast << SYSCTRL_DPLLCTRLB_WUF_Pos) |
sahilmgandhi 18:6a4db94011d3 447 ((uint32_t)config->low_power_enable << SYSCTRL_DPLLCTRLB_LPEN_Pos) |
sahilmgandhi 18:6a4db94011d3 448 SYSCTRL_DPLLCTRLB_FILTER(config->filter);
sahilmgandhi 18:6a4db94011d3 449
sahilmgandhi 18:6a4db94011d3 450 /*
sahilmgandhi 18:6a4db94011d3 451 * Fck = Fckrx * (LDR + 1 + LDRFRAC / 16)
sahilmgandhi 18:6a4db94011d3 452 */
sahilmgandhi 18:6a4db94011d3 453 _system_clock_inst.dpll.frequency =
sahilmgandhi 18:6a4db94011d3 454 (refclk * (((tmpldr + 1) << 4) + tmpldrfrac)) >> 4;
sahilmgandhi 18:6a4db94011d3 455 }
sahilmgandhi 18:6a4db94011d3 456 #endif
sahilmgandhi 18:6a4db94011d3 457
sahilmgandhi 18:6a4db94011d3 458 /**
sahilmgandhi 18:6a4db94011d3 459 * \brief Writes the calibration values for a given oscillator clock source.
sahilmgandhi 18:6a4db94011d3 460 *
sahilmgandhi 18:6a4db94011d3 461 * Writes an oscillator calibration value to the given oscillator control
sahilmgandhi 18:6a4db94011d3 462 * registers. The acceptable ranges are:
sahilmgandhi 18:6a4db94011d3 463 *
sahilmgandhi 18:6a4db94011d3 464 * For OSC32K:
sahilmgandhi 18:6a4db94011d3 465 * - 7 bits (max value 128)
sahilmgandhi 18:6a4db94011d3 466 * For OSC8MHZ:
sahilmgandhi 18:6a4db94011d3 467 * - 8 bits (Max value 255)
sahilmgandhi 18:6a4db94011d3 468 * For OSCULP:
sahilmgandhi 18:6a4db94011d3 469 * - 5 bits (Max value 32)
sahilmgandhi 18:6a4db94011d3 470 *
sahilmgandhi 18:6a4db94011d3 471 * \note The frequency range parameter applies only when configuring the 8MHz
sahilmgandhi 18:6a4db94011d3 472 * oscillator and will be ignored for the other oscillators.
sahilmgandhi 18:6a4db94011d3 473 *
sahilmgandhi 18:6a4db94011d3 474 * \param[in] clock_source Clock source to calibrate
sahilmgandhi 18:6a4db94011d3 475 * \param[in] calibration_value Calibration value to write
sahilmgandhi 18:6a4db94011d3 476 * \param[in] freq_range Frequency range (8MHz oscillator only)
sahilmgandhi 18:6a4db94011d3 477 *
sahilmgandhi 18:6a4db94011d3 478 * \retval STATUS_OK The calibration value was written
sahilmgandhi 18:6a4db94011d3 479 * successfully.
sahilmgandhi 18:6a4db94011d3 480 * \retval STATUS_ERR_INVALID_ARG The setting is not valid for selected clock
sahilmgandhi 18:6a4db94011d3 481 * source.
sahilmgandhi 18:6a4db94011d3 482 */
sahilmgandhi 18:6a4db94011d3 483 enum status_code system_clock_source_write_calibration(
sahilmgandhi 18:6a4db94011d3 484 const enum system_clock_source clock_source,
sahilmgandhi 18:6a4db94011d3 485 const uint16_t calibration_value,
sahilmgandhi 18:6a4db94011d3 486 const uint8_t freq_range)
sahilmgandhi 18:6a4db94011d3 487 {
sahilmgandhi 18:6a4db94011d3 488 switch (clock_source) {
sahilmgandhi 18:6a4db94011d3 489 case SYSTEM_CLOCK_SOURCE_OSC8M:
sahilmgandhi 18:6a4db94011d3 490
sahilmgandhi 18:6a4db94011d3 491 if (calibration_value > 0xfff || freq_range > 4) {
sahilmgandhi 18:6a4db94011d3 492 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 493 }
sahilmgandhi 18:6a4db94011d3 494
sahilmgandhi 18:6a4db94011d3 495 SYSCTRL->OSC8M.bit.CALIB = calibration_value;
sahilmgandhi 18:6a4db94011d3 496 SYSCTRL->OSC8M.bit.FRANGE = freq_range;
sahilmgandhi 18:6a4db94011d3 497 break;
sahilmgandhi 18:6a4db94011d3 498
sahilmgandhi 18:6a4db94011d3 499 case SYSTEM_CLOCK_SOURCE_OSC32K:
sahilmgandhi 18:6a4db94011d3 500
sahilmgandhi 18:6a4db94011d3 501 if (calibration_value > 128) {
sahilmgandhi 18:6a4db94011d3 502 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 503 }
sahilmgandhi 18:6a4db94011d3 504
sahilmgandhi 18:6a4db94011d3 505 _system_osc32k_wait_for_sync();
sahilmgandhi 18:6a4db94011d3 506 SYSCTRL->OSC32K.bit.CALIB = calibration_value;
sahilmgandhi 18:6a4db94011d3 507 break;
sahilmgandhi 18:6a4db94011d3 508
sahilmgandhi 18:6a4db94011d3 509 case SYSTEM_CLOCK_SOURCE_ULP32K:
sahilmgandhi 18:6a4db94011d3 510
sahilmgandhi 18:6a4db94011d3 511 if (calibration_value > 32) {
sahilmgandhi 18:6a4db94011d3 512 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 513 }
sahilmgandhi 18:6a4db94011d3 514
sahilmgandhi 18:6a4db94011d3 515 SYSCTRL->OSCULP32K.bit.CALIB = calibration_value;
sahilmgandhi 18:6a4db94011d3 516 break;
sahilmgandhi 18:6a4db94011d3 517
sahilmgandhi 18:6a4db94011d3 518 default:
sahilmgandhi 18:6a4db94011d3 519 Assert(false);
sahilmgandhi 18:6a4db94011d3 520 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 521
sahilmgandhi 18:6a4db94011d3 522 }
sahilmgandhi 18:6a4db94011d3 523
sahilmgandhi 18:6a4db94011d3 524 return STATUS_OK;
sahilmgandhi 18:6a4db94011d3 525 }
sahilmgandhi 18:6a4db94011d3 526
sahilmgandhi 18:6a4db94011d3 527 /**
sahilmgandhi 18:6a4db94011d3 528 * \brief Enables a clock source.
sahilmgandhi 18:6a4db94011d3 529 *
sahilmgandhi 18:6a4db94011d3 530 * Enables a clock source which has been previously configured.
sahilmgandhi 18:6a4db94011d3 531 *
sahilmgandhi 18:6a4db94011d3 532 * \param[in] clock_source Clock source to enable
sahilmgandhi 18:6a4db94011d3 533 *
sahilmgandhi 18:6a4db94011d3 534 * \retval STATUS_OK Clock source was enabled successfully and
sahilmgandhi 18:6a4db94011d3 535 * is ready
sahilmgandhi 18:6a4db94011d3 536 * \retval STATUS_ERR_INVALID_ARG The clock source is not available on this
sahilmgandhi 18:6a4db94011d3 537 * device
sahilmgandhi 18:6a4db94011d3 538 */
sahilmgandhi 18:6a4db94011d3 539 enum status_code system_clock_source_enable(
sahilmgandhi 18:6a4db94011d3 540 const enum system_clock_source clock_source)
sahilmgandhi 18:6a4db94011d3 541 {
sahilmgandhi 18:6a4db94011d3 542 switch (clock_source) {
sahilmgandhi 18:6a4db94011d3 543 case SYSTEM_CLOCK_SOURCE_OSC8M:
sahilmgandhi 18:6a4db94011d3 544 SYSCTRL->OSC8M.reg |= SYSCTRL_OSC8M_ENABLE;
sahilmgandhi 18:6a4db94011d3 545 return STATUS_OK;
sahilmgandhi 18:6a4db94011d3 546
sahilmgandhi 18:6a4db94011d3 547 case SYSTEM_CLOCK_SOURCE_OSC32K:
sahilmgandhi 18:6a4db94011d3 548 SYSCTRL->OSC32K.reg |= SYSCTRL_OSC32K_ENABLE;
sahilmgandhi 18:6a4db94011d3 549 break;
sahilmgandhi 18:6a4db94011d3 550
sahilmgandhi 18:6a4db94011d3 551 case SYSTEM_CLOCK_SOURCE_XOSC:
sahilmgandhi 18:6a4db94011d3 552 SYSCTRL->XOSC.reg |= SYSCTRL_XOSC_ENABLE;
sahilmgandhi 18:6a4db94011d3 553 break;
sahilmgandhi 18:6a4db94011d3 554
sahilmgandhi 18:6a4db94011d3 555 case SYSTEM_CLOCK_SOURCE_XOSC32K:
sahilmgandhi 18:6a4db94011d3 556 SYSCTRL->XOSC32K.reg |= SYSCTRL_XOSC32K_ENABLE;
sahilmgandhi 18:6a4db94011d3 557 break;
sahilmgandhi 18:6a4db94011d3 558
sahilmgandhi 18:6a4db94011d3 559 case SYSTEM_CLOCK_SOURCE_DFLL:
sahilmgandhi 18:6a4db94011d3 560 _system_clock_inst.dfll.control |= SYSCTRL_DFLLCTRL_ENABLE;
sahilmgandhi 18:6a4db94011d3 561 _system_clock_source_dfll_set_config_errata_9905();
sahilmgandhi 18:6a4db94011d3 562 break;
sahilmgandhi 18:6a4db94011d3 563
sahilmgandhi 18:6a4db94011d3 564 #ifdef FEATURE_SYSTEM_CLOCK_DPLL
sahilmgandhi 18:6a4db94011d3 565 case SYSTEM_CLOCK_SOURCE_DPLL:
sahilmgandhi 18:6a4db94011d3 566 SYSCTRL->DPLLCTRLA.reg |= SYSCTRL_DPLLCTRLA_ENABLE;
sahilmgandhi 18:6a4db94011d3 567 break;
sahilmgandhi 18:6a4db94011d3 568 #endif
sahilmgandhi 18:6a4db94011d3 569
sahilmgandhi 18:6a4db94011d3 570 case SYSTEM_CLOCK_SOURCE_ULP32K:
sahilmgandhi 18:6a4db94011d3 571 /* Always enabled */
sahilmgandhi 18:6a4db94011d3 572 return STATUS_OK;
sahilmgandhi 18:6a4db94011d3 573
sahilmgandhi 18:6a4db94011d3 574 default:
sahilmgandhi 18:6a4db94011d3 575 Assert(false);
sahilmgandhi 18:6a4db94011d3 576 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 577 }
sahilmgandhi 18:6a4db94011d3 578
sahilmgandhi 18:6a4db94011d3 579 return STATUS_OK;
sahilmgandhi 18:6a4db94011d3 580 }
sahilmgandhi 18:6a4db94011d3 581
sahilmgandhi 18:6a4db94011d3 582 /**
sahilmgandhi 18:6a4db94011d3 583 * \brief Disables a clock source.
sahilmgandhi 18:6a4db94011d3 584 *
sahilmgandhi 18:6a4db94011d3 585 * Disables a clock source that was previously enabled.
sahilmgandhi 18:6a4db94011d3 586 *
sahilmgandhi 18:6a4db94011d3 587 * \param[in] clock_source Clock source to disable
sahilmgandhi 18:6a4db94011d3 588 *
sahilmgandhi 18:6a4db94011d3 589 * \retval STATUS_OK Clock source was disabled successfully
sahilmgandhi 18:6a4db94011d3 590 * \retval STATUS_ERR_INVALID_ARG An invalid or unavailable clock source was
sahilmgandhi 18:6a4db94011d3 591 * given
sahilmgandhi 18:6a4db94011d3 592 */
sahilmgandhi 18:6a4db94011d3 593 enum status_code system_clock_source_disable(
sahilmgandhi 18:6a4db94011d3 594 const enum system_clock_source clock_source)
sahilmgandhi 18:6a4db94011d3 595 {
sahilmgandhi 18:6a4db94011d3 596 switch (clock_source) {
sahilmgandhi 18:6a4db94011d3 597 case SYSTEM_CLOCK_SOURCE_OSC8M:
sahilmgandhi 18:6a4db94011d3 598 SYSCTRL->OSC8M.reg &= ~SYSCTRL_OSC8M_ENABLE;
sahilmgandhi 18:6a4db94011d3 599 break;
sahilmgandhi 18:6a4db94011d3 600
sahilmgandhi 18:6a4db94011d3 601 case SYSTEM_CLOCK_SOURCE_OSC32K:
sahilmgandhi 18:6a4db94011d3 602 SYSCTRL->OSC32K.reg &= ~SYSCTRL_OSC32K_ENABLE;
sahilmgandhi 18:6a4db94011d3 603 break;
sahilmgandhi 18:6a4db94011d3 604
sahilmgandhi 18:6a4db94011d3 605 case SYSTEM_CLOCK_SOURCE_XOSC:
sahilmgandhi 18:6a4db94011d3 606 SYSCTRL->XOSC.reg &= ~SYSCTRL_XOSC_ENABLE;
sahilmgandhi 18:6a4db94011d3 607 break;
sahilmgandhi 18:6a4db94011d3 608
sahilmgandhi 18:6a4db94011d3 609 case SYSTEM_CLOCK_SOURCE_XOSC32K:
sahilmgandhi 18:6a4db94011d3 610 SYSCTRL->XOSC32K.reg &= ~SYSCTRL_XOSC32K_ENABLE;
sahilmgandhi 18:6a4db94011d3 611 break;
sahilmgandhi 18:6a4db94011d3 612
sahilmgandhi 18:6a4db94011d3 613 case SYSTEM_CLOCK_SOURCE_DFLL:
sahilmgandhi 18:6a4db94011d3 614 _system_clock_inst.dfll.control &= ~SYSCTRL_DFLLCTRL_ENABLE;
sahilmgandhi 18:6a4db94011d3 615 SYSCTRL->DFLLCTRL.reg = _system_clock_inst.dfll.control;
sahilmgandhi 18:6a4db94011d3 616 break;
sahilmgandhi 18:6a4db94011d3 617
sahilmgandhi 18:6a4db94011d3 618 #ifdef FEATURE_SYSTEM_CLOCK_DPLL
sahilmgandhi 18:6a4db94011d3 619 case SYSTEM_CLOCK_SOURCE_DPLL:
sahilmgandhi 18:6a4db94011d3 620 SYSCTRL->DPLLCTRLA.reg &= ~SYSCTRL_DPLLCTRLA_ENABLE;
sahilmgandhi 18:6a4db94011d3 621 break;
sahilmgandhi 18:6a4db94011d3 622 #endif
sahilmgandhi 18:6a4db94011d3 623
sahilmgandhi 18:6a4db94011d3 624 case SYSTEM_CLOCK_SOURCE_ULP32K:
sahilmgandhi 18:6a4db94011d3 625 /* Not possible to disable */
sahilmgandhi 18:6a4db94011d3 626
sahilmgandhi 18:6a4db94011d3 627 default:
sahilmgandhi 18:6a4db94011d3 628 Assert(false);
sahilmgandhi 18:6a4db94011d3 629 return STATUS_ERR_INVALID_ARG;
sahilmgandhi 18:6a4db94011d3 630
sahilmgandhi 18:6a4db94011d3 631 }
sahilmgandhi 18:6a4db94011d3 632
sahilmgandhi 18:6a4db94011d3 633 return STATUS_OK;
sahilmgandhi 18:6a4db94011d3 634 }
sahilmgandhi 18:6a4db94011d3 635
sahilmgandhi 18:6a4db94011d3 636 /**
sahilmgandhi 18:6a4db94011d3 637 * \brief Checks if a clock source is ready.
sahilmgandhi 18:6a4db94011d3 638 *
sahilmgandhi 18:6a4db94011d3 639 * Checks if a given clock source is ready to be used.
sahilmgandhi 18:6a4db94011d3 640 *
sahilmgandhi 18:6a4db94011d3 641 * \param[in] clock_source Clock source to check if ready
sahilmgandhi 18:6a4db94011d3 642 *
sahilmgandhi 18:6a4db94011d3 643 * \returns Ready state of the given clock source.
sahilmgandhi 18:6a4db94011d3 644 *
sahilmgandhi 18:6a4db94011d3 645 * \retval true Clock source is enabled and ready
sahilmgandhi 18:6a4db94011d3 646 * \retval false Clock source is disabled or not yet ready
sahilmgandhi 18:6a4db94011d3 647 */
sahilmgandhi 18:6a4db94011d3 648 bool system_clock_source_is_ready(
sahilmgandhi 18:6a4db94011d3 649 const enum system_clock_source clock_source)
sahilmgandhi 18:6a4db94011d3 650 {
sahilmgandhi 18:6a4db94011d3 651 uint32_t mask = 0;
sahilmgandhi 18:6a4db94011d3 652
sahilmgandhi 18:6a4db94011d3 653 switch (clock_source) {
sahilmgandhi 18:6a4db94011d3 654 case SYSTEM_CLOCK_SOURCE_OSC8M:
sahilmgandhi 18:6a4db94011d3 655 mask = SYSCTRL_PCLKSR_OSC8MRDY;
sahilmgandhi 18:6a4db94011d3 656 break;
sahilmgandhi 18:6a4db94011d3 657
sahilmgandhi 18:6a4db94011d3 658 case SYSTEM_CLOCK_SOURCE_OSC32K:
sahilmgandhi 18:6a4db94011d3 659 mask = SYSCTRL_PCLKSR_OSC32KRDY;
sahilmgandhi 18:6a4db94011d3 660 break;
sahilmgandhi 18:6a4db94011d3 661
sahilmgandhi 18:6a4db94011d3 662 case SYSTEM_CLOCK_SOURCE_XOSC:
sahilmgandhi 18:6a4db94011d3 663 mask = SYSCTRL_PCLKSR_XOSCRDY;
sahilmgandhi 18:6a4db94011d3 664 break;
sahilmgandhi 18:6a4db94011d3 665
sahilmgandhi 18:6a4db94011d3 666 case SYSTEM_CLOCK_SOURCE_XOSC32K:
sahilmgandhi 18:6a4db94011d3 667 mask = SYSCTRL_PCLKSR_XOSC32KRDY;
sahilmgandhi 18:6a4db94011d3 668 break;
sahilmgandhi 18:6a4db94011d3 669
sahilmgandhi 18:6a4db94011d3 670 case SYSTEM_CLOCK_SOURCE_DFLL:
sahilmgandhi 18:6a4db94011d3 671 if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) {
sahilmgandhi 18:6a4db94011d3 672 mask = (SYSCTRL_PCLKSR_DFLLRDY |
sahilmgandhi 18:6a4db94011d3 673 SYSCTRL_PCLKSR_DFLLLCKF | SYSCTRL_PCLKSR_DFLLLCKC);
sahilmgandhi 18:6a4db94011d3 674 } else {
sahilmgandhi 18:6a4db94011d3 675 mask = SYSCTRL_PCLKSR_DFLLRDY;
sahilmgandhi 18:6a4db94011d3 676 }
sahilmgandhi 18:6a4db94011d3 677 break;
sahilmgandhi 18:6a4db94011d3 678
sahilmgandhi 18:6a4db94011d3 679 #ifdef FEATURE_SYSTEM_CLOCK_DPLL
sahilmgandhi 18:6a4db94011d3 680 case SYSTEM_CLOCK_SOURCE_DPLL:
sahilmgandhi 18:6a4db94011d3 681 return ((SYSCTRL->DPLLSTATUS.reg &
sahilmgandhi 18:6a4db94011d3 682 (SYSCTRL_DPLLSTATUS_CLKRDY | SYSCTRL_DPLLSTATUS_LOCK)) ==
sahilmgandhi 18:6a4db94011d3 683 (SYSCTRL_DPLLSTATUS_CLKRDY | SYSCTRL_DPLLSTATUS_LOCK));
sahilmgandhi 18:6a4db94011d3 684 #endif
sahilmgandhi 18:6a4db94011d3 685
sahilmgandhi 18:6a4db94011d3 686 case SYSTEM_CLOCK_SOURCE_ULP32K:
sahilmgandhi 18:6a4db94011d3 687 /* Not possible to disable */
sahilmgandhi 18:6a4db94011d3 688 return true;
sahilmgandhi 18:6a4db94011d3 689
sahilmgandhi 18:6a4db94011d3 690 default:
sahilmgandhi 18:6a4db94011d3 691 return false;
sahilmgandhi 18:6a4db94011d3 692 }
sahilmgandhi 18:6a4db94011d3 693
sahilmgandhi 18:6a4db94011d3 694 return ((SYSCTRL->PCLKSR.reg & mask) == mask);
sahilmgandhi 18:6a4db94011d3 695 }
sahilmgandhi 18:6a4db94011d3 696
sahilmgandhi 18:6a4db94011d3 697 /* Include some checks for conf_clocks.h validation */
sahilmgandhi 18:6a4db94011d3 698 #include "clock_config_check.h"
sahilmgandhi 18:6a4db94011d3 699
sahilmgandhi 18:6a4db94011d3 700 #if !defined(__DOXYGEN__)
sahilmgandhi 18:6a4db94011d3 701 /** \internal
sahilmgandhi 18:6a4db94011d3 702 *
sahilmgandhi 18:6a4db94011d3 703 * Configures a Generic Clock Generator with the configuration from \c conf_clocks.h.
sahilmgandhi 18:6a4db94011d3 704 */
sahilmgandhi 18:6a4db94011d3 705 # define _CONF_CLOCK_GCLK_CONFIG(n, unused) \
sahilmgandhi 18:6a4db94011d3 706 if (CONF_CLOCK_GCLK_##n##_ENABLE == true) { \
sahilmgandhi 18:6a4db94011d3 707 struct system_gclk_gen_config gclk_conf; \
sahilmgandhi 18:6a4db94011d3 708 system_gclk_gen_get_config_defaults(&gclk_conf); \
sahilmgandhi 18:6a4db94011d3 709 gclk_conf.source_clock = CONF_CLOCK_GCLK_##n##_CLOCK_SOURCE; \
sahilmgandhi 18:6a4db94011d3 710 gclk_conf.division_factor = CONF_CLOCK_GCLK_##n##_PRESCALER; \
sahilmgandhi 18:6a4db94011d3 711 gclk_conf.run_in_standby = CONF_CLOCK_GCLK_##n##_RUN_IN_STANDBY; \
sahilmgandhi 18:6a4db94011d3 712 gclk_conf.output_enable = CONF_CLOCK_GCLK_##n##_OUTPUT_ENABLE; \
sahilmgandhi 18:6a4db94011d3 713 system_gclk_gen_set_config(GCLK_GENERATOR_##n, &gclk_conf); \
sahilmgandhi 18:6a4db94011d3 714 system_gclk_gen_enable(GCLK_GENERATOR_##n); \
sahilmgandhi 18:6a4db94011d3 715 }
sahilmgandhi 18:6a4db94011d3 716
sahilmgandhi 18:6a4db94011d3 717 /** \internal
sahilmgandhi 18:6a4db94011d3 718 *
sahilmgandhi 18:6a4db94011d3 719 * Configures a Generic Clock Generator with the configuration from \c conf_clocks.h,
sahilmgandhi 18:6a4db94011d3 720 * provided that it is not the main Generic Clock Generator channel.
sahilmgandhi 18:6a4db94011d3 721 */
sahilmgandhi 18:6a4db94011d3 722 # define _CONF_CLOCK_GCLK_CONFIG_NONMAIN(n, unused) \
sahilmgandhi 18:6a4db94011d3 723 if (n > 0) { _CONF_CLOCK_GCLK_CONFIG(n, unused); }
sahilmgandhi 18:6a4db94011d3 724 #endif
sahilmgandhi 18:6a4db94011d3 725
sahilmgandhi 18:6a4db94011d3 726 /** \internal
sahilmgandhi 18:6a4db94011d3 727 *
sahilmgandhi 18:6a4db94011d3 728 * Switch all peripheral clock to a not enabled general clock
sahilmgandhi 18:6a4db94011d3 729 * to save power.
sahilmgandhi 18:6a4db94011d3 730 */
sahilmgandhi 18:6a4db94011d3 731 static void _switch_peripheral_gclk(void)
sahilmgandhi 18:6a4db94011d3 732 {
sahilmgandhi 18:6a4db94011d3 733 uint32_t gclk_id;
sahilmgandhi 18:6a4db94011d3 734 struct system_gclk_chan_config gclk_conf;
sahilmgandhi 18:6a4db94011d3 735
sahilmgandhi 18:6a4db94011d3 736 #if CONF_CLOCK_GCLK_1_ENABLE == false
sahilmgandhi 18:6a4db94011d3 737 gclk_conf.source_generator = GCLK_GENERATOR_1;
sahilmgandhi 18:6a4db94011d3 738 #elif CONF_CLOCK_GCLK_2_ENABLE == false
sahilmgandhi 18:6a4db94011d3 739 gclk_conf.source_generator = GCLK_GENERATOR_2;
sahilmgandhi 18:6a4db94011d3 740 #elif CONF_CLOCK_GCLK_3_ENABLE == false
sahilmgandhi 18:6a4db94011d3 741 gclk_conf.source_generator = GCLK_GENERATOR_3;
sahilmgandhi 18:6a4db94011d3 742 #elif CONF_CLOCK_GCLK_4_ENABLE == false
sahilmgandhi 18:6a4db94011d3 743 gclk_conf.source_generator = GCLK_GENERATOR_4;
sahilmgandhi 18:6a4db94011d3 744 #elif CONF_CLOCK_GCLK_5_ENABLE == false
sahilmgandhi 18:6a4db94011d3 745 gclk_conf.source_generator = GCLK_GENERATOR_5;
sahilmgandhi 18:6a4db94011d3 746 #elif CONF_CLOCK_GCLK_6_ENABLE == false
sahilmgandhi 18:6a4db94011d3 747 gclk_conf.source_generator = GCLK_GENERATOR_6;
sahilmgandhi 18:6a4db94011d3 748 #elif CONF_CLOCK_GCLK_7_ENABLE == false
sahilmgandhi 18:6a4db94011d3 749 gclk_conf.source_generator = GCLK_GENERATOR_7;
sahilmgandhi 18:6a4db94011d3 750 #else
sahilmgandhi 18:6a4db94011d3 751 gclk_conf.source_generator = GCLK_GENERATOR_7;
sahilmgandhi 18:6a4db94011d3 752 #endif
sahilmgandhi 18:6a4db94011d3 753
sahilmgandhi 18:6a4db94011d3 754 for (gclk_id = 0; gclk_id < GCLK_NUM; gclk_id++) {
sahilmgandhi 18:6a4db94011d3 755 system_gclk_chan_set_config(gclk_id, &gclk_conf);
sahilmgandhi 18:6a4db94011d3 756 }
sahilmgandhi 18:6a4db94011d3 757 }
sahilmgandhi 18:6a4db94011d3 758
sahilmgandhi 18:6a4db94011d3 759 /**
sahilmgandhi 18:6a4db94011d3 760 * \brief Initialize clock system based on the configuration in conf_clocks.h.
sahilmgandhi 18:6a4db94011d3 761 *
sahilmgandhi 18:6a4db94011d3 762 * This function will apply the settings in conf_clocks.h when run from the user
sahilmgandhi 18:6a4db94011d3 763 * application. All clock sources and GCLK generators are running when this function
sahilmgandhi 18:6a4db94011d3 764 * returns.
sahilmgandhi 18:6a4db94011d3 765 *
sahilmgandhi 18:6a4db94011d3 766 * \note OSC8M is always enabled and if user selects other clocks for GCLK generators,
sahilmgandhi 18:6a4db94011d3 767 * the OSC8M default enable can be disabled after system_clock_init. Make sure the
sahilmgandhi 18:6a4db94011d3 768 * clock switch successfully before disabling OSC8M.
sahilmgandhi 18:6a4db94011d3 769 */
sahilmgandhi 18:6a4db94011d3 770 void system_clock_init(void)
sahilmgandhi 18:6a4db94011d3 771 {
sahilmgandhi 18:6a4db94011d3 772 /* Various bits in the INTFLAG register can be set to one at startup.
sahilmgandhi 18:6a4db94011d3 773 This will ensure that these bits are cleared */
sahilmgandhi 18:6a4db94011d3 774 SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD33RDY | SYSCTRL_INTFLAG_BOD33DET |
sahilmgandhi 18:6a4db94011d3 775 SYSCTRL_INTFLAG_DFLLRDY;
sahilmgandhi 18:6a4db94011d3 776
sahilmgandhi 18:6a4db94011d3 777 system_flash_set_waitstates(CONF_CLOCK_FLASH_WAIT_STATES);
sahilmgandhi 18:6a4db94011d3 778
sahilmgandhi 18:6a4db94011d3 779 /* Switch all peripheral clock to a not enabled general clock to save power. */
sahilmgandhi 18:6a4db94011d3 780 _switch_peripheral_gclk();
sahilmgandhi 18:6a4db94011d3 781
sahilmgandhi 18:6a4db94011d3 782 /* XOSC */
sahilmgandhi 18:6a4db94011d3 783 #if CONF_CLOCK_XOSC_ENABLE == true
sahilmgandhi 18:6a4db94011d3 784 struct system_clock_source_xosc_config xosc_conf;
sahilmgandhi 18:6a4db94011d3 785 system_clock_source_xosc_get_config_defaults(&xosc_conf);
sahilmgandhi 18:6a4db94011d3 786
sahilmgandhi 18:6a4db94011d3 787 xosc_conf.external_clock = CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL;
sahilmgandhi 18:6a4db94011d3 788 xosc_conf.startup_time = CONF_CLOCK_XOSC_STARTUP_TIME;
sahilmgandhi 18:6a4db94011d3 789 xosc_conf.auto_gain_control = CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL;
sahilmgandhi 18:6a4db94011d3 790 xosc_conf.frequency = CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY;
sahilmgandhi 18:6a4db94011d3 791 xosc_conf.on_demand = CONF_CLOCK_XOSC_ON_DEMAND;
sahilmgandhi 18:6a4db94011d3 792 xosc_conf.run_in_standby = CONF_CLOCK_XOSC_RUN_IN_STANDBY;
sahilmgandhi 18:6a4db94011d3 793
sahilmgandhi 18:6a4db94011d3 794 system_clock_source_xosc_set_config(&xosc_conf);
sahilmgandhi 18:6a4db94011d3 795 system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC);
sahilmgandhi 18:6a4db94011d3 796 #endif
sahilmgandhi 18:6a4db94011d3 797
sahilmgandhi 18:6a4db94011d3 798
sahilmgandhi 18:6a4db94011d3 799 /* XOSC32K */
sahilmgandhi 18:6a4db94011d3 800 #if CONF_CLOCK_XOSC32K_ENABLE == true
sahilmgandhi 18:6a4db94011d3 801 struct system_clock_source_xosc32k_config xosc32k_conf;
sahilmgandhi 18:6a4db94011d3 802 system_clock_source_xosc32k_get_config_defaults(&xosc32k_conf);
sahilmgandhi 18:6a4db94011d3 803
sahilmgandhi 18:6a4db94011d3 804 xosc32k_conf.frequency = 32768UL;
sahilmgandhi 18:6a4db94011d3 805 xosc32k_conf.external_clock = CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL;
sahilmgandhi 18:6a4db94011d3 806 xosc32k_conf.startup_time = CONF_CLOCK_XOSC32K_STARTUP_TIME;
sahilmgandhi 18:6a4db94011d3 807 xosc32k_conf.auto_gain_control = CONF_CLOCK_XOSC32K_AUTO_AMPLITUDE_CONTROL;
sahilmgandhi 18:6a4db94011d3 808 xosc32k_conf.enable_1khz_output = CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT;
sahilmgandhi 18:6a4db94011d3 809 xosc32k_conf.enable_32khz_output = CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT;
sahilmgandhi 18:6a4db94011d3 810 xosc32k_conf.on_demand = false;
sahilmgandhi 18:6a4db94011d3 811 xosc32k_conf.run_in_standby = CONF_CLOCK_XOSC32K_RUN_IN_STANDBY;
sahilmgandhi 18:6a4db94011d3 812
sahilmgandhi 18:6a4db94011d3 813 system_clock_source_xosc32k_set_config(&xosc32k_conf);
sahilmgandhi 18:6a4db94011d3 814 system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC32K);
sahilmgandhi 18:6a4db94011d3 815 while(!system_clock_source_is_ready(SYSTEM_CLOCK_SOURCE_XOSC32K));
sahilmgandhi 18:6a4db94011d3 816 if (CONF_CLOCK_XOSC32K_ON_DEMAND) {
sahilmgandhi 18:6a4db94011d3 817 SYSCTRL->XOSC32K.bit.ONDEMAND = 1;
sahilmgandhi 18:6a4db94011d3 818 }
sahilmgandhi 18:6a4db94011d3 819 #endif
sahilmgandhi 18:6a4db94011d3 820
sahilmgandhi 18:6a4db94011d3 821
sahilmgandhi 18:6a4db94011d3 822 /* OSCK32K */
sahilmgandhi 18:6a4db94011d3 823 #if CONF_CLOCK_OSC32K_ENABLE == true
sahilmgandhi 18:6a4db94011d3 824 SYSCTRL->OSC32K.bit.CALIB =
sahilmgandhi 18:6a4db94011d3 825 ((*(uint32_t *)SYSCTRL_FUSES_OSC32K_ADDR >>
sahilmgandhi 18:6a4db94011d3 826 SYSCTRL_FUSES_OSC32K_Pos) & 0x7Ful);
sahilmgandhi 18:6a4db94011d3 827
sahilmgandhi 18:6a4db94011d3 828 struct system_clock_source_osc32k_config osc32k_conf;
sahilmgandhi 18:6a4db94011d3 829 system_clock_source_osc32k_get_config_defaults(&osc32k_conf);
sahilmgandhi 18:6a4db94011d3 830
sahilmgandhi 18:6a4db94011d3 831 osc32k_conf.startup_time = CONF_CLOCK_OSC32K_STARTUP_TIME;
sahilmgandhi 18:6a4db94011d3 832 osc32k_conf.enable_1khz_output = CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT;
sahilmgandhi 18:6a4db94011d3 833 osc32k_conf.enable_32khz_output = CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT;
sahilmgandhi 18:6a4db94011d3 834 osc32k_conf.on_demand = CONF_CLOCK_OSC32K_ON_DEMAND;
sahilmgandhi 18:6a4db94011d3 835 osc32k_conf.run_in_standby = CONF_CLOCK_OSC32K_RUN_IN_STANDBY;
sahilmgandhi 18:6a4db94011d3 836
sahilmgandhi 18:6a4db94011d3 837 system_clock_source_osc32k_set_config(&osc32k_conf);
sahilmgandhi 18:6a4db94011d3 838 system_clock_source_enable(SYSTEM_CLOCK_SOURCE_OSC32K);
sahilmgandhi 18:6a4db94011d3 839 #endif
sahilmgandhi 18:6a4db94011d3 840
sahilmgandhi 18:6a4db94011d3 841
sahilmgandhi 18:6a4db94011d3 842 /* DFLL Config (Open and Closed Loop) */
sahilmgandhi 18:6a4db94011d3 843 #if CONF_CLOCK_DFLL_ENABLE == true
sahilmgandhi 18:6a4db94011d3 844 struct system_clock_source_dfll_config dfll_conf;
sahilmgandhi 18:6a4db94011d3 845 system_clock_source_dfll_get_config_defaults(&dfll_conf);
sahilmgandhi 18:6a4db94011d3 846
sahilmgandhi 18:6a4db94011d3 847 dfll_conf.loop_mode = CONF_CLOCK_DFLL_LOOP_MODE;
sahilmgandhi 18:6a4db94011d3 848 dfll_conf.on_demand = false;
sahilmgandhi 18:6a4db94011d3 849
sahilmgandhi 18:6a4db94011d3 850 /* Using DFLL48M COARSE CAL value from NVM Software Calibration Area Mapping
sahilmgandhi 18:6a4db94011d3 851 in DFLL.COARSE helps to output a frequency close to 48 MHz.*/
sahilmgandhi 18:6a4db94011d3 852 #define NVM_DFLL_COARSE_POS 58 /* DFLL48M Coarse calibration value bit position.*/
sahilmgandhi 18:6a4db94011d3 853 #define NVM_DFLL_COARSE_SIZE 6 /* DFLL48M Coarse calibration value bit size.*/
sahilmgandhi 18:6a4db94011d3 854
sahilmgandhi 18:6a4db94011d3 855 uint32_t coarse =( *((uint32_t *)(NVMCTRL_OTP4)
sahilmgandhi 18:6a4db94011d3 856 + (NVM_DFLL_COARSE_POS / 32))
sahilmgandhi 18:6a4db94011d3 857 >> (NVM_DFLL_COARSE_POS % 32))
sahilmgandhi 18:6a4db94011d3 858 & ((1 << NVM_DFLL_COARSE_SIZE) - 1);
sahilmgandhi 18:6a4db94011d3 859 /* In some revision chip, the coarse calibration value is not correct. */
sahilmgandhi 18:6a4db94011d3 860 if (coarse == 0x3f) {
sahilmgandhi 18:6a4db94011d3 861 coarse = 0x1f;
sahilmgandhi 18:6a4db94011d3 862 }
sahilmgandhi 18:6a4db94011d3 863 dfll_conf.coarse_value = coarse;
sahilmgandhi 18:6a4db94011d3 864
sahilmgandhi 18:6a4db94011d3 865 if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_OPEN) {
sahilmgandhi 18:6a4db94011d3 866 dfll_conf.fine_value = CONF_CLOCK_DFLL_FINE_VALUE;
sahilmgandhi 18:6a4db94011d3 867 }
sahilmgandhi 18:6a4db94011d3 868
sahilmgandhi 18:6a4db94011d3 869 # if CONF_CLOCK_DFLL_QUICK_LOCK == true
sahilmgandhi 18:6a4db94011d3 870 dfll_conf.quick_lock = SYSTEM_CLOCK_DFLL_QUICK_LOCK_ENABLE;
sahilmgandhi 18:6a4db94011d3 871 # else
sahilmgandhi 18:6a4db94011d3 872 dfll_conf.quick_lock = SYSTEM_CLOCK_DFLL_QUICK_LOCK_DISABLE;
sahilmgandhi 18:6a4db94011d3 873 # endif
sahilmgandhi 18:6a4db94011d3 874
sahilmgandhi 18:6a4db94011d3 875 # if CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK == true
sahilmgandhi 18:6a4db94011d3 876 dfll_conf.stable_tracking = SYSTEM_CLOCK_DFLL_STABLE_TRACKING_TRACK_AFTER_LOCK;
sahilmgandhi 18:6a4db94011d3 877 # else
sahilmgandhi 18:6a4db94011d3 878 dfll_conf.stable_tracking = SYSTEM_CLOCK_DFLL_STABLE_TRACKING_FIX_AFTER_LOCK;
sahilmgandhi 18:6a4db94011d3 879 # endif
sahilmgandhi 18:6a4db94011d3 880
sahilmgandhi 18:6a4db94011d3 881 # if CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP == true
sahilmgandhi 18:6a4db94011d3 882 dfll_conf.wakeup_lock = SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_KEEP;
sahilmgandhi 18:6a4db94011d3 883 # else
sahilmgandhi 18:6a4db94011d3 884 dfll_conf.wakeup_lock = SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_LOSE;
sahilmgandhi 18:6a4db94011d3 885 # endif
sahilmgandhi 18:6a4db94011d3 886
sahilmgandhi 18:6a4db94011d3 887 # if CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE == true
sahilmgandhi 18:6a4db94011d3 888 dfll_conf.chill_cycle = SYSTEM_CLOCK_DFLL_CHILL_CYCLE_ENABLE;
sahilmgandhi 18:6a4db94011d3 889 # else
sahilmgandhi 18:6a4db94011d3 890 dfll_conf.chill_cycle = SYSTEM_CLOCK_DFLL_CHILL_CYCLE_DISABLE;
sahilmgandhi 18:6a4db94011d3 891 # endif
sahilmgandhi 18:6a4db94011d3 892
sahilmgandhi 18:6a4db94011d3 893 if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) {
sahilmgandhi 18:6a4db94011d3 894 dfll_conf.multiply_factor = CONF_CLOCK_DFLL_MULTIPLY_FACTOR;
sahilmgandhi 18:6a4db94011d3 895 }
sahilmgandhi 18:6a4db94011d3 896
sahilmgandhi 18:6a4db94011d3 897 dfll_conf.coarse_max_step = CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE;
sahilmgandhi 18:6a4db94011d3 898 dfll_conf.fine_max_step = CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE;
sahilmgandhi 18:6a4db94011d3 899
sahilmgandhi 18:6a4db94011d3 900 if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_USB_RECOVERY) {
sahilmgandhi 18:6a4db94011d3 901 dfll_conf.fine_value = 0x1ff;
sahilmgandhi 18:6a4db94011d3 902 dfll_conf.quick_lock = SYSTEM_CLOCK_DFLL_QUICK_LOCK_ENABLE;
sahilmgandhi 18:6a4db94011d3 903 dfll_conf.stable_tracking = SYSTEM_CLOCK_DFLL_STABLE_TRACKING_FIX_AFTER_LOCK;
sahilmgandhi 18:6a4db94011d3 904 dfll_conf.wakeup_lock = SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_KEEP;
sahilmgandhi 18:6a4db94011d3 905 dfll_conf.chill_cycle = SYSTEM_CLOCK_DFLL_CHILL_CYCLE_DISABLE;
sahilmgandhi 18:6a4db94011d3 906
sahilmgandhi 18:6a4db94011d3 907 dfll_conf.multiply_factor = 48000;
sahilmgandhi 18:6a4db94011d3 908 }
sahilmgandhi 18:6a4db94011d3 909
sahilmgandhi 18:6a4db94011d3 910 system_clock_source_dfll_set_config(&dfll_conf);
sahilmgandhi 18:6a4db94011d3 911 #endif
sahilmgandhi 18:6a4db94011d3 912
sahilmgandhi 18:6a4db94011d3 913
sahilmgandhi 18:6a4db94011d3 914 /* OSC8M */
sahilmgandhi 18:6a4db94011d3 915 struct system_clock_source_osc8m_config osc8m_conf;
sahilmgandhi 18:6a4db94011d3 916 system_clock_source_osc8m_get_config_defaults(&osc8m_conf);
sahilmgandhi 18:6a4db94011d3 917
sahilmgandhi 18:6a4db94011d3 918 osc8m_conf.prescaler = CONF_CLOCK_OSC8M_PRESCALER;
sahilmgandhi 18:6a4db94011d3 919 osc8m_conf.on_demand = CONF_CLOCK_OSC8M_ON_DEMAND;
sahilmgandhi 18:6a4db94011d3 920 osc8m_conf.run_in_standby = CONF_CLOCK_OSC8M_RUN_IN_STANDBY;
sahilmgandhi 18:6a4db94011d3 921
sahilmgandhi 18:6a4db94011d3 922 system_clock_source_osc8m_set_config(&osc8m_conf);
sahilmgandhi 18:6a4db94011d3 923 system_clock_source_enable(SYSTEM_CLOCK_SOURCE_OSC8M);
sahilmgandhi 18:6a4db94011d3 924
sahilmgandhi 18:6a4db94011d3 925
sahilmgandhi 18:6a4db94011d3 926 /* GCLK */
sahilmgandhi 18:6a4db94011d3 927 #if CONF_CLOCK_CONFIGURE_GCLK == true
sahilmgandhi 18:6a4db94011d3 928 system_gclk_init();
sahilmgandhi 18:6a4db94011d3 929
sahilmgandhi 18:6a4db94011d3 930 /* Configure all GCLK generators except for the main generator, which
sahilmgandhi 18:6a4db94011d3 931 * is configured later after all other clock systems are set up */
sahilmgandhi 18:6a4db94011d3 932 MREPEAT(GCLK_GEN_NUM, _CONF_CLOCK_GCLK_CONFIG_NONMAIN, ~);
sahilmgandhi 18:6a4db94011d3 933
sahilmgandhi 18:6a4db94011d3 934 # if CONF_CLOCK_DFLL_ENABLE == true
sahilmgandhi 18:6a4db94011d3 935 /* Enable DFLL reference clock if in closed loop mode */
sahilmgandhi 18:6a4db94011d3 936 if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) {
sahilmgandhi 18:6a4db94011d3 937 struct system_gclk_chan_config dfll_gclk_chan_conf;
sahilmgandhi 18:6a4db94011d3 938
sahilmgandhi 18:6a4db94011d3 939 system_gclk_chan_get_config_defaults(&dfll_gclk_chan_conf);
sahilmgandhi 18:6a4db94011d3 940 dfll_gclk_chan_conf.source_generator = CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR;
sahilmgandhi 18:6a4db94011d3 941 system_gclk_chan_set_config(SYSCTRL_GCLK_ID_DFLL48, &dfll_gclk_chan_conf);
sahilmgandhi 18:6a4db94011d3 942 system_gclk_chan_enable(SYSCTRL_GCLK_ID_DFLL48);
sahilmgandhi 18:6a4db94011d3 943 }
sahilmgandhi 18:6a4db94011d3 944 # endif
sahilmgandhi 18:6a4db94011d3 945
sahilmgandhi 18:6a4db94011d3 946 # if CONF_CLOCK_DPLL_ENABLE == true
sahilmgandhi 18:6a4db94011d3 947 /* Enable DPLL internal lock timer and reference clock */
sahilmgandhi 18:6a4db94011d3 948 struct system_gclk_chan_config dpll_gclk_chan_conf;
sahilmgandhi 18:6a4db94011d3 949 system_gclk_chan_get_config_defaults(&dpll_gclk_chan_conf);
sahilmgandhi 18:6a4db94011d3 950 if (CONF_CLOCK_DPLL_LOCK_TIME != SYSTEM_CLOCK_SOURCE_DPLL_LOCK_TIME_DEFAULT) {
sahilmgandhi 18:6a4db94011d3 951 dpll_gclk_chan_conf.source_generator = CONF_CLOCK_DPLL_LOCK_GCLK_GENERATOR;
sahilmgandhi 18:6a4db94011d3 952 system_gclk_chan_set_config(SYSCTRL_GCLK_ID_FDPLL32K, &dpll_gclk_chan_conf);
sahilmgandhi 18:6a4db94011d3 953 system_gclk_chan_enable(SYSCTRL_GCLK_ID_FDPLL32K);
sahilmgandhi 18:6a4db94011d3 954 }
sahilmgandhi 18:6a4db94011d3 955
sahilmgandhi 18:6a4db94011d3 956 if (CONF_CLOCK_DPLL_REFERENCE_CLOCK == SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_GCLK) {
sahilmgandhi 18:6a4db94011d3 957 dpll_gclk_chan_conf.source_generator = CONF_CLOCK_DPLL_REFERENCE_GCLK_GENERATOR;
sahilmgandhi 18:6a4db94011d3 958 system_gclk_chan_set_config(SYSCTRL_GCLK_ID_FDPLL, &dpll_gclk_chan_conf);
sahilmgandhi 18:6a4db94011d3 959 system_gclk_chan_enable(SYSCTRL_GCLK_ID_FDPLL);
sahilmgandhi 18:6a4db94011d3 960 }
sahilmgandhi 18:6a4db94011d3 961 # endif
sahilmgandhi 18:6a4db94011d3 962 #endif
sahilmgandhi 18:6a4db94011d3 963
sahilmgandhi 18:6a4db94011d3 964
sahilmgandhi 18:6a4db94011d3 965 /* DFLL Enable (Open and Closed Loop) */
sahilmgandhi 18:6a4db94011d3 966 #if CONF_CLOCK_DFLL_ENABLE == true
sahilmgandhi 18:6a4db94011d3 967 system_clock_source_enable(SYSTEM_CLOCK_SOURCE_DFLL);
sahilmgandhi 18:6a4db94011d3 968 while(!system_clock_source_is_ready(SYSTEM_CLOCK_SOURCE_DFLL));
sahilmgandhi 18:6a4db94011d3 969 if (CONF_CLOCK_DFLL_ON_DEMAND) {
sahilmgandhi 18:6a4db94011d3 970 SYSCTRL->DFLLCTRL.bit.ONDEMAND = 1;
sahilmgandhi 18:6a4db94011d3 971 }
sahilmgandhi 18:6a4db94011d3 972 #endif
sahilmgandhi 18:6a4db94011d3 973
sahilmgandhi 18:6a4db94011d3 974 /* DPLL */
sahilmgandhi 18:6a4db94011d3 975 #ifdef FEATURE_SYSTEM_CLOCK_DPLL
sahilmgandhi 18:6a4db94011d3 976 # if (CONF_CLOCK_DPLL_ENABLE == true)
sahilmgandhi 18:6a4db94011d3 977
sahilmgandhi 18:6a4db94011d3 978 /* Enable DPLL reference clock */
sahilmgandhi 18:6a4db94011d3 979 if (CONF_CLOCK_DPLL_REFERENCE_CLOCK == SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_XOSC32K) {
sahilmgandhi 18:6a4db94011d3 980 /* XOSC32K should have been enabled for DPLL_REF0 */
sahilmgandhi 18:6a4db94011d3 981 Assert(CONF_CLOCK_XOSC32K_ENABLE);
sahilmgandhi 18:6a4db94011d3 982 } else if (CONF_CLOCK_DPLL_REFERENCE_CLOCK == SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_XOSC) {
sahilmgandhi 18:6a4db94011d3 983 /* XOSC should have been enabled for DPLL_REF1 */
sahilmgandhi 18:6a4db94011d3 984 Assert(CONF_CLOCK_XOSC_ENABLE);
sahilmgandhi 18:6a4db94011d3 985 } else if (CONF_CLOCK_DPLL_REFERENCE_CLOCK == SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_GCLK) {
sahilmgandhi 18:6a4db94011d3 986 /* GCLK should have been enabled */
sahilmgandhi 18:6a4db94011d3 987 Assert(CONF_CLOCK_CONFIGURE_GCLK);
sahilmgandhi 18:6a4db94011d3 988 } else {
sahilmgandhi 18:6a4db94011d3 989 Assert(false);
sahilmgandhi 18:6a4db94011d3 990 }
sahilmgandhi 18:6a4db94011d3 991
sahilmgandhi 18:6a4db94011d3 992 struct system_clock_source_dpll_config dpll_config;
sahilmgandhi 18:6a4db94011d3 993 system_clock_source_dpll_get_config_defaults(&dpll_config);
sahilmgandhi 18:6a4db94011d3 994
sahilmgandhi 18:6a4db94011d3 995 dpll_config.on_demand = false;
sahilmgandhi 18:6a4db94011d3 996 dpll_config.run_in_standby = CONF_CLOCK_DPLL_RUN_IN_STANDBY;
sahilmgandhi 18:6a4db94011d3 997 dpll_config.lock_bypass = CONF_CLOCK_DPLL_LOCK_BYPASS;
sahilmgandhi 18:6a4db94011d3 998 dpll_config.wake_up_fast = CONF_CLOCK_DPLL_WAKE_UP_FAST;
sahilmgandhi 18:6a4db94011d3 999 dpll_config.low_power_enable = CONF_CLOCK_DPLL_LOW_POWER_ENABLE;
sahilmgandhi 18:6a4db94011d3 1000
sahilmgandhi 18:6a4db94011d3 1001 dpll_config.filter = CONF_CLOCK_DPLL_FILTER;
sahilmgandhi 18:6a4db94011d3 1002 dpll_config.lock_time = CONF_CLOCK_DPLL_LOCK_TIME;
sahilmgandhi 18:6a4db94011d3 1003
sahilmgandhi 18:6a4db94011d3 1004 dpll_config.reference_clock = CONF_CLOCK_DPLL_REFERENCE_CLOCK;
sahilmgandhi 18:6a4db94011d3 1005 dpll_config.reference_frequency = CONF_CLOCK_DPLL_REFERENCE_FREQUENCY;
sahilmgandhi 18:6a4db94011d3 1006 dpll_config.reference_divider = CONF_CLOCK_DPLL_REFERENCE_DIVIDER;
sahilmgandhi 18:6a4db94011d3 1007 dpll_config.output_frequency = CONF_CLOCK_DPLL_OUTPUT_FREQUENCY;
sahilmgandhi 18:6a4db94011d3 1008
sahilmgandhi 18:6a4db94011d3 1009 system_clock_source_dpll_set_config(&dpll_config);
sahilmgandhi 18:6a4db94011d3 1010 system_clock_source_enable(SYSTEM_CLOCK_SOURCE_DPLL);
sahilmgandhi 18:6a4db94011d3 1011 while(!system_clock_source_is_ready(SYSTEM_CLOCK_SOURCE_DPLL));
sahilmgandhi 18:6a4db94011d3 1012 if (CONF_CLOCK_DPLL_ON_DEMAND) {
sahilmgandhi 18:6a4db94011d3 1013 SYSCTRL->DPLLCTRLA.bit.ONDEMAND = 1;
sahilmgandhi 18:6a4db94011d3 1014 }
sahilmgandhi 18:6a4db94011d3 1015
sahilmgandhi 18:6a4db94011d3 1016 # endif
sahilmgandhi 18:6a4db94011d3 1017 #endif
sahilmgandhi 18:6a4db94011d3 1018
sahilmgandhi 18:6a4db94011d3 1019 /* CPU and BUS clocks */
sahilmgandhi 18:6a4db94011d3 1020 system_cpu_clock_set_divider(CONF_CLOCK_CPU_DIVIDER);
sahilmgandhi 18:6a4db94011d3 1021
sahilmgandhi 18:6a4db94011d3 1022 system_apb_clock_set_divider(SYSTEM_CLOCK_APB_APBA, CONF_CLOCK_APBA_DIVIDER);
sahilmgandhi 18:6a4db94011d3 1023 system_apb_clock_set_divider(SYSTEM_CLOCK_APB_APBB, CONF_CLOCK_APBB_DIVIDER);
sahilmgandhi 18:6a4db94011d3 1024 system_apb_clock_set_divider(SYSTEM_CLOCK_APB_APBC, CONF_CLOCK_APBC_DIVIDER);
sahilmgandhi 18:6a4db94011d3 1025
sahilmgandhi 18:6a4db94011d3 1026 /* GCLK 0 */
sahilmgandhi 18:6a4db94011d3 1027 #if CONF_CLOCK_CONFIGURE_GCLK == true
sahilmgandhi 18:6a4db94011d3 1028 /* Configure the main GCLK last as it might depend on other generators */
sahilmgandhi 18:6a4db94011d3 1029 _CONF_CLOCK_GCLK_CONFIG(0, ~);
sahilmgandhi 18:6a4db94011d3 1030 #endif
sahilmgandhi 18:6a4db94011d3 1031 }