Starting point for the SAMD20 demo.
diff --git a/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock.c b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock.c new file mode 100644 index 0000000..3f773e5 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock.c
@@ -0,0 +1,748 @@ +/** + * \file + * + * \brief SAM D20 Clock Driver + * + * Copyright (C) 2012-2013 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +#include <clock.h> +#include <conf_clocks.h> + +/** + * \internal + * \brief DFLL-specific data container + */ +struct _system_clock_dfll_config { + uint32_t control; + uint32_t val; + uint32_t mul; +}; + +/** + * \internal + * \brief XOSC-specific data container + */ +struct _system_clock_xosc_config { + uint32_t frequency; +}; + +/** + * \internal + * \brief System clock module data container + */ +struct _system_clock_module { + volatile struct _system_clock_dfll_config dfll; + volatile struct _system_clock_xosc_config xosc; + volatile struct _system_clock_xosc_config xosc32k; +}; + +/** + * \internal + * \brief Internal module instance to cache configuration values + */ +static struct _system_clock_module _system_clock_inst = { + .dfll = { + .control = 0, + .val = 0, + .mul = 0, + }, + .xosc = { + .frequency = 0, + }, + .xosc32k = { + .frequency = 0, + }, + }; + +/** + * \internal + * \brief Wait for sync to the DFLL control registers + */ +static inline void _system_dfll_wait_for_sync(void) +{ + while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY)) { + /* Wait for DFLL sync */ + } +} + +/** + * \internal + * \brief Wait for sync to the OSC32K control registers + */ +static inline void _system_osc32k_wait_for_sync(void) +{ + while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC32KRDY)) { + /* Wait for OSC32K sync */ + } +} + +static inline void _system_clock_source_dfll_set_config_errata_9905(void) +{ + + /* Disable ONDEMAND mode while writing configurations */ + SYSCTRL->DFLLCTRL.reg = _system_clock_inst.dfll.control & ~SYSCTRL_DFLLCTRL_ONDEMAND; + _system_dfll_wait_for_sync(); + + SYSCTRL->DFLLMUL.reg = _system_clock_inst.dfll.mul; + SYSCTRL->DFLLVAL.reg = _system_clock_inst.dfll.val; + + /* Write full configuration to DFLL control register */ + SYSCTRL->DFLLCTRL.reg = _system_clock_inst.dfll.control; +} + +/** + * \brief Retrieve the frequency of a clock source + * + * Determines the current operating frequency of a given clock source. + * + * \param[in] clock_source Clock source to get the frequency of + * + * \returns Frequency of the given clock source, in Hz + */ +uint32_t system_clock_source_get_hz( + const enum system_clock_source clock_source) +{ + switch (clock_source) { + case SYSTEM_CLOCK_SOURCE_XOSC: + return _system_clock_inst.xosc.frequency; + + case SYSTEM_CLOCK_SOURCE_OSC8M: + return 8000000UL >> SYSCTRL->OSC8M.bit.PRESC; + + case SYSTEM_CLOCK_SOURCE_OSC32K: + return 32768UL; + + case SYSTEM_CLOCK_SOURCE_ULP32K: + return 32768UL; + + case SYSTEM_CLOCK_SOURCE_XOSC32K: + return _system_clock_inst.xosc32k.frequency; + + case SYSTEM_CLOCK_SOURCE_DFLL: + + /* Check if the DFLL has been configured */ + if (!(_system_clock_inst.dfll.control & SYSCTRL_DFLLCTRL_ENABLE)) + return 0; + + /* Make sure that the DFLL module is ready */ + _system_dfll_wait_for_sync(); + + /* Check if operating in closed loop mode */ + if (_system_clock_inst.dfll.control & SYSCTRL_DFLLCTRL_MODE) { + return system_gclk_chan_get_hz(SYSCTRL_GCLK_ID_DFLL48) * + (_system_clock_inst.dfll.mul & 0xffff); + } + + return 48000000UL; + + default: + return 0; + } +} + +/** + * \brief Configure the internal OSC8M oscillator clock source + * + * Configures the 8MHz (nominal) internal RC oscillator with the given + * configuration settings. + * + * \param[in] config OSC8M configuration structure containing the new config + */ +void system_clock_source_osc8m_set_config( + struct system_clock_source_osc8m_config *const config) +{ + SYSCTRL_OSC8M_Type temp = SYSCTRL->OSC8M; + + /* Use temporary struct to reduce register access */ + temp.bit.PRESC = config->prescaler; + temp.bit.ONDEMAND = config->on_demand; + temp.bit.RUNSTDBY = config->run_in_standby; + + SYSCTRL->OSC8M = temp; +} + +/** + * \brief Configure the internal OSC32K oscillator clock source + * + * Configures the 32KHz (nominal) internal RC oscillator with the given + * configuration settings. + * + * \param[in] config OSC32K configuration structure containing the new config + */ +void system_clock_source_osc32k_set_config( + struct system_clock_source_osc32k_config *const config) +{ + SYSCTRL_OSC32K_Type temp = SYSCTRL->OSC32K; + + /* Update settings via a temporary struct to reduce register access */ + temp.bit.EN1K = config->enable_1khz_output; + temp.bit.EN32K = config->enable_32khz_output; + temp.bit.STARTUP = config->startup_time; + temp.bit.ONDEMAND = config->on_demand; + temp.bit.RUNSTDBY = config->run_in_standby; + + SYSCTRL->OSC32K = temp; +} + +/** + * \brief Configure the external oscillator clock source + * + * Configures the external oscillator clock source with the given configuration + * settings. + * + * \param[in] config External oscillator configuration structure containing + * the new config + */ +void system_clock_source_xosc_set_config( + struct system_clock_source_xosc_config *const config) +{ + SYSCTRL_XOSC_Type temp = SYSCTRL->XOSC; + + temp.bit.STARTUP = config->startup_time; + + if (config->external_clock == SYSTEM_CLOCK_EXTERNAL_CRYSTAL) { + temp.bit.XTALEN = 1; + } else { + temp.bit.XTALEN = 0; + } + + temp.bit.AMPGC = config->auto_gain_control; + + /* Set gain if automatic gain control is not selected */ + if (!config->auto_gain_control) { + if (config->frequency <= 2000000) { + temp.bit.GAIN = 0; + } else if (config->frequency <= 4000000) { + temp.bit.GAIN = 1; + } else if (config->frequency <= 8000000) { + temp.bit.GAIN = 2; + } else if (config->frequency <= 16000000) { + temp.bit.GAIN = 3; + } else if (config->frequency <= 30000000) { + temp.bit.GAIN = 4; + } + + } + + temp.bit.ONDEMAND = config->on_demand; + temp.bit.RUNSTDBY = config->run_in_standby; + + /* Store XOSC frequency for internal use */ + _system_clock_inst.xosc.frequency = config->frequency; + + SYSCTRL->XOSC = temp; +} + +/** + * \brief Configure the XOSC32K external 32KHz oscillator clock source + * + * Configures the external 32KHz oscillator clock source with the given + * configuration settings. + * + * \param[in] config XOSC32K configuration structure containing the new config + */ +void system_clock_source_xosc32k_set_config( + struct system_clock_source_xosc32k_config *const config) +{ + SYSCTRL_XOSC32K_Type temp = SYSCTRL->XOSC32K; + + temp.bit.STARTUP = config->startup_time; + + if (config->external_clock == SYSTEM_CLOCK_EXTERNAL_CRYSTAL) { + temp.bit.XTALEN = 1; + } else { + temp.bit.XTALEN = 0; + } + + temp.bit.AAMPEN = config->auto_gain_control; + temp.bit.EN1K = config->enable_1khz_output; + temp.bit.EN32K = config->enable_32khz_output; + + temp.bit.ONDEMAND = config->on_demand; + temp.bit.RUNSTDBY = config->run_in_standby; + + /* Cache the new frequency in case the user needs to check the current + * operating frequency later */ + _system_clock_inst.xosc32k.frequency = config->frequency; + + SYSCTRL->XOSC32K = temp; +} + +/** + * \brief Configure the DFLL clock source + * + * Configures the Digital Frequency Locked Loop clock source with the given + * configuration settings. + * + * \note The DFLL will be running when this function returns, as the DFLL module + * needs to be enabled in order to perform the module configuration. + * + * \param[in] config DFLL configuration structure containing the new config + */ +void system_clock_source_dfll_set_config( + struct system_clock_source_dfll_config *const config) +{ + _system_clock_inst.dfll.val = + SYSCTRL_DFLLVAL_COARSE(config->coarse_value) | + SYSCTRL_DFLLVAL_FINE(config->fine_value); + + _system_clock_inst.dfll.control = + (uint32_t)config->wakeup_lock | + (uint32_t)config->stable_tracking | + (uint32_t)config->quick_lock | + (uint32_t)config->chill_cycle | + (uint32_t)config->run_in_standby << SYSCTRL_DFLLCTRL_RUNSTDBY_Pos | + (uint32_t)config->on_demand << SYSCTRL_DFLLCTRL_ONDEMAND_Pos; + + if (config->loop_mode == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) { + _system_clock_inst.dfll.mul = + SYSCTRL_DFLLMUL_CSTEP(config->coarse_max_step) | + SYSCTRL_DFLLMUL_FSTEP(config->fine_max_step) | + SYSCTRL_DFLLMUL_MUL(config->multiply_factor); + + /* Enable the closed loop mode */ + _system_clock_inst.dfll.control |= config->loop_mode; + } +} + +/** + * \brief Writes the calibration values for a given oscillator clock source + * + * Writes an oscillator calibration value to the given oscillator control + * registers. The acceptable ranges are: + * + * For OSC32K: + * - 7 bits (max value 128) + * For OSC8MHZ: + * - 8 bits (Max value 255) + * For OSCULP: + * - 5 bits (Max value 32) + * + * \note The frequency range parameter applies only when configuring the 8MHz + * oscillator and will be ignored for the other oscillators. + * + * \param[in] clock_source Clock source to calibrate + * \param[in] calibration_value Calibration value to write + * \param[in] freq_range Frequency range (8MHz oscillator only) + * + * \retval STATUS_ERR_INVALID_ARG The selected clock source is not available + */ +enum status_code system_clock_source_write_calibration( + const enum system_clock_source clock_source, + const uint16_t calibration_value, + const uint8_t freq_range) +{ + switch (clock_source) { + case SYSTEM_CLOCK_SOURCE_OSC8M: + + if (calibration_value > 0xfff || freq_range > 4) { + return STATUS_ERR_INVALID_ARG; + } + + SYSCTRL->OSC8M.bit.CALIB = calibration_value; + SYSCTRL->OSC8M.bit.FRANGE = freq_range; + break; + + case SYSTEM_CLOCK_SOURCE_OSC32K: + + if (calibration_value > 128) { + return STATUS_ERR_INVALID_ARG; + } + + _system_osc32k_wait_for_sync(); + SYSCTRL->OSC32K.bit.CALIB = calibration_value; + break; + + case SYSTEM_CLOCK_SOURCE_ULP32K: + + if (calibration_value > 32) { + return STATUS_ERR_INVALID_ARG; + } + + SYSCTRL->OSCULP32K.bit.CALIB = calibration_value; + break; + + default: + Assert(false); + return STATUS_ERR_INVALID_ARG; + break; + } + + return STATUS_OK; +} + +/** + * \brief Enables a clock source + * + * Enables a clock source which has been previously configured. + * + * \param[in] clock_source Clock source to enable + * + * \retval STATUS_OK Clock source was enabled successfully and + * is ready + * \retval STATUS_ERR_INVALID_ARG The clock source is not available on this + * device + * + * \retval STATUS_ERR_NOT_INITIALIZED DFLL configuration is not initialized + */ +enum status_code system_clock_source_enable( + const enum system_clock_source clock_source) +{ + switch (clock_source) { + case SYSTEM_CLOCK_SOURCE_OSC8M: + SYSCTRL->OSC8M.reg |= SYSCTRL_OSC8M_ENABLE; + return STATUS_OK; + + case SYSTEM_CLOCK_SOURCE_OSC32K: + SYSCTRL->OSC32K.reg |= SYSCTRL_OSC32K_ENABLE; + break; + + case SYSTEM_CLOCK_SOURCE_XOSC: + SYSCTRL->XOSC.reg |= SYSCTRL_XOSC_ENABLE; + break; + + case SYSTEM_CLOCK_SOURCE_XOSC32K: + SYSCTRL->XOSC32K.reg |= SYSCTRL_XOSC32K_ENABLE; + break; + + case SYSTEM_CLOCK_SOURCE_DFLL: + _system_clock_inst.dfll.control |= SYSCTRL_DFLLCTRL_ENABLE; + _system_clock_source_dfll_set_config_errata_9905(); + break; + + case SYSTEM_CLOCK_SOURCE_ULP32K: + /* Always enabled */ + return STATUS_OK; + + default: + Assert(false); + return STATUS_ERR_INVALID_ARG; + } + + return STATUS_OK; +} + +/** + * \brief Disables a clock source + * + * Disables a clock source that was previously enabled. + * + * \param[in] clock_source Clock source to disable + * + * \retval STATUS_OK Clock source was disabled successfully + * \retval STATUS_ERR_INVALID_ARG An invalid or unavailable clock source was + * given + */ +enum status_code system_clock_source_disable( + const enum system_clock_source clock_source) +{ + switch (clock_source) { + case SYSTEM_CLOCK_SOURCE_OSC8M: + SYSCTRL->OSC8M.reg &= ~SYSCTRL_OSC8M_ENABLE; + break; + + case SYSTEM_CLOCK_SOURCE_OSC32K: + SYSCTRL->OSC32K.reg &= ~SYSCTRL_OSC32K_ENABLE; + break; + + case SYSTEM_CLOCK_SOURCE_XOSC: + SYSCTRL->XOSC.reg &= ~SYSCTRL_XOSC_ENABLE; + break; + + case SYSTEM_CLOCK_SOURCE_XOSC32K: + SYSCTRL->XOSC32K.reg &= ~SYSCTRL_XOSC32K_ENABLE; + break; + + case SYSTEM_CLOCK_SOURCE_DFLL: + _system_clock_inst.dfll.control &= ~SYSCTRL_DFLLCTRL_ENABLE; + SYSCTRL->DFLLCTRL.reg = _system_clock_inst.dfll.control; + break; + + case SYSTEM_CLOCK_SOURCE_ULP32K: + /* Not possible to disable */ + return STATUS_ERR_INVALID_ARG; + + default: + return STATUS_ERR_INVALID_ARG; + } + + return STATUS_OK; +} + +/** + * \brief Checks if a clock source is ready + * + * Checks if a given clock source is ready to be used. + * + * \param[in] clock_source Clock source to check if ready + * + * \returns Ready state of the given clock source. + * + * \retval true Clock source is enabled and ready + * \retval false Clock source is disabled or not yet ready + */ +bool system_clock_source_is_ready( + const enum system_clock_source clock_source) +{ + uint32_t mask; + + switch (clock_source) { + case SYSTEM_CLOCK_SOURCE_OSC8M: + mask = SYSCTRL_PCLKSR_OSC8MRDY; + break; + + case SYSTEM_CLOCK_SOURCE_OSC32K: + mask = SYSCTRL_PCLKSR_OSC32KRDY; + break; + + case SYSTEM_CLOCK_SOURCE_XOSC: + mask = SYSCTRL_PCLKSR_XOSCRDY; + break; + + case SYSTEM_CLOCK_SOURCE_XOSC32K: + mask = SYSCTRL_PCLKSR_XOSC32KRDY; + break; + + case SYSTEM_CLOCK_SOURCE_DFLL: + mask = SYSCTRL_PCLKSR_DFLLRDY; + break; + + case SYSTEM_CLOCK_SOURCE_ULP32K: + /* Not possible to disable */ + return true; + + default: + return false; + } + + return ((SYSCTRL->PCLKSR.reg & mask) != 0); +} + +/* Include some checks for conf_clocks.h validation */ +#include "clock_config_check.h" + +#if !defined(__DOXYGEN__) +/** \internal + * + * Configures a Generic Clock Generator with the configuration from \c conf_clocks.h. + */ +# define _CONF_CLOCK_GCLK_CONFIG(n, unused) \ + if (CONF_CLOCK_GCLK_##n##_ENABLE == true) { \ + struct system_gclk_gen_config gclk_conf; \ + system_gclk_gen_get_config_defaults(&gclk_conf); \ + gclk_conf.source_clock = CONF_CLOCK_GCLK_##n##_CLOCK_SOURCE; \ + gclk_conf.division_factor = CONF_CLOCK_GCLK_##n##_PRESCALER; \ + gclk_conf.run_in_standby = CONF_CLOCK_GCLK_##n##_RUN_IN_STANDBY; \ + gclk_conf.output_enable = CONF_CLOCK_GCLK_##n##_OUTPUT_ENABLE; \ + system_gclk_gen_set_config(GCLK_GENERATOR_##n, &gclk_conf); \ + system_gclk_gen_enable(GCLK_GENERATOR_##n); \ + } + +/** \internal + * + * Configures a Generic Clock Generator with the configuration from \c conf_clocks.h, + * provided that it is not the main Generic Clock Generator channel. + */ +# define _CONF_CLOCK_GCLK_CONFIG_NONMAIN(n, unused) \ + if (n > 0) { _CONF_CLOCK_GCLK_CONFIG(n, unused); } +#endif + +/** + * \brief Initialize clock system based on the configuration in conf_clocks.h + * + * This function will apply the settings in conf_clocks.h when run from the user + * application. All clock sources and GCLK generators are running when this function + * returns. + */ +void system_clock_init(void) +{ + /* Workaround for errata 10558 */ + SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD12RDY | SYSCTRL_INTFLAG_BOD33RDY | + SYSCTRL_INTFLAG_BOD12DET | SYSCTRL_INTFLAG_BOD33DET | + SYSCTRL_INTFLAG_DFLLRDY; + + system_flash_set_waitstates(CONF_CLOCK_FLASH_WAIT_STATES); + + /* XOSC */ +#if CONF_CLOCK_XOSC_ENABLE == true + struct system_clock_source_xosc_config xosc_conf; + system_clock_source_xosc_get_config_defaults(&xosc_conf); + + xosc_conf.external_clock = CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL; + xosc_conf.startup_time = CONF_CLOCK_XOSC_STARTUP_TIME; + xosc_conf.auto_gain_control = CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL; + xosc_conf.frequency = CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY; + xosc_conf.on_demand = CONF_CLOCK_XOSC_ON_DEMAND; + xosc_conf.run_in_standby = CONF_CLOCK_XOSC_RUN_IN_STANDBY; + + system_clock_source_xosc_set_config(&xosc_conf); + system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC); +#endif + + + /* XOSC32K */ +#if CONF_CLOCK_XOSC32K_ENABLE == true + struct system_clock_source_xosc32k_config xosc32k_conf; + system_clock_source_xosc32k_get_config_defaults(&xosc32k_conf); + + xosc32k_conf.frequency = 32768UL; + xosc32k_conf.external_clock = CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL; + xosc32k_conf.startup_time = CONF_CLOCK_XOSC32K_STARTUP_TIME; + xosc32k_conf.auto_gain_control = CONF_CLOCK_XOSC32K_AUTO_AMPLITUDE_CONTROL; + xosc32k_conf.enable_1khz_output = CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT; + xosc32k_conf.enable_32khz_output = CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT; + xosc32k_conf.on_demand = CONF_CLOCK_XOSC32K_ON_DEMAND; + xosc32k_conf.run_in_standby = CONF_CLOCK_XOSC32K_RUN_IN_STANDBY; + + system_clock_source_xosc32k_set_config(&xosc32k_conf); + system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC32K); +#endif + + + /* OSCK32K */ +#if CONF_CLOCK_OSC32K_ENABLE == true + SYSCTRL->OSC32K.bit.CALIB = + (*(uint32_t *)SYSCTRL_FUSES_OSC32KCAL_ADDR >> SYSCTRL_FUSES_OSC32KCAL_Pos); + + struct system_clock_source_osc32k_config osc32k_conf; + system_clock_source_osc32k_get_config_defaults(&osc32k_conf); + + osc32k_conf.startup_time = CONF_CLOCK_OSC32K_STARTUP_TIME; + osc32k_conf.enable_1khz_output = CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT; + osc32k_conf.enable_32khz_output = CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT; + osc32k_conf.on_demand = CONF_CLOCK_OSC32K_ON_DEMAND; + osc32k_conf.run_in_standby = CONF_CLOCK_OSC32K_RUN_IN_STANDBY; + + system_clock_source_osc32k_set_config(&osc32k_conf); + system_clock_source_enable(SYSTEM_CLOCK_SOURCE_OSC32K); +#endif + + + /* DFLL (Open and Closed Loop) */ +#if CONF_CLOCK_DFLL_ENABLE == true + struct system_clock_source_dfll_config dfll_conf; + system_clock_source_dfll_get_config_defaults(&dfll_conf); + + dfll_conf.loop_mode = CONF_CLOCK_DFLL_LOOP_MODE; + dfll_conf.on_demand = CONF_CLOCK_DFLL_ON_DEMAND; + dfll_conf.run_in_standby = CONF_CLOCK_DFLL_RUN_IN_STANDBY; + + if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_OPEN) { + dfll_conf.coarse_value = CONF_CLOCK_DFLL_COARSE_VALUE; + dfll_conf.fine_value = CONF_CLOCK_DFLL_FINE_VALUE; + } + +# if CONF_CLOCK_DFLL_QUICK_LOCK == true + dfll_conf.quick_lock = SYSTEM_CLOCK_DFLL_QUICK_LOCK_ENABLE; +# else + dfll_conf.quick_lock = SYSTEM_CLOCK_DFLL_QUICK_LOCK_DISABLE; +# endif + +# if CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK == true + dfll_conf.stable_tracking = SYSTEM_CLOCK_DFLL_STABLE_TRACKING_TRACK_AFTER_LOCK; +# else + dfll_conf.stable_tracking = SYSTEM_CLOCK_DFLL_STABLE_TRACKING_FIX_AFTER_LOCK; +# endif + +# if CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP == true + dfll_conf.wakeup_lock = SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_KEEP; +# else + dfll_conf.wakeup_lock = SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_LOSE; +# endif + +# if CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE == true + dfll_conf.chill_cycle = SYSTEM_CLOCK_DFLL_CHILL_CYCLE_ENABLE; +# else + dfll_conf.chill_cycle = SYSTEM_CLOCK_DFLL_CHILL_CYCLE_DISABLE; +# endif + + if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) { + dfll_conf.multiply_factor = CONF_CLOCK_DFLL_MULTIPLY_FACTOR; + } + + dfll_conf.coarse_max_step = CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE; + dfll_conf.fine_max_step = CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE; + + system_clock_source_dfll_set_config(&dfll_conf); + system_clock_source_enable(SYSTEM_CLOCK_SOURCE_DFLL); +#endif + + + /* OSC8M */ + struct system_clock_source_osc8m_config osc8m_conf; + system_clock_source_osc8m_get_config_defaults(&osc8m_conf); + + osc8m_conf.prescaler = CONF_CLOCK_OSC8M_PRESCALER; + osc8m_conf.on_demand = CONF_CLOCK_OSC8M_ON_DEMAND; + osc8m_conf.run_in_standby = CONF_CLOCK_OSC8M_RUN_IN_STANDBY; + + system_clock_source_osc8m_set_config(&osc8m_conf); + system_clock_source_enable(SYSTEM_CLOCK_SOURCE_OSC8M); + + + /* GCLK */ +#if CONF_CLOCK_CONFIGURE_GCLK == true + system_gclk_init(); + + /* Configure all GCLK generators except for the main generator, which + * is configured later after all other clock systems are set up */ + MREPEAT(GCLK_GEN_NUM_MSB, _CONF_CLOCK_GCLK_CONFIG_NONMAIN, ~); + +# if (CONF_CLOCK_DFLL_ENABLE) + /* Enable DFLL reference clock if in closed loop mode */ + if (CONF_CLOCK_DFLL_LOOP_MODE == SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED) { + struct system_gclk_chan_config dfll_gclk_chan_conf; + + system_gclk_chan_get_config_defaults(&dfll_gclk_chan_conf); + dfll_gclk_chan_conf.source_generator = CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR; + system_gclk_chan_set_config(SYSCTRL_GCLK_ID_DFLL48, &dfll_gclk_chan_conf); + system_gclk_chan_enable(SYSCTRL_GCLK_ID_DFLL48); + } +# endif + + /* Configure the main GCLK last as it might depend on other generators */ + _CONF_CLOCK_GCLK_CONFIG(0, ~); +#endif + + + /* CPU and BUS clocks */ + system_cpu_clock_set_divider(CONF_CLOCK_CPU_DIVIDER); + system_main_clock_set_failure_detect(CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT); + system_apb_clock_set_divider(SYSTEM_CLOCK_APB_APBA, CONF_CLOCK_APBA_DIVIDER); + system_apb_clock_set_divider(SYSTEM_CLOCK_APB_APBB, CONF_CLOCK_APBB_DIVIDER); +}
diff --git a/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock.h b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock.h new file mode 100644 index 0000000..f9871b0 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock.h
@@ -0,0 +1,1275 @@ +/** + * \file + * + * \brief SAM D20 Clock Driver + * + * Copyright (C) 2012-2013 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +#ifndef SYSTEM_CLOCK_H_INCLUDED +#define SYSTEM_CLOCK_H_INCLUDED + +/** + * \defgroup asfdoc_samd20_system_clock_group SAM D20 System Clock Management Driver (SYSTEM CLOCK) + * + * This driver for SAM D20 devices provides an interface for the configuration + * and management of the device's clocking related functions. This includes + * the various clock sources, bus clocks and generic clocks within the device, + * with functions to manage the enabling, disabling, source selection and + * prescaling of clocks to various internal peripherals. + * + * The following peripherals are used by this module: + * + * - GCLK (Generic Clock Management) + * - PM (Power Management) + * - SYSCTRL (Clock Source Control) + * + * The outline of this documentation is as follows: + * - \ref asfdoc_samd20_system_clock_prerequisites + * - \ref asfdoc_samd20_system_clock_module_overview + * - \ref asfdoc_samd20_system_clock_special_considerations + * - \ref asfdoc_samd20_system_clock_extra_info + * - \ref asfdoc_samd20_system_clock_examples + * - \ref asfdoc_samd20_system_clock_api_overview + * + * + * \section asfdoc_samd20_system_clock_prerequisites Prerequisites + * + * There are no prerequisites for this module. + * + * + * \section asfdoc_samd20_system_clock_module_overview Module Overview + * The SAM D20 devices contain a sophisticated clocking system, which is designed + * to give the maximum flexibility to the user application. This system allows + * a system designer to tune the performance and power consumption of the device + * in a dynamic manner, to achieve the best trade-off between the two for a + * particular application. + * + * This driver provides a set of functions for the configuration and management + * of the various clock related functionality within the device. + * + * \subsection asfdoc_samd20_system_clock_module_overview_clock_sources Clock Sources + * The SAM D20 devices have a number of master clock source modules, each of + * which being capable of producing a stabilized output frequency which can then + * be fed into the various peripherals and modules within the device. + * + * Possible clock source modules include internal R/C oscillators, internal + * DFLL modules, as well as external crystal oscillators and/or clock inputs. + * + * \subsection asfdoc_samd20_system_clock_module_overview_cpu_clock CPU / Bus Clocks + * The CPU and AHB/APBx buses are clocked by the same physical clock source + * (referred in this module as the Main Clock), however the APBx buses may + * have additional prescaler division ratios set to give each peripheral bus a + * different clock speed. + * + * The general main clock tree for the CPU and associated buses is shown in + * \ref asfdoc_samd20_system_clock_module_clock_tree "the figure below". + * + * \anchor asfdoc_samd20_system_clock_module_clock_tree + * \dot + * digraph overview { + * rankdir=LR; + * clk_src [label="Clock Sources", shape=none, height=0]; + * node [label="CPU Bus" shape=ellipse] cpu_bus; + * node [label="AHB Bus" shape=ellipse] ahb_bus; + * node [label="APBA Bus" shape=ellipse] apb_a_bus; + * node [label="APBB Bus" shape=ellipse] apb_b_bus; + * node [label="APBC Bus" shape=ellipse] apb_c_bus; + * node [label="Main Bus\nPrescaler" shape=square] main_prescaler; + * node [label="APBA Bus\nPrescaler" shape=square] apb_a_prescaler; + * node [label="APBB Bus\nPrescaler" shape=square] apb_b_prescaler; + * node [label="APBC Bus\nPrescaler" shape=square] apb_c_prescaler; + * node [label="", shape=polygon, sides=4, distortion=0.6, orientation=90, style=filled, fillcolor=black, height=0.9, width=0.2] main_clock_mux; + * + * clk_src -> main_clock_mux; + * main_clock_mux -> main_prescaler; + * main_prescaler -> cpu_bus; + * main_prescaler -> ahb_bus; + * main_prescaler -> apb_a_prescaler; + * main_prescaler -> apb_b_prescaler; + * main_prescaler -> apb_c_prescaler; + * apb_a_prescaler -> apb_a_bus; + * apb_b_prescaler -> apb_b_bus; + * apb_c_prescaler -> apb_c_bus; + * } + * \enddot + * + * \subsection asfdoc_samd20_system_clock_module_overview_clock_masking Clock Masking + * To save power, the input clock to one or more peripherals on the AHB and APBx + * busses can be masked away - when masked, no clock is passed into the module. + * Disabling of clocks of unused modules will prevent all access to the masked + * module, but will reduce the overall device power consumption. + * + * \subsection asfdoc_samd20_system_clock_module_overview_gclk Generic Clocks + * Within the SAM D20 devices are a number of Generic Clocks; these are used to + * provide clocks to the various peripheral clock domains in the device in a + * standardized manner. One or more master source clocks can be selected as the + * input clock to a Generic Clock Generator, which can prescale down the input + * frequency to a slower rate for use in a peripheral. + * + * Additionally, a number of individually selectable Generic Clock Channels are + * provided, which multiplex and gate the various generator outputs for one or + * more peripherals within the device. This setup allows for a single common + * generator to feed one or more channels, which can then be enabled or disabled + * individually as required. + * + * \anchor asfdoc_samd20_system_clock_module_chain_overview + * \dot + * digraph overview { + * rankdir=LR; + * node [label="Clock\nSource a" shape=square] system_clock_source; + * node [label="Generator 1" shape=square] clock_gen; + * node [label="Channel x" shape=square] clock_chan0; + * node [label="Channel y" shape=square] clock_chan1; + * node [label="Peripheral x" shape=ellipse style=filled fillcolor=lightgray] peripheral0; + * node [label="Peripheral y" shape=ellipse style=filled fillcolor=lightgray] peripheral1; + * + * system_clock_source -> clock_gen; + * clock_gen -> clock_chan0; + * clock_chan0 -> peripheral0; + * clock_gen -> clock_chan1; + * clock_chan1 -> peripheral1; + * } + * \enddot + * + * \subsubsection asfdoc_samd20_system_clock_module_chain_example Clock Chain Example + * An example setup of a complete clock chain within the device is shown in + * \ref asfdoc_samd20_system_clock_module_chain_example_fig "the figure below". + * + * \anchor asfdoc_samd20_system_clock_module_chain_example_fig + * \dot + * digraph overview { + * rankdir=LR; + * node [label="External\nOscillator" shape=square] system_clock_source0; + * node [label="Generator 0" shape=square] clock_gen0; + * node [label="Channel x" shape=square] clock_chan0; + * node [label="Core CPU" shape=ellipse style=filled fillcolor=lightgray] peripheral0; + * + * system_clock_source0 -> clock_gen0; + * clock_gen0 -> clock_chan0; + * clock_chan0 -> peripheral0; + * node [label="8MHz R/C\nOscillator (OSC8M)" shape=square fillcolor=white] system_clock_source1; + * node [label="Generator 1" shape=square] clock_gen1; + * node [label="Channel y" shape=square] clock_chan1; + * node [label="Channel z" shape=square] clock_chan2; + * node [label="SERCOM\nModule" shape=ellipse style=filled fillcolor=lightgray] peripheral1; + * node [label="Timer\nModule" shape=ellipse style=filled fillcolor=lightgray] peripheral2; + * + * system_clock_source1 -> clock_gen1; + * clock_gen1 -> clock_chan1; + * clock_gen1 -> clock_chan2; + * clock_chan1 -> peripheral1; + * clock_chan2 -> peripheral2; + * } + * \enddot + * + * \subsubsection asfdoc_samd20_system_clock_module_overview_gclk_generators Generic Clock Generators + * Each Generic Clock generator within the device can source its input clock + * from one of the provided Source Clocks, and prescale the output for one or + * more Generic Clock Channels in a one-to-many relationship. The generators + * thus allow for several clocks to be generated of different frequencies, + * power usages and accuracies, which can be turned on and off individually to + * disable the clocks to multiple peripherals as a group. + * + * \subsubsection asfdoc_samd20_system_clock_module_overview_gclk_channels Generic Clock Channels + * To connect a Generic Clock Generator to a peripheral within the + * device, a Generic Clock Channel is used. Each peripheral or + * peripheral group has an associated Generic Clock Channel, which serves as the + * clock input for the peripheral(s). To supply a clock to the peripheral + * module(s), the associated channel must be connected to a running Generic + * Clock Generator and the channel enabled. + * + * \section asfdoc_samd20_system_clock_special_considerations Special Considerations + * + * There are no special considerations for this module. + * + * + * \section asfdoc_samd20_system_clock_extra_info Extra Information + * + * For extra information see \ref asfdoc_samd20_system_clock_extra. This includes: + * - \ref asfdoc_samd20_system_clock_extra_acronyms + * - \ref asfdoc_samd20_system_clock_extra_dependencies + * - \ref asfdoc_samd20_system_clock_extra_errata + * - \ref asfdoc_samd20_system_clock_extra_history + * + * + * \section asfdoc_samd20_system_clock_examples Examples + * + * For a list of examples related to this driver, see + * \ref asfdoc_samd20_system_clock_exqsg. + * + * + * \section asfdoc_samd20_system_clock_api_overview API Overview + * @{ + */ + +#include <compiler.h> +#include <gclk.h> + +/** + * \brief Available start-up times for the XOSC32K + * + * Available external 32KHz oscillator start-up times, as a number of external + * clock cycles. + */ +enum system_xosc32k_startup { + /** Wait 0 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC32K_STARTUP_0, + /** Wait 32 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC32K_STARTUP_32, + /** Wait 2048 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC32K_STARTUP_2048, + /** Wait 4096 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC32K_STARTUP_4096, + /** Wait 16384 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC32K_STARTUP_16384, + /** Wait 32768 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC32K_STARTUP_32768, + /** Wait 65536 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC32K_STARTUP_65536, + /** Wait 131072 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC32K_STARTUP_131072, +}; + +/** + * \brief Available start-up times for the XOSC + * + * Available external oscillator start-up times, as a number of external clock + * cycles. + */ +enum system_xosc_startup { + /** Wait 1 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_1, + /** Wait 2 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_2, + /** Wait 4 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_4, + /** Wait 8 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_8, + /** Wait 16 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_16, + /** Wait 32 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_32, + /** Wait 64 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_64, + /** Wait 128 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_128, + /** Wait 256 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_256, + /** Wait 512 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_512, + /** Wait 1024 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_1024, + /** Wait 2048 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_2048, + /** Wait 4096 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_4096, + /** Wait 8192 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_8192, + /** Wait 16384 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_16384, + /** Wait 32768 clock cycles until the clock source is considered stable */ + SYSTEM_XOSC_STARTUP_32768, +}; + +/** + * \brief Available start-up times for the OSC32K + * + * Available internal 32KHz oscillator start-up times, as a number of internal + * OSC32K clock cycles. + */ +enum system_osc32k_startup { + /** Wait 0 clock cycles until the clock source is considered stable */ + SYSTEM_OSC32K_STARTUP_0, + /** Wait 2 clock cycles until the clock source is considered stable */ + SYSTEM_OSC32K_STARTUP_2, + /** Wait 4 clock cycles until the clock source is considered stable */ + SYSTEM_OSC32K_STARTUP_4, + /** Wait 8 clock cycles until the clock source is considered stable */ + SYSTEM_OSC32K_STARTUP_8, + /** Wait 16 clock cycles until the clock source is considered stable */ + SYSTEM_OSC32K_STARTUP_16, + /** Wait 32 clock cycles until the clock source is considered stable */ + SYSTEM_OSC32K_STARTUP_32, + /** Wait 64 clock cycles until the clock source is considered stable */ + SYSTEM_OSC32K_STARTUP_64, + /** Wait 128 clock cycles until the clock source is considered stable */ + SYSTEM_OSC32K_STARTUP_128, +}; + +/** + * \brief Division prescalers for the internal 8MHz system clock + * + * Available prescalers for the internal 8MHz (nominal) system clock. + */ +enum system_osc8m_div { + /** Do not divide the 8MHz RC oscillator output */ + SYSTEM_OSC8M_DIV_1, + /** Divide the 8MHz RC oscillator output by 2 */ + SYSTEM_OSC8M_DIV_2, + /** Divide the 8MHz RC oscillator output by 4 */ + SYSTEM_OSC8M_DIV_4, + /** Divide the 8MHz RC oscillator output by 8 */ + SYSTEM_OSC8M_DIV_8, +}; + +/** + * \brief Main CPU and APB/AHB bus clock source prescaler values + * + * Available division ratios for the CPU and APB/AHB bus clocks. + */ +enum system_main_clock_div { + /** Divide Main clock by 1 */ + SYSTEM_MAIN_CLOCK_DIV_1, + /** Divide Main clock by 2 */ + SYSTEM_MAIN_CLOCK_DIV_2, + /** Divide Main clock by 4 */ + SYSTEM_MAIN_CLOCK_DIV_4, + /** Divide Main clock by 8 */ + SYSTEM_MAIN_CLOCK_DIV_8, + /** Divide Main clock by 16 */ + SYSTEM_MAIN_CLOCK_DIV_16, + /** Divide Main clock by 32 */ + SYSTEM_MAIN_CLOCK_DIV_32, + /** Divide Main clock by 64 */ + SYSTEM_MAIN_CLOCK_DIV_64, + /** Divide Main clock by 128 */ + SYSTEM_MAIN_CLOCK_DIV_128, +}; + +/** + * \brief External clock source types. + * + * Available external clock source types. + */ +enum system_clock_external { + /** The external clock source is a crystal oscillator */ + SYSTEM_CLOCK_EXTERNAL_CRYSTAL, + /** The connected clock source is an external logic level clock signal */ + SYSTEM_CLOCK_EXTERNAL_CLOCK, +}; + +/** + * \brief Operating modes of the DFLL clock source. + * + * Available operating modes of the DFLL clock source module, + */ +enum system_clock_dfll_loop_mode { + /** The DFLL is operating in open loop mode with no feedback */ + SYSTEM_CLOCK_DFLL_LOOP_MODE_OPEN, + /** The DFLL is operating in closed loop mode with frequency feedback from + * a low frequency reference clock + */ + SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED = SYSCTRL_DFLLCTRL_MODE, +}; + +/** + * \brief Locking behavior for the DFLL during device wake-up + * + * DFLL lock behavior modes on device wake-up from sleep. + */ +enum system_clock_dfll_wakeup_lock { + /** Keep DFLL lock when the device wakes from sleep */ + SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_KEEP, + /** Lose DFLL lock when the devices wakes from sleep */ + SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_LOSE = SYSCTRL_DFLLCTRL_LLAW, +}; + +/** + * \brief Fine tracking behavior for the DFLL once a lock has been acquired + * + * DFLL fine tracking behavior modes after a lock has been acquired. + */ +enum system_clock_dfll_stable_tracking { + /** Keep tracking after the DFLL has gotten a fine lock */ + SYSTEM_CLOCK_DFLL_STABLE_TRACKING_TRACK_AFTER_LOCK, + /** Stop tracking after the DFLL has gotten a fine lock */ + SYSTEM_CLOCK_DFLL_STABLE_TRACKING_FIX_AFTER_LOCK = SYSCTRL_DFLLCTRL_STABLE, +}; + +/** + * \brief Chill-cycle behavior of the DFLL module + * + * DFLL chill-cycle behavior modes of the DFLL module. A chill cycle is a period + * of time when the DFLL output frequency is not measured by the unit, to allow + * the output to stabilize after a change in the input clock source. + */ +enum system_clock_dfll_chill_cycle { + /** Enable a chill cycle, where the DFLL output frequency is not measured */ + SYSTEM_CLOCK_DFLL_CHILL_CYCLE_ENABLE, + /** Disable a chill cycle, where the DFLL output frequency is not measured */ + SYSTEM_CLOCK_DFLL_CHILL_CYCLE_DISABLE = SYSCTRL_DFLLCTRL_CCDIS, +}; + +/** + * \brief QuickLock settings for the DFLL module + * + * DFLL QuickLock settings for the DFLL module, to allow for a faster lock of + * the DFLL output frequency at the expense of accuracy. + */ +enum system_clock_dfll_quick_lock { + /** Enable the QuickLock feature for looser lock requirements on the DFLL */ + SYSTEM_CLOCK_DFLL_QUICK_LOCK_ENABLE, + /** Disable the QuickLock feature for strict lock requirements on the DFLL */ + SYSTEM_CLOCK_DFLL_QUICK_LOCK_DISABLE = SYSCTRL_DFLLCTRL_QLDIS, +}; + +/** + * \brief List of APB peripheral buses + * + * Available bus clock domains on the APB bus. + */ +enum system_clock_apb_bus { + /** Peripheral bus A on the APB bus. */ + SYSTEM_CLOCK_APB_APBA, + /** Peripheral bus B on the APB bus. */ + SYSTEM_CLOCK_APB_APBB, + /** Peripheral bus C on the APB bus. */ + SYSTEM_CLOCK_APB_APBC, +}; + +/** + * \brief Available clock sources in the system + * + * Clock sources available to the GCLK generators + */ +enum system_clock_source { + /** Internal 8MHz RC oscillator */ + SYSTEM_CLOCK_SOURCE_OSC8M = GCLK_SOURCE_OSC8M, + /** Internal 32kHz RC oscillator */ + SYSTEM_CLOCK_SOURCE_OSC32K = GCLK_SOURCE_OSC32K, + /** External oscillator */ + SYSTEM_CLOCK_SOURCE_XOSC = GCLK_SOURCE_XOSC , + /** External 32kHz oscillator */ + SYSTEM_CLOCK_SOURCE_XOSC32K = GCLK_SOURCE_XOSC32K, + /** Digital Frequency Locked Loop (DFLL) */ + SYSTEM_CLOCK_SOURCE_DFLL = GCLK_SOURCE_DFLL48M, + /** Internal Ultra Low Power 32kHz oscillator */ + SYSTEM_CLOCK_SOURCE_ULP32K = GCLK_SOURCE_OSCULP32K, +}; + +/** + * \brief Configuration structure for XOSC + * + * External oscillator clock configuration structure. + */ +struct system_clock_source_xosc_config { + /** External clock type */ + enum system_clock_external external_clock; + /** Crystal oscillator start-up time */ + enum system_xosc_startup startup_time; + /** Enable automatic amplitude gain control */ + bool auto_gain_control; + /** External clock/crystal frequency */ + uint32_t frequency; + /** Keep the XOSC enabled in standby sleep mode */ + bool run_in_standby; + /** Run On Demand. If this is set the XOSC won't run + * until requested by a peripheral */ + bool on_demand; +}; + +/** + * \brief Configuration structure for XOSC32K + * + * External 32KHz oscillator clock configuration structure. + */ +struct system_clock_source_xosc32k_config { + /** External clock type */ + enum system_clock_external external_clock; + /** Crystal oscillator start-up time */ + enum system_xosc32k_startup startup_time; + /** Enable automatic amplitude control */ + bool auto_gain_control; + /** Enable 1kHz output */ + bool enable_1khz_output; + /** Enable 32kHz output */ + bool enable_32khz_output; + /** External clock/crystal frequency */ + uint32_t frequency; + /** Keep the XOSC32K enabled in standby sleep mode */ + bool run_in_standby; + /** Run On Demand. If this is set the XOSC32K won't run + * until requested by a peripheral */ + bool on_demand; +}; + +/** + * \brief Configuration structure for OSC8M + * + * Internal 8MHz (nominal) oscillator configuration structure. + */ +struct system_clock_source_osc8m_config { + /* Internal 8MHz RC oscillator prescaler */ + enum system_osc8m_div prescaler; + /** Keep the OSC8M enabled in standby sleep mode */ + bool run_in_standby; + /** Run On Demand. If this is set the OSC8M won't run + * until requested by a peripheral */ + bool on_demand; +}; + +/** + * \brief Configuration structure for OSC32K + * + * Internal 32KHz (nominal) oscillator configuration structure. + */ +struct system_clock_source_osc32k_config { + /** Startup time */ + enum system_osc32k_startup startup_time; + /** Enable 1kHz output */ + bool enable_1khz_output; + /** Enable 32kHz output */ + bool enable_32khz_output; + /** Keep the OSC32K enabled in standby sleep mode */ + bool run_in_standby; + /** Run On Demand. If this is set the OSC32K won't run + * until requested by a peripheral */ + bool on_demand; +}; + +/** + * \brief Configuration structure for DFLL + * + * DFLL oscillator configuration structure. + */ +struct system_clock_source_dfll_config { + /** Loop mode */ + enum system_clock_dfll_loop_mode loop_mode; + /** Keep the DFLL enabled in standby sleep mode */ + bool run_in_standby; + /** Run On Demand. If this is set the DFLL won't run + * until requested by a peripheral */ + bool on_demand; + /** Enable Quick Lock */ + enum system_clock_dfll_quick_lock quick_lock; + /** Enable Chill Cycle */ + enum system_clock_dfll_chill_cycle chill_cycle; + /** DFLL lock state on wakeup */ + enum system_clock_dfll_wakeup_lock wakeup_lock; + /** DFLL tracking after fine lock */ + enum system_clock_dfll_stable_tracking stable_tracking; + /** Coarse calibration value (Open loop mode) */ + uint8_t coarse_value; + /** Fine calibration value (Open loop mode) */ + uint8_t fine_value; + /** Coarse adjustment max step size (Closed loop mode) */ + uint8_t coarse_max_step; + /** Fine adjustment max step size (Closed loop mode) */ + uint8_t fine_max_step; + /** DFLL multiply factor (Closed loop mode */ + uint16_t multiply_factor; +}; + +/** + * \name External Oscillator management + * @{ + */ + +/** + * \brief Retrieve the default configuration for XOSC + * + * Fills a configuration structure with the default configuration for an + * external oscillator module: + * - External Crystal + * - Start-up time of 16384 external clock cycles + * - Automatic crystal gain control mode enabled + * - Frequency of 12MHz + * - Don't run in STANDBY sleep mode + * - Run only when requested by peripheral (on demand) + * + * \param[out] config Configuration structure to fill with default values + */ +static inline void system_clock_source_xosc_get_config_defaults( + struct system_clock_source_xosc_config *const config) +{ + Assert(config); + + config->external_clock = SYSTEM_CLOCK_EXTERNAL_CRYSTAL; + config->startup_time = SYSTEM_XOSC_STARTUP_16384; + config->auto_gain_control = true; + config->frequency = 12000000UL; + config->run_in_standby = false; + config->on_demand = true; +} + +void system_clock_source_xosc_set_config( + struct system_clock_source_xosc_config *const config); + +/** + * @} + */ + + +/** + * \name External 32KHz Oscillator management + * @{ + */ + +/** + * \brief Retrieve the default configuration for XOSC32K + * + * Fills a configuration structure with the default configuration for an + * external 32KHz oscillator module: + * - External Crystal + * - Start-up time of 16384 external clock cycles + * - Automatic crystal gain control mode enabled + * - Frequency of 32.768KHz + * - 1KHz clock output disabled + * - 32KHz clock output enabled + * - Don't run in STANDBY sleep mode + * - Run only when requested by peripheral (on demand) + * + * \param[out] config Configuration structure to fill with default values + */ +static inline void system_clock_source_xosc32k_get_config_defaults( + struct system_clock_source_xosc32k_config *const config) +{ + Assert(config); + + config->external_clock = SYSTEM_CLOCK_EXTERNAL_CRYSTAL; + config->startup_time = SYSTEM_XOSC32K_STARTUP_16384; + config->auto_gain_control = true; + config->frequency = 32768UL; + config->enable_1khz_output = false; + config->enable_32khz_output = true; + config->run_in_standby = false; + config->on_demand = true; +} + +void system_clock_source_xosc32k_set_config( + struct system_clock_source_xosc32k_config *const config); +/** + * @} + */ + + +/** + * \name Internal 32KHz Oscillator management + * @{ + */ + +/** + * \brief Retrieve the default configuration for OSC32K + * + * Fills a configuration structure with the default configuration for an + * internal 32KHz oscillator module: + * - 1KHz clock output enabled + * - 32KHz clock output enabled + * - Don't run in STANDBY sleep mode + * - Run only when requested by peripheral (on demand) + * + * \param[out] config Configuration structure to fill with default values + */ +static inline void system_clock_source_osc32k_get_config_defaults( + struct system_clock_source_osc32k_config *const config) +{ + Assert(config); + + config->enable_1khz_output = true; + config->enable_32khz_output = true; + config->run_in_standby = false; + config->on_demand = true; +} + +void system_clock_source_osc32k_set_config( + struct system_clock_source_osc32k_config *const config); + +/** + * @} + */ + + +/** + * \name Internal 8MHz Oscillator management + * @{ + */ + +/** + * \brief Retrieve the default configuration for OSC8M + * + * Fills a configuration structure with the default configuration for an + * internal 8MHz (nominal) oscillator module: + * - Clock output frequency divided by a factor of 8 + * - Don't run in STANDBY sleep mode + * - Run only when requested by peripheral (on demand) + * + * \param[out] config Configuration structure to fill with default values + */ +static inline void system_clock_source_osc8m_get_config_defaults( + struct system_clock_source_osc8m_config *const config) +{ + Assert(config); + + config->prescaler = SYSTEM_OSC8M_DIV_8; + config->run_in_standby = false; + config->on_demand = true; +} + +void system_clock_source_osc8m_set_config( + struct system_clock_source_osc8m_config *const config); + +/** + * @} + */ + + +/** + * \name Internal DFLL management + * @{ + */ + +/** + * \brief Retrieve the default configuration for DFLL + * + * Fills a configuration structure with the default configuration for a + * DFLL oscillator module: + * - Open loop mode + * - QuickLock mode enabled + * - Chill cycle enabled + * - Output frequency lock maintained during device wake-up + * - Continuous tracking of the output frequency + * - Default tracking values at the mid-points for both coarse and fine + * tracking parameters + * - Don't run in STANDBY sleep mode + * - Run only when requested by peripheral (on demand) + * + * \param[out] config Configuration structure to fill with default values + */ +static inline void system_clock_source_dfll_get_config_defaults( + struct system_clock_source_dfll_config *const config) +{ + Assert(config); + + config->loop_mode = SYSTEM_CLOCK_DFLL_LOOP_MODE_OPEN; + config->quick_lock = SYSTEM_CLOCK_DFLL_QUICK_LOCK_ENABLE; + config->chill_cycle = SYSTEM_CLOCK_DFLL_CHILL_CYCLE_ENABLE; + config->wakeup_lock = SYSTEM_CLOCK_DFLL_WAKEUP_LOCK_KEEP; + config->stable_tracking = SYSTEM_CLOCK_DFLL_STABLE_TRACKING_TRACK_AFTER_LOCK; + config->run_in_standby = false; + config->on_demand = true; + + /* Open loop mode calibration value */ + config->coarse_value = 0x1f / 4; /* Midpoint */ + config->fine_value = 0xff / 4; /* Midpoint */ + + /* Closed loop mode */ + config->coarse_max_step = 1; + config->fine_max_step = 1; + config->multiply_factor = 6; /* Multiply 8MHz by 6 to get 48MHz */ +} + +void system_clock_source_dfll_set_config( + struct system_clock_source_dfll_config *const config); + +/** + * @} + */ + +/** + * \name Clock source management + * @{ + */ +enum status_code system_clock_source_write_calibration( + const enum system_clock_source system_clock_source, + const uint16_t calibration_value, + const uint8_t freq_range); + +enum status_code system_clock_source_enable( + const enum system_clock_source system_clock_source); + +enum status_code system_clock_source_disable( + const enum system_clock_source clk_source); + +bool system_clock_source_is_ready( + const enum system_clock_source clk_source); + +uint32_t system_clock_source_get_hz( + const enum system_clock_source clk_source); + +/** + * @} + */ + +/** + * \name Main clock management + * @{ + */ + +/** + * \brief Enable or disable the main clock failure detection. + * + * This mechanism allows switching automatically the main clock to the safe + * RCSYS clock, when the main clock source is considered off. + * + * This may happen for instance when an external crystal is selected as the + * clock source of the main clock and the crystal dies. The mechanism is to + * detect, during a RCSYS period, at least one rising edge of the main clock. + * If no rising edge is seen the clock is considered failed. + * As soon as the detector is enabled, the clock failure detector + * CFD) will monitor the divided main clock. When a clock failure is detected, + * the main clock automatically switches to the RCSYS clock and the CFD + * interrupt is generated if enabled. + * + * \note The failure detect must be disabled if the system clock is the same or + * slower than 32kHz as it will believe the system clock has failed with + * a too-slow clock. + * + * \param[in] enable Boolean \c true to enable, \c false to disable detection + */ +static inline void system_main_clock_set_failure_detect( + const bool enable) +{ + if (enable) { + PM->CTRL.reg |= PM_CTRL_CFDEN; + } else { + PM->CTRL.reg &= ~PM_CTRL_CFDEN; + } +} + +/** + * \brief Set main CPU clock divider. + * + * Sets the clock divider used on the main clock to provide the CPU clock. + * + * \param[in] divider CPU clock divider to set + */ +static inline void system_cpu_clock_set_divider( + const enum system_main_clock_div divider) +{ + Assert(((uint32_t)divider & PM_CPUSEL_CPUDIV_Msk) == divider); + PM->CPUSEL.reg = (uint32_t)divider; +} + +/** + * \brief Retrieves the current frequency of the CPU core. + * + * Retrieves the operating frequency of the CPU core, obtained from the main + * generic clock and the set CPU bus divider. + * + * \return Current CPU frequency in Hz. + */ +static inline uint32_t system_cpu_clock_get_hz(void) +{ + return (system_gclk_gen_get_hz(GCLK_GENERATOR_0) >> PM->CPUSEL.reg); +} + +/** + * \brief Set APBx clock divider. + * + * Set the clock divider used on the main clock to provide the clock for the + * given APBx bus. + * + * \param[in] divider APBx bus divider to set + * \param[in] bus APBx bus to set divider for + * + * \returns Status of the clock division change operation. + * + * \retval STATUS_ERR_INVALID_ARG Invalid bus ID was given + * \retval STATUS_OK The APBx clock was set successfully + */ +static inline enum status_code system_apb_clock_set_divider( + const enum system_clock_apb_bus bus, + const enum system_main_clock_div divider) +{ + switch (bus) { + case SYSTEM_CLOCK_APB_APBA: + PM->APBASEL.reg = (uint32_t)divider; + break; + case SYSTEM_CLOCK_APB_APBB: + PM->APBBSEL.reg = (uint32_t)divider; + break; + case SYSTEM_CLOCK_APB_APBC: + PM->APBCSEL.reg = (uint32_t)divider; + break; + default: + Assert(false); + return STATUS_ERR_INVALID_ARG; + } + + return STATUS_OK; +} + +/** + * \brief Retrieves the current frequency of a ABPx. + * + * Retrieves the operating frequency of an APBx bus, obtained from the main + * generic clock and the set APBx bus divider. + * + * \return Current APBx bus frequency in Hz. + */ +static inline uint32_t system_apb_clock_get_hz( + const enum system_clock_apb_bus bus) +{ + uint16_t bus_divider = 0; + + switch (bus) { + case SYSTEM_CLOCK_APB_APBA: + bus_divider = PM->APBASEL.reg; + break; + case SYSTEM_CLOCK_APB_APBB: + bus_divider = PM->APBBSEL.reg; + break; + case SYSTEM_CLOCK_APB_APBC: + bus_divider = PM->APBCSEL.reg; + break; + default: + Assert(false); + return 0; + } + + return (system_gclk_gen_get_hz(GCLK_GENERATOR_0) >> bus_divider); +} + + +/** + * @} + */ + +/** + * \name Bus clock masking + * @{ + */ + +/** + * \brief Set bits in the clock mask for the AHB bus. + * + * This function will set bits in the clock mask for the AHB bus. + * Any bits set to 1 will enable that clock, 0 bits in the mask + * will be ignored + * + * \param[in] ahb_mask AHB clock mask to enable + */ +static inline void system_ahb_clock_set_mask( + const uint32_t ahb_mask) +{ + PM->AHBMASK.reg |= ahb_mask; +} + +/** + * \brief Clear bits in the clock mask for the AHB bus. + * + * This function will clear bits in the clock mask for the AHB bus. + * Any bits set to 1 will disable that clock, 0 bits in the mask + * will be ignored. + * + * \param[in] ahb_mask AHB clock mask to disable + */ +static inline void system_ahb_clock_clear_mask( + const uint32_t ahb_mask) +{ + PM->AHBMASK.reg &= ~ahb_mask; +} + +/** + * \brief Set bits in the clock mask for an APBx bus. + * + * This function will set bits in the clock mask for an APBx bus. + * Any bits set to 1 will enable the corresponding module clock, zero bits in + * the mask will be ignored. + * + * \param[in] mask APBx clock mask, a \c SYSTEM_CLOCK_APB_APBx constant from + * the device header files + * \param[in] bus Bus to set clock mask bits for, a mask of \c PM_APBxMASK_* + * constants from the device header files + * + * \returns Status indicating the result of the clock mask change operation. + * + * \retval STATUS_ERR_INVALID_ARG Invalid bus given + * \retval STATUS_OK The clock mask was set successfully + */ +static inline enum status_code system_apb_clock_set_mask( + const enum system_clock_apb_bus bus, + const uint32_t mask) +{ + switch (bus) { + case SYSTEM_CLOCK_APB_APBA: + PM->APBAMASK.reg |= mask; + break; + + case SYSTEM_CLOCK_APB_APBB: + PM->APBBMASK.reg |= mask; + break; + + case SYSTEM_CLOCK_APB_APBC: + PM->APBCMASK.reg |= mask; + break; + + default: + Assert(false); + return STATUS_ERR_INVALID_ARG; + + } + + return STATUS_OK; +} + +/** + * \brief Clear bits in the clock mask for an APBx bus. + * + * This function will clear bits in the clock mask for an APBx bus. + * Any bits set to 1 will disable the corresponding module clock, zero bits in + * the mask will be ignored. + * + * \param[in] mask APBx clock mask, a \c SYSTEM_CLOCK_APB_APBx constant from + * the device header files + * \param[in] bus Bus to clear clock mask bits for + * + * \returns Status indicating the result of the clock mask change operation. + * + * \retval STATUS_ERR_INVALID_ARG Invalid bus ID was given. + * \retval STATUS_OK The clock mask was changed successfully. + */ +static inline enum status_code system_apb_clock_clear_mask( + const enum system_clock_apb_bus bus, + const uint32_t mask) +{ + switch (bus) { + case SYSTEM_CLOCK_APB_APBA: + PM->APBAMASK.reg &= ~mask; + break; + + case SYSTEM_CLOCK_APB_APBB: + PM->APBBMASK.reg &= ~mask; + break; + + case SYSTEM_CLOCK_APB_APBC: + PM->APBCMASK.reg &= ~mask; + break; + + default: + Assert(false); + return STATUS_ERR_INVALID_ARG; + } + + return STATUS_OK; +} + +/** + * @} + */ + +/** + * \name System Clock Initialization + * @{ + */ + +void system_clock_init(void); + +/** + * @} + */ + +/** + * \name System Flash Wait States + * @{ + */ + +/** + * \brief Set flash controller wait states + * + * Will set the number of wait states that are used by the onboard + * flash memory. The number of wait states depend on both device + * supply voltage and CPU speed. The required number of wait states + * can be found in the electrical characteristics of the device. + * + * \param[in] wait_states Number of wait states to use for internal flash + */ +static inline void system_flash_set_waitstates(uint8_t wait_states) +{ + Assert((wait_states & NVMCTRL_CTRLB_RWS_Msk) == wait_states); + NVMCTRL->CTRLB.bit.RWS = wait_states; +} +/** + * @} + */ + +/** + * @} + */ + +/** + * \page asfdoc_samd20_system_clock_extra Extra Information for SYSTEM CLOCK Driver + * + * \section asfdoc_samd20_system_clock_extra_acronyms Acronyms + * Below is a table listing the acronyms used in this module, along with their + * intended meanings. + * + * <table> + * <tr> + * <th>Acronym</th> + * <th>Description</th> + * </tr> + * <tr> + * <td>DFLL</td> + * <td>Digital Frequency Locked Loop</td> + * </tr> + * <tr> + * <td>MUX</td> + * <td>Multiplexer</td> + * </tr> + * <tr> + * <td>OSC32K</td> + * <td>Internal 32KHz Oscillator</td> + * </tr> + * <tr> + * <td>OSC8M</td> + * <td>Internal 8MHz Oscillator</td> + * </tr> + * <tr> + * <td>PLL</td> + * <td>Phase Locked Loop</td> + * </tr> + * <tr> + * <td>OSC</td> + * <td>Oscillator</td> + * </tr> + * <tr> + * <td>XOSC</td> + * <td>External Oscillator</td> + * </tr> + * <tr> + * <td>XOSC32K</td> + * <td>External 32KHz Oscillator</td> + * </tr> + * <tr> + * <td>AHB</td> + * <td>Advanced High-performance Bus</td> + * </tr> + * <tr> + * <td>APB</td> + * <td>Advanced Peripheral Bus</td> + * </tr> + * </table> + * + * + * \section asfdoc_samd20_system_clock_extra_dependencies Dependencies + * This driver has the following dependencies: + * + * - None + * + * + * \section asfdoc_samd20_system_clock_extra_errata Errata + * <tr> + * <td> + * \li This driver implements workaround for errata 10558 + * "Several reset values of SYSCTRL.INTFLAG are wrong (BOD and DFLL)"<br> + * When system_init is called it will reset these interrupts flags before they are used. + * </td> + * </tr> + * + * <tr> + * <td> + * \li This driver implements experimental workaround for errata 9905<br> + * "The DFLL clock must be requested before being configured otherwise a + * write access to a DFLL register can freeze the device."<br> + * This driver will enable and configure the DFLL before the ONDEMAND bit is set. + * </td> + * </tr> + * + * + * + * \section asfdoc_samd20_system_clock_extra_history Module History + * An overview of the module history is presented in the table below, with + * details on the enhancements and fixes made to the module since its first + * release. The current version of this corresponds to the newest version in + * the table. + * + * <table> + * <tr> + * <th>Changelog</th> + * </tr> + * <tr> + * <td> + * \li Changed default value for CONF_CLOCK_DFLL_ON_DEMAND from true to false + * </td> + * </tr> + * <tr> + * <td>\li Updated dfll configuration function to implement workaround for errata 9905 in the DFLL module. + * \li Updated \c system_clock_init() to reset interrupt flags before they are used, errata 10558. + * \li Fixed \c system_clock_source_get_hz() to return correcy DFLL frequency number. + * </td> + * </tr> + * <tr> + * <td>\li Fixed \c system_clock_source_is_ready not returning the correct + * state for \c SYSTEM_CLOCK_SOURCE_OSC8M. + * \li Renamed the various \c system_clock_source_*_get_default_config() + * functions to \c system_clock_source_*_get_config_defaults() to + * match the remainder of ASF. + * \li Added OSC8M calibration constant loading from the device signature + * row when the oscillator is initialized.</td> + * </tr> + * <tr> + * <td>Initial Release</td> + * </tr> + * </table> + */ + +/** + * \page asfdoc_samd20_system_clock_exqsg Examples for System Clock Driver + * + * This is a list of the available Quick Start guides (QSGs) and example + * applications for \ref asfdoc_samd20_system_clock_group. QSGs are simple + * examples with step-by-step instructions to configure and use this driver in + * a selection of use cases. Note that QSGs can be compiled as a standalone + * application or be added to the user application. + * + * - \subpage asfdoc_samd20_system_clock_basic_use_case + * - \subpage asfdoc_samd20_system_gclk_basic_use_case + * + * \page asfdoc_samd20_system_clock_document_revision_history Document Revision History + * + * <table> + * <tr> + * <th>Doc. Rev.</td> + * <th>Date</td> + * <th>Comments</td> + * </tr> + * <tr> + * <td>B</td> + * <td>06/2013</td> + * <td>Corrected documentation typos.</td> + * </tr> + * <tr> + * <td>A</td> + * <td>06/2013</td> + * <td>Initial release</td> + * </tr> + * </table> + */ + +#endif /* SYSTEM_CLOCK_H_INCLUDED */
diff --git a/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock_config_check.h b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock_config_check.h new file mode 100644 index 0000000..0181f77 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/clock_config_check.h
@@ -0,0 +1,383 @@ +/** + * \file + * + * \brief SAM D20 Clock Driver + * + * Copyright (C) 2012-2013 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#ifndef CLOCK_CONFIG_CHECK_H +# define CLOCK_CONFIG_CHECK_H + +#if !defined(CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT) +# error CONF_CLOCK_CPU_CLOCK_FAILURE_DETECT not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_FLASH_WAIT_STATES) +# error CONF_CLOCK_FLASH_WAIT_STATES not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_CPU_DIVIDER) +# error CONF_CLOCK_CPU_DIVIDER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_APBA_DIVIDER) +# error CONF_CLOCK_APBA_DIVIDER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_APBB_DIVIDER) +# error CONF_CLOCK_APBB_DIVIDER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_OSC8M_PRESCALER) +# error CONF_CLOCK_OSC8M_PRESCALER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_OSC8M_ON_DEMAND) +# error CONF_CLOCK_OSC8M_ON_DEMAND not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_OSC8M_RUN_IN_STANDBY) +# error CONF_CLOCK_OSC8M_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC_ENABLE) +# error CONF_CLOCK_XOSC_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL) +# error CONF_CLOCK_XOSC_EXTERNAL_CRYSTAL not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY) +# error CONF_CLOCK_XOSC_EXTERNAL_FREQUENCY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC_STARTUP_TIME) +# error CONF_CLOCK_XOSC_STARTUP_TIME not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL) +# error CONF_CLOCK_XOSC_AUTO_GAIN_CONTROL not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC_ON_DEMAND) +# error CONF_CLOCK_XOSC_ON_DEMAND not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC_RUN_IN_STANDBY) +# error CONF_CLOCK_XOSC_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC32K_ENABLE) +# error CONF_CLOCK_XOSC32K_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL) +# error CONF_CLOCK_XOSC32K_EXTERNAL_CRYSTAL not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC32K_STARTUP_TIME) +# error CONF_CLOCK_XOSC32K_STARTUP_TIME not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC32K_AUTO_AMPLITUDE_CONTROL) +# error CONF_CLOCK_XOSC32K_AUTO_AMPLITUDE_CONTROL not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT) +# error CONF_CLOCK_XOSC32K_ENABLE_1KHZ_OUPUT not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT) +# error CONF_CLOCK_XOSC32K_ENABLE_32KHZ_OUTPUT not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC32K_ON_DEMAND) +# error CONF_CLOCK_XOSC32K_ON_DEMAND not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_XOSC32K_RUN_IN_STANDBY) +# error CONF_CLOCK_XOSC32K_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_OSC32K_ENABLE) +# error CONF_CLOCK_OSC32K_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_OSC32K_STARTUP_TIME) +# error CONF_CLOCK_OSC32K_STARTUP_TIME not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT) +# error CONF_CLOCK_OSC32K_ENABLE_1KHZ_OUTPUT not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT) +# error CONF_CLOCK_OSC32K_ENABLE_32KHZ_OUTPUT not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_OSC32K_ON_DEMAND) +# error CONF_CLOCK_OSC32K_ON_DEMAND not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_OSC32K_RUN_IN_STANDBY) +# error CONF_CLOCK_OSC32K_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_ENABLE) +# error CONF_CLOCK_DFLL_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_LOOP_MODE) +# error CONF_CLOCK_DFLL_LOOP_MODE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_ON_DEMAND) +# error CONF_CLOCK_DFLL_ON_DEMAND not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_RUN_IN_STANDBY) +# error CONF_CLOCK_DFLL_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_COARSE_VALUE) +# error CONF_CLOCK_DFLL_COARSE_VALUE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_FINE_VALUE) +# error CONF_CLOCK_DFLL_FINE_VALUE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR) +# error CONF_CLOCK_DFLL_SOURCE_GCLK_GENERATOR not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_MULTIPLY_FACTOR) +# error CONF_CLOCK_DFLL_MULTIPLY_FACTOR not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_QUICK_LOCK) +# error CONF_CLOCK_DFLL_QUICK_LOCK not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK) +# error CONF_CLOCK_DFLL_TRACK_AFTER_FINE_LOCK not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP) +# error CONF_CLOCK_DFLL_KEEP_LOCK_ON_WAKEUP not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE) +# error CONF_CLOCK_DFLL_ENABLE_CHILL_CYCLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE) +# error CONF_CLOCK_DFLL_MAX_COARSE_STEP_SIZE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE) +# error CONF_CLOCK_DFLL_MAX_FINE_STEP_SIZE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_CONFIGURE_GCLK) +# error CONF_CLOCK_CONFIGURE_GCLK not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_0_ENABLE) +# error CONF_CLOCK_GCLK_0_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_0_RUN_IN_STANDBY) +# error CONF_CLOCK_GCLK_0_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_0_CLOCK_SOURCE) +# error CONF_CLOCK_GCLK_0_CLOCK_SOURCE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_0_PRESCALER) +# error CONF_CLOCK_GCLK_0_PRESCALER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_0_OUTPUT_ENABLE) +# error CONF_CLOCK_GCLK_0_OUTPUT_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_1_ENABLE) +# error CONF_CLOCK_GCLK_1_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_1_RUN_IN_STANDBY) +# error CONF_CLOCK_GCLK_1_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_1_CLOCK_SOURCE) +# error CONF_CLOCK_GCLK_1_CLOCK_SOURCE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_1_PRESCALER) +# error CONF_CLOCK_GCLK_1_PRESCALER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_1_OUTPUT_ENABLE) +# error CONF_CLOCK_GCLK_1_OUTPUT_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_2_ENABLE) +# error CONF_CLOCK_GCLK_2_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_2_RUN_IN_STANDBY) +# error CONF_CLOCK_GCLK_2_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_2_CLOCK_SOURCE) +# error CONF_CLOCK_GCLK_2_CLOCK_SOURCE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_2_PRESCALER) +# error CONF_CLOCK_GCLK_2_PRESCALER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_2_OUTPUT_ENABLE) +# error CONF_CLOCK_GCLK_2_OUTPUT_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_3_ENABLE) +# error CONF_CLOCK_GCLK_3_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_3_RUN_IN_STANDBY) +# error CONF_CLOCK_GCLK_3_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_3_CLOCK_SOURCE) +# error CONF_CLOCK_GCLK_3_CLOCK_SOURCE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_3_PRESCALER) +# error CONF_CLOCK_GCLK_3_PRESCALER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_3_OUTPUT_ENABLE) +# error CONF_CLOCK_GCLK_3_OUTPUT_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_4_ENABLE) +# error CONF_CLOCK_GCLK_4_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_4_RUN_IN_STANDBY) +# error CONF_CLOCK_GCLK_4_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_4_CLOCK_SOURCE) +# error CONF_CLOCK_GCLK_4_CLOCK_SOURCE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_4_PRESCALER) +# error CONF_CLOCK_GCLK_4_PRESCALER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_4_OUTPUT_ENABLE) +# error CONF_CLOCK_GCLK_4_OUTPUT_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_5_ENABLE) +# error CONF_CLOCK_GCLK_5_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_5_RUN_IN_STANDBY) +# error CONF_CLOCK_GCLK_5_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_5_CLOCK_SOURCE) +# error CONF_CLOCK_GCLK_5_CLOCK_SOURCE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_5_PRESCALER) +# error CONF_CLOCK_GCLK_5_PRESCALER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_5_OUTPUT_ENABLE) +# error CONF_CLOCK_GCLK_5_OUTPUT_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_6_ENABLE) +# error CONF_CLOCK_GCLK_6_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_6_RUN_IN_STANDBY) +# error CONF_CLOCK_GCLK_6_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_6_CLOCK_SOURCE) +# error CONF_CLOCK_GCLK_6_CLOCK_SOURCE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_6_PRESCALER) +# error CONF_CLOCK_GCLK_6_PRESCALER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_6_OUTPUT_ENABLE) +# error CONF_CLOCK_GCLK_6_OUTPUT_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_7_ENABLE) +# error CONF_CLOCK_GCLK_7_ENABLE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_7_RUN_IN_STANDBY) +# error CONF_CLOCK_GCLK_7_RUN_IN_STANDBY not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_7_CLOCK_SOURCE) +# error CONF_CLOCK_GCLK_7_CLOCK_SOURCE not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_7_PRESCALER) +# error CONF_CLOCK_GCLK_7_PRESCALER not defined in conf_clock.h +#endif + +#if !defined(CONF_CLOCK_GCLK_7_OUTPUT_ENABLE) +# error CONF_CLOCK_GCLK_7_OUTPUT_ENABLE not defined in conf_clock.h +#endif + +#endif /* CLOCK_CONFIG_CHECK_H */
diff --git a/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/gclk.c b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/gclk.c new file mode 100644 index 0000000..9d2cd44 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/gclk.c
@@ -0,0 +1,392 @@ +/** + * \file + * + * \brief SAM D20 Generic Clock Driver + * + * Copyright (C) 2012-2013 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +#include <gclk.h> +#include <clock.h> +#include <system_interrupt.h> + +/** + * \brief Initializes the GCLK driver. + * + * Initializes the Generic Clock module, disabling and resetting all active + * Generic Clock Generators and Channels to their power-on default values. + */ +void system_gclk_init(void) +{ + /* Turn on the digital interface clock */ + system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBA, PM_APBAMASK_GCLK); + + /* Software reset the module to ensure it is re-initialized correctly */ + GCLK->CTRL.reg = GCLK_CTRL_SWRST; + while (GCLK->CTRL.reg & GCLK_CTRL_SWRST) { + /* Wait for reset to complete */ + } +} + +/** + * \brief Writes a Generic Clock Generator configuration to the hardware module. + * + * Writes out a given configuration of a Generic Clock Generator configuration + * to the hardware module. + * + * \note Changing the clock source on the fly (on a running + * generator) can take additional time if the clock source is configured + * to only run on-demand (ONDEMAND bit is set) and it is not currently + * running (no peripheral is requesting the clock source). In this case + * the GCLK will request the new clock while still keeping a request to + * the old clock source until the new clock source is ready. + * + * \note This function will not start a generator that is not already running; + * to start the generator, call \ref system_gclk_gen_enable() + * after configuring a generator. + * + * \param[in] generator Generic Clock Generator index to configure + * \param[in] config Configuration settings for the generator + */ +void system_gclk_gen_set_config( + const uint8_t generator, + struct system_gclk_gen_config *const config) +{ + /* Sanity check arguments */ + Assert(config); + + /* Cache new register configurations to minimize sync requirements. */ + uint32_t new_genctrl_config = (generator << GCLK_GENCTRL_ID_Pos); + uint32_t new_gendiv_config = (generator << GCLK_GENDIV_ID_Pos); + + /* Select the requested source clock for the generator */ + new_genctrl_config |= config->source_clock << GCLK_GENCTRL_SRC_Pos; + + /* Configure the clock to be either high or low when disabled */ + if (config->high_when_disabled) { + new_genctrl_config |= GCLK_GENCTRL_OOV; + } + + /* Configure if the clock output to I/O pin should be enabled. */ + if (config->output_enable) { + new_genctrl_config |= GCLK_GENCTRL_OE; + } + + /* Set division factor */ + if (config->division_factor > 1) { + /* Check if division is a power of two */ + if (((config->division_factor & (config->division_factor - 1)) == 0)) { + /* Determine the index of the highest bit set to get the + * division factor that must be loaded into the division + * register */ + + uint32_t div2_count = 0; + + uint32_t mask; + for (mask = (1UL << 1); mask < config->division_factor; + mask <<= 1) { + div2_count++; + } + + /* Set binary divider power of 2 division factor */ + new_gendiv_config |= div2_count << GCLK_GENDIV_DIV_Pos; + new_genctrl_config |= GCLK_GENCTRL_DIVSEL; + } else { + /* Set integer division factor */ + + new_gendiv_config |= + (config->division_factor) << GCLK_GENDIV_DIV_Pos; + + /* Enable non-binary division with increased duty cycle accuracy */ + new_genctrl_config |= GCLK_GENCTRL_IDC; + } + + } + + /* Enable or disable the clock in standby mode */ + if (config->run_in_standby) { + new_genctrl_config |= GCLK_GENCTRL_RUNSTDBY; + } + + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + + system_interrupt_enter_critical_section(); + + /* Select the correct generator */ + *((uint8_t*)&GCLK->GENDIV.reg) = generator; + + /* Write the new generator configuration */ + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + GCLK->GENDIV.reg = new_gendiv_config; + + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + GCLK->GENCTRL.reg = new_genctrl_config | (GCLK->GENCTRL.reg & GCLK_GENCTRL_GENEN); + + system_interrupt_leave_critical_section(); +} + +/** + * \brief Enables a Generic Clock Generator that was previously configured. + * + * Starts the clock generation of a Generic Clock Generator that was previously + * configured via a call to \ref system_gclk_gen_set_config(). + * + * \param[in] generator Generic Clock Generator index to enable + */ +void system_gclk_gen_enable( + const uint8_t generator) +{ + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + + system_interrupt_enter_critical_section(); + + /* Select the requested generator */ + *((uint8_t*)&GCLK->GENCTRL.reg) = generator; + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + + /* Enable generator */ + GCLK->GENCTRL.reg |= GCLK_GENCTRL_GENEN; + + system_interrupt_leave_critical_section(); +} + +/** + * \brief Disables a Generic Clock Generator that was previously enabled. + * + * Stops the clock generation of a Generic Clock Generator that was previously + * started via a call to \ref system_gclk_gen_enable(). + * + * \param[in] generator Generic Clock Generator index to disable + */ +void system_gclk_gen_disable( + const uint8_t generator) +{ + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + + system_interrupt_enter_critical_section(); + + /* Select the requested generator */ + *((uint8_t*)&GCLK->GENCTRL.reg) = generator; + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + + /* Disable generator */ + GCLK->GENCTRL.reg &= ~GCLK_GENCTRL_GENEN; + while (GCLK->GENCTRL.reg & GCLK_GENCTRL_GENEN) { + /* Wait for clock to become disabled */ + } + + system_interrupt_leave_critical_section(); +} + +/** + * \brief Retrieves the clock frequency of a Generic Clock generator. + * + * Determines the clock frequency (in Hz) of a specified Generic Clock + * generator, used as a source to a Generic Clock Channel module. + * + * \param[in] generator Generic Clock Generator index + * + * \return The frequency of the generic clock generator, in Hz. + */ +uint32_t system_gclk_gen_get_hz( + const uint8_t generator) +{ + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + + system_interrupt_enter_critical_section(); + + /* Select the appropriate generator */ + *((uint8_t*)&GCLK->GENCTRL.reg) = generator; + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + + /* Get the frequency of the source connected to the GCLK generator */ + uint32_t gen_input_hz = system_clock_source_get_hz( + (enum system_clock_source)GCLK->GENCTRL.bit.SRC); + + *((uint8_t*)&GCLK->GENCTRL.reg) = generator; + + uint8_t divsel = GCLK->GENCTRL.bit.DIVSEL; + + /* Select the appropriate generator division register */ + *((uint8_t*)&GCLK->GENDIV.reg) = generator; + while (system_gclk_is_syncing()) { + /* Wait for synchronization */ + }; + + uint32_t divider = GCLK->GENDIV.bit.DIV; + + system_interrupt_leave_critical_section(); + + /* Check if the generator is using fractional or binary division */ + if (!divsel && divider > 1) { + gen_input_hz /= divider; + } else if (divsel) { + gen_input_hz >>= (divider+1); + } + + return gen_input_hz; +} + +/** + * \brief Writes a Generic Clock configuration to the hardware module. + * + * Writes out a given configuration of a Generic Clock configuration to the + * hardware module. If the clock is currently running, it will be stopped. + * + * \note Once called the clock will not be running; to start the clock, + * call \ref system_gclk_chan_enable() after configuring a clock channel. + * + * \param[in] channel Generic Clock channel to configure + * \param[in] config Configuration settings for the clock + */ +void system_gclk_chan_set_config( + const uint8_t channel, + struct system_gclk_chan_config *const config) +{ + /* Sanity check arguments */ + Assert(config); + + /* Cache the new config to reduce sync requirements */ + uint32_t new_clkctrl_config = (channel << GCLK_CLKCTRL_ID_Pos); + + /* Select the desired generic clock generator */ + new_clkctrl_config |= config->source_generator << GCLK_CLKCTRL_GEN_Pos; + + /* Enable write lock if requested to prevent further modification */ + if (config->write_lock) { + new_clkctrl_config |= GCLK_CLKCTRL_WRTLOCK; + } + + /* Disable generic clock channel */ + system_gclk_chan_disable(channel); + + /* Write the new configuration */ + GCLK->CLKCTRL.reg = new_clkctrl_config; +} + +/** + * \brief Enables a Generic Clock that was previously configured. + * + * Starts the clock generation of a Generic Clock that was previously + * configured via a call to \ref system_gclk_chan_set_config(). + * + * \param[in] channel Generic Clock channel to enable + */ +void system_gclk_chan_enable( + const uint8_t channel) +{ + system_interrupt_enter_critical_section(); + + /* Select the requested generator channel */ + *((uint8_t*)&GCLK->CLKCTRL.reg) = channel; + + /* Enable the generic clock */ + GCLK->CLKCTRL.reg |= GCLK_CLKCTRL_CLKEN; + + system_interrupt_leave_critical_section(); +} + +/** + * \brief Disables a Generic Clock that was previously enabled. + * + * Stops the clock generation of a Generic Clock that was previously started + * via a call to \ref system_gclk_chan_enable(). + * + * \param[in] channel Generic Clock channel to disable + */ +void system_gclk_chan_disable( + const uint8_t channel) +{ + system_interrupt_enter_critical_section(); + + /* Select the requested generator channel */ + *((uint8_t*)&GCLK->CLKCTRL.reg) = channel; + + /* Disable the generic clock */ + GCLK->CLKCTRL.reg &= ~GCLK_CLKCTRL_CLKEN; + while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN) { + /* Wait for clock to become disabled */ + } + + system_interrupt_leave_critical_section(); +} + +/** + * \brief Retrieves the clock frequency of a Generic Clock channel. + * + * Determines the clock frequency (in Hz) of a specified Generic Clock + * channel, used as a source to a device peripheral module. + * + * \param[in] channel Generic Clock Channel index + * + * \return The frequency of the generic clock channel, in Hz. + */ +uint32_t system_gclk_chan_get_hz( + const uint8_t channel) +{ + uint8_t gen_id; + + system_interrupt_enter_critical_section(); + + /* Select the requested generic clock channel */ + *((uint8_t*)&GCLK->CLKCTRL.reg) = channel; + gen_id = GCLK->CLKCTRL.bit.GEN; + + system_interrupt_leave_critical_section(); + + /* Return the clock speed of the associated GCLK generator */ + return system_gclk_gen_get_hz(gen_id); +}
diff --git a/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/gclk.h b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/gclk.h new file mode 100644 index 0000000..c334a4a --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/gclk.h
@@ -0,0 +1,314 @@ +/** + * \file + * + * \brief SAM D20 Generic Clock Driver + * + * Copyright (C) 2012-2013 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ +#ifndef SYSTEM_CLOCK_GCLK_H_INCLUDED +#define SYSTEM_CLOCK_GCLK_H_INCLUDED + +/** + * \addtogroup asfdoc_samd20_system_clock_group + * + * @{ + */ + +#include <compiler.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief List of available GCLK generators. + * + * List of Available GCLK generators. This enum is used in the peripheral + * device drivers to select the GCLK generator to be used for its operation. + * + * The number of GCLK generators available is device dependent. + */ +enum gclk_generator { + /** GCLK generator channel 0. */ + GCLK_GENERATOR_0, +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 0) + /** GCLK generator channel 1. */ + GCLK_GENERATOR_1, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 1) + /** GCLK generator channel 2. */ + GCLK_GENERATOR_2, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 2) + /** GCLK generator channel 3. */ + GCLK_GENERATOR_3, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 3) + /** GCLK generator channel 4. */ + GCLK_GENERATOR_4, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 4) + /** GCLK generator channel 5. */ + GCLK_GENERATOR_5, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 5) + /** GCLK generator channel 6. */ + GCLK_GENERATOR_6, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 6) + /** GCLK generator channel 7. */ + GCLK_GENERATOR_7, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 7) + /** GCLK generator channel 8. */ + GCLK_GENERATOR_8, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 8) + /** GCLK generator channel 9. */ + GCLK_GENERATOR_9, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 9) + /** GCLK generator channel 10. */ + GCLK_GENERATOR_10, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 10) + /** GCLK generator channel 11. */ + GCLK_GENERATOR_11, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 11) + /** GCLK generator channel 12. */ + GCLK_GENERATOR_12, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 12) + /** GCLK generator channel 13. */ + GCLK_GENERATOR_13, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 13) + /** GCLK generator channel 14. */ + GCLK_GENERATOR_14, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 14) + /** GCLK generator channel 15. */ + GCLK_GENERATOR_15, +#endif +#if defined(__DOXYGEN__) || (GCLK_GEN_NUM_MSB > 15) + /** GCLK generator channel 16. */ + GCLK_GENERATOR_16, +#endif +}; + +/** + * \brief Generic Clock Generator configuration structure. + * + * Configuration structure for a Generic Clock Generator channel. This + * structure should be initialized by the + * \ref system_gclk_gen_get_config_defaults() function before being modified by + * the user application. + */ +struct system_gclk_gen_config { + /** Source clock input channel index. */ + uint8_t source_clock; + /** If \c true, the generator output level is high when disabled. */ + bool high_when_disabled; + /** Integer division factor of the clock output compared to the input. */ + uint32_t division_factor; + /** If \c true, the clock is kept enabled during device standby mode. */ + bool run_in_standby; + /** If \c true, enables GCLK generator clock output to a GPIO pin. */ + bool output_enable; +}; + +/** + * \brief Generic Clock configuration structure. + * + * Configuration structure for a Generic Clock channel. This structure + * should be initialized by the \ref system_gclk_chan_get_config_defaults() + * function before being modified by the user application. + */ +struct system_gclk_chan_config { + /** Generic Clock Generator source channel. */ + enum gclk_generator source_generator; + /** If \c true the clock configuration will be locked until the device is + * reset. */ + bool write_lock; +}; + +/** \name Generic Clock management + * @{ + */ + +/** + * \brief Determines if the hardware module(s) are currently synchronizing to the bus. + * + * Checks to see if the underlying hardware peripheral module(s) are currently + * synchronizing across multiple clock domains to the hardware bus, This + * function can be used to delay further operations on a module until such time + * that it is ready, to prevent blocking delays for synchronization in the + * user application. + * + * \return Synchronization status of the underlying hardware module(s). + * + * \retval true if the module has completed synchronization + * \retval false if the module synchronization is ongoing + */ +static inline bool system_gclk_is_syncing(void) +{ + if (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) { + return true; + } + + return false; +} + +void system_gclk_init(void); + +/** @} */ + + +/** + * \name Generic Clock management (Generators) + * @{ + */ + +/** + * \brief Initializes a Generic Clock Generator configuration structure to defaults. + * + * Initializes a given Generic Clock Generator configuration structure to + * a set of known default values. This function should be called on all + * new instances of these configuration structures before being modified + * by the user application. + * + * The default configuration is as follows: + * \li Clock is generated undivided from the source frequency + * \li Clock generator output is low when the generator is disabled + * \li The input clock is sourced from input clock channel 0 + * \li Clock will be disabled during sleep + * \li The clock output will not be routed to a physical GPIO pin + * + * \param[out] config Configuration structure to initialize to default values + */ +static inline void system_gclk_gen_get_config_defaults( + struct system_gclk_gen_config *const config) +{ + /* Sanity check arguments */ + Assert(config); + + /* Default configuration values */ + config->division_factor = 1; + config->high_when_disabled = false; + config->source_clock = GCLK_SOURCE_OSC8M; + config->run_in_standby = false; + config->output_enable = false; +} + +void system_gclk_gen_set_config( + const uint8_t generator, + struct system_gclk_gen_config *const config); + +void system_gclk_gen_enable( + const uint8_t generator); + +void system_gclk_gen_disable( + const uint8_t generator); + +/** @} */ + + +/** + * \name Generic Clock management (Channels) + * @{ + */ + +/** + * \brief Initializes a Generic Clock configuration structure to defaults. + * + * Initializes a given Generic Clock configuration structure to a set of + * known default values. This function should be called on all new + * instances of these configuration structures before being modified by the + * user application. + * + * The default configuration is as follows: + * \li Clock is sourced from the Generic Clock Generator channel 0 + * \li Clock configuration will not be write-locked when set + * + * \param[out] config Configuration structure to initialize to default values + */ +static inline void system_gclk_chan_get_config_defaults( + struct system_gclk_chan_config *const config) +{ + /* Sanity check arguments */ + Assert(config); + + /* Default configuration values */ + config->source_generator = GCLK_GENERATOR_0; + config->write_lock = false; +} + +void system_gclk_chan_set_config( + const uint8_t channel, + struct system_gclk_chan_config *const config); + +void system_gclk_chan_enable( + const uint8_t channel); + +void system_gclk_chan_disable( + const uint8_t channel); + +/** @} */ + + +/** + * \name Generic Clock frequency retrieval + * @{ + */ + +uint32_t system_gclk_gen_get_hz( + const uint8_t generator); + +uint32_t system_gclk_chan_get_hz( + const uint8_t channel); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +/** @} */ + +#endif
diff --git a/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/quick_start_clock/qs_clock_source.h b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/quick_start_clock/qs_clock_source.h new file mode 100644 index 0000000..b20af38 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/quick_start_clock/qs_clock_source.h
@@ -0,0 +1,125 @@ +/** + * \file + * + * \brief SAM D20 System Clock Driver Quick Start + * + * Copyright (C) 2012-2013 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + */ + +/** + * \page asfdoc_samd20_system_clock_basic_use_case Quick Start Guide for SYSTEM CLOCK - Basic + * + * In this case we apply the following configuration: + * - RC8MHz (internal 8MHz RC oscillator) + * - Divide by 4, giving a frequency of 2MHz + * - DFLL (Digital frequency locked loop) + * - Open loop mode + * - 48MHz frequency + * - CPU clock + * - Use the DFLL, configured to 48MHz + * + * \section asfdoc_samd20_system_clock_basic_use_case_setup Setup + * + * \subsection asfdoc_samd20_system_clock_basic_use_case_setup_prereq Prerequisites + * There are no special setup requirements for this use-case. + * + * \subsection asfdoc_samd20_system_clock_basic_use_case_setup_code Code + * Copy-paste the following setup code to your application: + * \snippet qs_clock_source.c setup + * + * \subsection asfdoc_samd20_system_clock_basic_use_case_setup_flow Workflow + * -# Create a EXTOSC32K module configuration struct, which can be filled + * out to adjust the configuration of the external 32KHz oscillator channel. + * \snippet qs_clock_source.c config_extosc32k_config + * + * -# Initialize the oscillator configuration struct with the module's default + * values. + * \note This should always be performed before using the configuration + * struct to ensure that all values are initialized to known default + * settings. + * + * \snippet qs_clock_source.c config_extosc32k_get_defaults + * + * -# Alter the EXTOSC32K module configuration struct to require a start-up time + * of 4096 clock cycles. + * \snippet qs_clock_source.c config_extosc32k_change_defaults + * + * -# Write the new configuration to the EXTOSC32K module. + * \snippet qs_clock_source.c config_extosc32k_set_config + * + * -# Create a DFLL module configuration struct, which can be filled + * out to adjust the configuration of the external 32KHz oscillator channel. + * \snippet qs_clock_source.c config_dfll_config + * + * -# Initialize the DFLL oscillator configuration struct with the module's + * default values. + * \note This should always be performed before using the configuration + * struct to ensure that all values are initialized to known default + * settings. + * + * \snippet qs_clock_source.c config_dfll_get_defaults + * + * -# Write the new configuration to the DFLL module. + * \snippet qs_clock_source.c config_extosc32k_set_config + + + * \section asfdoc_samd20_system_clock_basic_use_case_use_main Use Case + * + * \subsection asfdoc_samd20_system_clock_basic_use_case_code Code + * + * Copy-paste the following code to your user application: + * \snippet qs_clock_source.c main + * + * \subsection asfdoc_samd20_system_clock_basic_use_case_flow Workflow + * -# Configure the external 32KHz oscillator source using the previously + * defined setup function. + * \snippet qs_clock_source.c config_extosc32k_main + * + * -# Enable the configured external 32KHz oscillator source. + * \snippet qs_clock_source.c enable_extosc32k_main + * + * -# Configure the DFLL oscillator source using the previously defined setup + * function. + * \snippet qs_clock_source.c config_dfll_main + * + * -# Enable the configured DFLL oscillator source. + * \snippet qs_clock_source.c enable_dfll_main + * + * -# Switch the system clock source to the DFLL, by reconfiguring the main + * clock generator. + * \snippet qs_clock_source.c set_sys_clk_src + */
diff --git a/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/quick_start_gclk/qs_gclk_basic.h b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/quick_start_gclk/qs_gclk_basic.h new file mode 100644 index 0000000..787df91 --- /dev/null +++ b/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOSDemo/src/ASF/sam0/drivers/system/clock/quick_start_gclk/qs_gclk_basic.h
@@ -0,0 +1,126 @@ +/** + * \file + * + * \brief SAM D20 Generic Clock Driver Quick Start + * + * Copyright (C) 2012-2013 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + +/** + * \page asfdoc_samd20_system_gclk_basic_use_case Quick Start Guide for SYSTEM CLOCK - GCLK Configuration + * + * In this use case, the GCLK module is configured for: + * \li One generator attached to the internal 8MHz RC oscillator clock source + * \li Generator output equal to input frequency divided by a factor of 128 + * \li One channel (connected to the TC0 module) enabled with the enabled generator selected + * + * This use case configures a clock channel to output a clock for a peripheral + * within the device, by first setting up a clock generator from a master clock + * source, and then linking the generator to the desired channel. This clock + * can then be used to clock a module within the device. + * + * \section asfdoc_samd20_system_gclk_basic_use_case_setup Setup + * + * \subsection asfdoc_samd20_system_gclk_basic_use_case_setup_prereq Prerequisites + * There are no special setup requirements for this use-case. + * + * \subsection asfdoc_samd20_system_gclk_basic_use_case_setup_code Code + * Copy-paste the following setup code to your user application: + * \snippet qs_gclk_basic.c setup + * + * Add to user application initialization (typically the start of \c main()): + * \snippet qs_gclk_basic.c setup_init + * + * \subsection asfdoc_samd20_system_gclk_basic_use_case_setup_flow Workflow + * -# Create a GCLK generator configuration struct, which can be filled out to + * adjust the configuration of a single clock generator. + * \snippet qs_gclk_basic.c setup_1 + * -# Initialize the generator configuration struct with the module's default + * values. + * \note This should always be performed before using the configuration + * struct to ensure that all values are initialized to known default + * settings. + * + * \snippet qs_gclk_basic.c setup_2 + * -# Adjust the configuration struct to request that the master clock source + * channel 0 be used as the source of the generator, and set the generator + * output prescaler to divide the input clock by a factor of 128. + * \snippet qs_gclk_basic.c setup_3 + * -# Configure the generator using the configuration structure. + * \note The existing configuration struct may be re-used, as long as any + * values that have been altered from the default settings are taken + * into account by the user application. + * + * \snippet qs_gclk_basic.c setup_4 + * -# Enable the generator once it has been properly configured, to begin clock + * generation. + * \snippet qs_gclk_basic.c setup_5 + * + * -# Create a GCLK channel configuration struct, which can be filled out to + * adjust the configuration of a single generic clock channel. + * \snippet qs_gclk_basic.c setup_6 + * -# Initialize the channel configuration struct with the module's default + * values. + * \note This should always be performed before using the configuration + * struct to ensure that all values are initialized to known default + * settings. + * + * \snippet qs_gclk_basic.c setup_7 + * -# Adjust the configuration struct to request that the previously configured + * and enabled clock generator be used as the clock source for the channel. + * \snippet qs_gclk_basic.c setup_8 + * -# Configure the channel using the configuration structure. + * \note The existing configuration struct may be re-used, as long as any + * values that have been altered from the default settings are taken + * into account by the user application. + * + * \snippet qs_gclk_basic.c setup_9 + * -# Enable the channel once it has been properly configured, to output the + * clock to the channel's peripheral module consumers. + * \snippet qs_gclk_basic.c setup_10 + * + * \section asfdoc_samd20_system_gclk_basic_use_case_main Use Case + * + * \subsection asfdoc_samd20_system_gclk_basic_use_case_code Code + * Copy-paste the following code to your user application: + * \snippet qs_gclk_basic.c main + * + * \subsection asfdoc_samd20_system_gclk_basic_use_case_flow Workflow + * -# As the clock is generated asynchronously to the system core, no special + * extra application code is required. + */