Added example MS/TP port to ATxmega XPLAINED A3BU evaluation board.
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Generic clock management
|
||||
*
|
||||
* Copyright (c) 2010-2012 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 CLK_GENCLK_H_INCLUDED
|
||||
#define CLK_GENCLK_H_INCLUDED
|
||||
|
||||
#include "parts.h"
|
||||
|
||||
#if SAM3S
|
||||
# include "sam3s/genclk.h"
|
||||
#elif SAM3U
|
||||
# include "sam3u/genclk.h"
|
||||
#elif SAM3N
|
||||
# include "sam3n/genclk.h"
|
||||
#elif SAM3XA
|
||||
# include "sam3x/genclk.h"
|
||||
#elif SAM4S
|
||||
# include "sam4s/genclk.h"
|
||||
#elif SAM4L
|
||||
# include "sam4l/genclk.h"
|
||||
#elif SAM4E
|
||||
# include "sam4e/genclk.h"
|
||||
#elif (UC3A0 || UC3A1)
|
||||
# include "uc3a0_a1/genclk.h"
|
||||
#elif UC3A3
|
||||
# include "uc3a3_a4/genclk.h"
|
||||
#elif UC3B
|
||||
# include "uc3b0_b1/genclk.h"
|
||||
#elif UC3C
|
||||
# include "uc3c/genclk.h"
|
||||
#elif UC3D
|
||||
# include "uc3d/genclk.h"
|
||||
#elif UC3L
|
||||
# include "uc3l/genclk.h"
|
||||
#else
|
||||
# error Unsupported chip type
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup clk_group
|
||||
* \defgroup genclk_group Generic Clock Management
|
||||
*
|
||||
* Generic clocks are configurable clocks which run outside the system
|
||||
* clock domain. They are often connected to peripherals which have an
|
||||
* asynchronous component running independently of the bus clock, e.g.
|
||||
* USB controllers, low-power timers and RTCs, etc.
|
||||
*
|
||||
* Note that not all platforms have support for generic clocks; on such
|
||||
* platforms, this API will not be available.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def GENCLK_DIV_MAX
|
||||
* \brief Maximum divider supported by the generic clock implementation
|
||||
*/
|
||||
/**
|
||||
* \enum genclk_source
|
||||
* \brief Generic clock source ID
|
||||
*
|
||||
* Each generic clock may be generated from a different clock source.
|
||||
* These are the available alternatives provided by the chip.
|
||||
*/
|
||||
|
||||
//! \name Generic clock configuration
|
||||
//@{
|
||||
/**
|
||||
* \struct genclk_config
|
||||
* \brief Hardware representation of a set of generic clock parameters
|
||||
*/
|
||||
/**
|
||||
* \fn void genclk_config_defaults(struct genclk_config *cfg,
|
||||
* unsigned int id)
|
||||
* \brief Initialize \a cfg to the default configuration for the clock
|
||||
* identified by \a id.
|
||||
*/
|
||||
/**
|
||||
* \fn void genclk_config_read(struct genclk_config *cfg, unsigned int id)
|
||||
* \brief Read the currently active configuration of the clock
|
||||
* identified by \a id into \a cfg.
|
||||
*/
|
||||
/**
|
||||
* \fn void genclk_config_write(const struct genclk_config *cfg,
|
||||
* unsigned int id)
|
||||
* \brief Activate the configuration \a cfg on the clock identified by
|
||||
* \a id.
|
||||
*/
|
||||
/**
|
||||
* \fn void genclk_config_set_source(struct genclk_config *cfg,
|
||||
* enum genclk_source src)
|
||||
* \brief Select a new source clock \a src in configuration \a cfg.
|
||||
*/
|
||||
/**
|
||||
* \fn void genclk_config_set_divider(struct genclk_config *cfg,
|
||||
* unsigned int divider)
|
||||
* \brief Set a new \a divider in configuration \a cfg.
|
||||
*/
|
||||
/**
|
||||
* \fn void genclk_enable_source(enum genclk_source src)
|
||||
* \brief Enable the source clock \a src used by a generic clock.
|
||||
*/
|
||||
//@}
|
||||
|
||||
//! \name Enabling and disabling Generic Clocks
|
||||
//@{
|
||||
/**
|
||||
* \fn void genclk_enable(const struct genclk_config *cfg, unsigned int id)
|
||||
* \brief Activate the configuration \a cfg on the clock identified by
|
||||
* \a id and enable it.
|
||||
*/
|
||||
/**
|
||||
* \fn void genclk_disable(unsigned int id)
|
||||
* \brief Disable the generic clock identified by \a id.
|
||||
*/
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \brief Enable the configuration defined by \a src and \a divider
|
||||
* for the generic clock identified by \a id.
|
||||
*
|
||||
* \param id The ID of the generic clock.
|
||||
* \param src The source clock of the generic clock.
|
||||
* \param divider The divider used to generate the generic clock.
|
||||
*/
|
||||
static inline void
|
||||
genclk_enable_config (unsigned int id, enum genclk_source src,
|
||||
unsigned int divider)
|
||||
{
|
||||
struct genclk_config gcfg;
|
||||
|
||||
genclk_config_defaults (&gcfg, id);
|
||||
genclk_enable_source (src);
|
||||
genclk_config_set_source (&gcfg, src);
|
||||
genclk_config_set_divider (&gcfg, divider);
|
||||
genclk_enable (&gcfg, id);
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
#endif /* CLK_GENCLK_H_INCLUDED */
|
||||
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Oscillator management
|
||||
*
|
||||
* Copyright (c) 2010-2012 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 OSC_H_INCLUDED
|
||||
#define OSC_H_INCLUDED
|
||||
|
||||
#include "parts.h"
|
||||
#include "conf_clock.h"
|
||||
|
||||
#if SAM3S
|
||||
# include "sam3s/osc.h"
|
||||
#elif SAM3XA
|
||||
# include "sam3x/osc.h"
|
||||
#elif SAM3U
|
||||
# include "sam3u/osc.h"
|
||||
#elif SAM3N
|
||||
# include "sam3n/osc.h"
|
||||
#elif SAM4S
|
||||
# include "sam4s/osc.h"
|
||||
#elif SAM4E
|
||||
# include "sam4e/osc.h"
|
||||
#elif SAM4L
|
||||
# include "sam4l/osc.h"
|
||||
#elif (UC3A0 || UC3A1)
|
||||
# include "uc3a0_a1/osc.h"
|
||||
#elif UC3A3
|
||||
# include "uc3a3_a4/osc.h"
|
||||
#elif UC3B
|
||||
# include "uc3b0_b1/osc.h"
|
||||
#elif UC3C
|
||||
# include "uc3c/osc.h"
|
||||
#elif UC3D
|
||||
# include "uc3d/osc.h"
|
||||
#elif UC3L
|
||||
# include "uc3l/osc.h"
|
||||
#elif XMEGA
|
||||
# include "xmega/osc.h"
|
||||
#else
|
||||
# error Unsupported chip type
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup clk_group
|
||||
* \defgroup osc_group Oscillator Management
|
||||
*
|
||||
* This group contains functions and definitions related to configuring
|
||||
* and enabling/disabling on-chip oscillators. Internal RC-oscillators,
|
||||
* external crystal oscillators and external clock generators are
|
||||
* supported by this module. What all of these have in common is that
|
||||
* they swing at a fixed, nominal frequency which is normally not
|
||||
* adjustable.
|
||||
*
|
||||
* \par Example: Enabling an oscillator
|
||||
*
|
||||
* The following example demonstrates how to enable the external
|
||||
* oscillator on XMEGA A and wait for it to be ready to use. The
|
||||
* oscillator identifiers are platform-specific, so while the same
|
||||
* procedure is used on all platforms, the parameter to osc_enable()
|
||||
* will be different from device to device.
|
||||
* \code
|
||||
osc_enable(OSC_ID_XOSC);
|
||||
osc_wait_ready(OSC_ID_XOSC); \endcode
|
||||
*
|
||||
* \section osc_group_board Board-specific Definitions
|
||||
* If external oscillators are used, the board code must provide the
|
||||
* following definitions for each of those:
|
||||
* - \b BOARD_<osc name>_HZ: The nominal frequency of the oscillator.
|
||||
* - \b BOARD_<osc name>_STARTUP_US: The startup time of the
|
||||
* oscillator in microseconds.
|
||||
* - \b BOARD_<osc name>_TYPE: The type of oscillator connected, i.e.
|
||||
* whether it's a crystal or external clock, and sometimes what kind
|
||||
* of crystal it is. The meaning of this value is platform-specific.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name Oscillator Management
|
||||
//@{
|
||||
/**
|
||||
* \fn void osc_enable(uint8_t id)
|
||||
* \brief Enable oscillator \a id
|
||||
*
|
||||
* The startup time and mode value is automatically determined based on
|
||||
* definitions in the board code.
|
||||
*/
|
||||
/**
|
||||
* \fn void osc_disable(uint8_t id)
|
||||
* \brief Disable oscillator \a id
|
||||
*/
|
||||
/**
|
||||
* \fn osc_is_ready(uint8_t id)
|
||||
* \brief Determine whether oscillator \a id is ready.
|
||||
* \retval true Oscillator \a id is running and ready to use as a clock
|
||||
* source.
|
||||
* \retval false Oscillator \a id is not running.
|
||||
*/
|
||||
/**
|
||||
* \fn uint32_t osc_get_rate(uint8_t id)
|
||||
* \brief Return the frequency of oscillator \a id in Hz
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/**
|
||||
* \brief Wait until the oscillator identified by \a id is ready
|
||||
*
|
||||
* This function will busy-wait for the oscillator identified by \a id
|
||||
* to become stable and ready to use as a clock source.
|
||||
*
|
||||
* \param id A number identifying the oscillator to wait for.
|
||||
*/
|
||||
static inline void
|
||||
osc_wait_ready (uint8_t id)
|
||||
{
|
||||
while (!osc_is_ready (id))
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
//@}
|
||||
|
||||
//! @}
|
||||
|
||||
#endif /* OSC_H_INCLUDED */
|
||||
@@ -0,0 +1,322 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief PLL management
|
||||
*
|
||||
* Copyright (c) 2010-2012 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 CLK_PLL_H_INCLUDED
|
||||
#define CLK_PLL_H_INCLUDED
|
||||
|
||||
#include "parts.h"
|
||||
#include "conf_clock.h"
|
||||
|
||||
#if SAM3S
|
||||
# include "sam3s/pll.h"
|
||||
#elif SAM3XA
|
||||
# include "sam3x/pll.h"
|
||||
#elif SAM3U
|
||||
# include "sam3u/pll.h"
|
||||
#elif SAM3N
|
||||
# include "sam3n/pll.h"
|
||||
#elif SAM4S
|
||||
# include "sam4s/pll.h"
|
||||
#elif SAM4E
|
||||
# include "sam4e/pll.h"
|
||||
#elif SAM4L
|
||||
# include "sam4l/pll.h"
|
||||
#elif (UC3A0 || UC3A1)
|
||||
# include "uc3a0_a1/pll.h"
|
||||
#elif UC3A3
|
||||
# include "uc3a3_a4/pll.h"
|
||||
#elif UC3B
|
||||
# include "uc3b0_b1/pll.h"
|
||||
#elif UC3C
|
||||
# include "uc3c/pll.h"
|
||||
#elif UC3D
|
||||
# include "uc3d/pll.h"
|
||||
#elif (UC3L0128 || UC3L0256 || UC3L3_L4)
|
||||
# include "uc3l/pll.h"
|
||||
#elif XMEGA
|
||||
# include "xmega/pll.h"
|
||||
#else
|
||||
# error Unsupported chip type
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \ingroup clk_group
|
||||
* \defgroup pll_group PLL Management
|
||||
*
|
||||
* This group contains functions and definitions related to configuring
|
||||
* and enabling/disabling on-chip PLLs. A PLL will take an input signal
|
||||
* (the \em source), optionally divide the frequency by a configurable
|
||||
* \em divider, and then multiply the frequency by a configurable \em
|
||||
* multiplier.
|
||||
*
|
||||
* Some devices don't support input dividers; specifying any other
|
||||
* divisor than 1 on these devices will result in an assertion failure.
|
||||
* Other devices may have various restrictions to the frequency range of
|
||||
* the input and output signals.
|
||||
*
|
||||
* \par Example: Setting up PLL0 with default parameters
|
||||
*
|
||||
* The following example shows how to configure and enable PLL0 using
|
||||
* the default parameters specified using the configuration symbols
|
||||
* listed above.
|
||||
* \code
|
||||
pll_enable_config_defaults(0); \endcode
|
||||
*
|
||||
* To configure, enable PLL0 using the default parameters and to disable
|
||||
* a specific feature like Wide Bandwidth Mode (a UC3A3-specific
|
||||
* PLL option.), you can use this initialization process.
|
||||
* \code
|
||||
struct pll_config pllcfg;
|
||||
if (pll_is_locked(pll_id)) {
|
||||
return; // Pll already running
|
||||
}
|
||||
pll_enable_source(CONFIG_PLL0_SOURCE);
|
||||
pll_config_defaults(&pllcfg, 0);
|
||||
pll_config_set_option(&pllcfg, PLL_OPT_WBM_DISABLE);
|
||||
pll_enable(&pllcfg, 0);
|
||||
pll_wait_for_lock(0); \endcode
|
||||
*
|
||||
* When the last function call returns, PLL0 is ready to be used as the
|
||||
* main system clock source.
|
||||
*
|
||||
* \section pll_group_config Configuration Symbols
|
||||
*
|
||||
* Each PLL has a set of default parameters determined by the following
|
||||
* configuration symbols in the application's configuration file:
|
||||
* - \b CONFIG_PLLn_SOURCE: The default clock source connected to the
|
||||
* input of PLL \a n. Must be one of the values defined by the
|
||||
* #pll_source enum.
|
||||
* - \b CONFIG_PLLn_MUL: The default multiplier (loop divider) of PLL
|
||||
* \a n.
|
||||
* - \b CONFIG_PLLn_DIV: The default input divider of PLL \a n.
|
||||
*
|
||||
* These configuration symbols determine the result of calling
|
||||
* pll_config_defaults() and pll_get_default_rate().
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name Chip-specific PLL characteristics
|
||||
//@{
|
||||
/**
|
||||
* \def PLL_MAX_STARTUP_CYCLES
|
||||
* \brief Maximum PLL startup time in number of slow clock cycles
|
||||
*/
|
||||
/**
|
||||
* \def NR_PLLS
|
||||
* \brief Number of on-chip PLLs
|
||||
*/
|
||||
|
||||
/**
|
||||
* \def PLL_MIN_HZ
|
||||
* \brief Minimum frequency that the PLL can generate
|
||||
*/
|
||||
/**
|
||||
* \def PLL_MAX_HZ
|
||||
* \brief Maximum frequency that the PLL can generate
|
||||
*/
|
||||
/**
|
||||
* \def PLL_NR_OPTIONS
|
||||
* \brief Number of PLL option bits
|
||||
*/
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \enum pll_source
|
||||
* \brief PLL clock source
|
||||
*/
|
||||
|
||||
//! \name PLL configuration
|
||||
//@{
|
||||
|
||||
/**
|
||||
* \struct pll_config
|
||||
* \brief Hardware-specific representation of PLL configuration.
|
||||
*
|
||||
* This structure contains one or more device-specific values
|
||||
* representing the current PLL configuration. The contents of this
|
||||
* structure is typically different from platform to platform, and the
|
||||
* user should not access any fields except through the PLL
|
||||
* configuration API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \fn void pll_config_init(struct pll_config *cfg,
|
||||
* enum pll_source src, unsigned int div, unsigned int mul)
|
||||
* \brief Initialize PLL configuration from standard parameters.
|
||||
*
|
||||
* \note This function may be defined inline because it is assumed to be
|
||||
* called very few times, and usually with constant parameters. Inlining
|
||||
* it will in such cases reduce the code size significantly.
|
||||
*
|
||||
* \param cfg The PLL configuration to be initialized.
|
||||
* \param src The oscillator to be used as input to the PLL.
|
||||
* \param div PLL input divider.
|
||||
* \param mul PLL loop divider (i.e. multiplier).
|
||||
*
|
||||
* \return A configuration which will make the PLL run at
|
||||
* (\a mul / \a div) times the frequency of \a src
|
||||
*/
|
||||
/**
|
||||
* \def pll_config_defaults(cfg, pll_id)
|
||||
* \brief Initialize PLL configuration using default parameters.
|
||||
*
|
||||
* After this function returns, \a cfg will contain a configuration
|
||||
* which will make the PLL run at (CONFIG_PLLx_MUL / CONFIG_PLLx_DIV)
|
||||
* times the frequency of CONFIG_PLLx_SOURCE.
|
||||
*
|
||||
* \param cfg The PLL configuration to be initialized.
|
||||
* \param pll_id Use defaults for this PLL.
|
||||
*/
|
||||
/**
|
||||
* \def pll_get_default_rate(pll_id)
|
||||
* \brief Get the default rate in Hz of \a pll_id
|
||||
*/
|
||||
/**
|
||||
* \fn void pll_config_set_option(struct pll_config *cfg,
|
||||
* unsigned int option)
|
||||
* \brief Set the PLL option bit \a option in the configuration \a cfg.
|
||||
*
|
||||
* \param cfg The PLL configuration to be changed.
|
||||
* \param option The PLL option bit to be set.
|
||||
*/
|
||||
/**
|
||||
* \fn void pll_config_clear_option(struct pll_config *cfg,
|
||||
* unsigned int option)
|
||||
* \brief Clear the PLL option bit \a option in the configuration \a cfg.
|
||||
*
|
||||
* \param cfg The PLL configuration to be changed.
|
||||
* \param option The PLL option bit to be cleared.
|
||||
*/
|
||||
/**
|
||||
* \fn void pll_config_read(struct pll_config *cfg, unsigned int pll_id)
|
||||
* \brief Read the currently active configuration of \a pll_id.
|
||||
*
|
||||
* \param cfg The configuration object into which to store the currently
|
||||
* active configuration.
|
||||
* \param pll_id The ID of the PLL to be accessed.
|
||||
*/
|
||||
/**
|
||||
* \fn void pll_config_write(const struct pll_config *cfg,
|
||||
* unsigned int pll_id)
|
||||
* \brief Activate the configuration \a cfg on \a pll_id
|
||||
*
|
||||
* \param cfg The configuration object representing the PLL
|
||||
* configuration to be activated.
|
||||
* \param pll_id The ID of the PLL to be updated.
|
||||
*/
|
||||
|
||||
//@}
|
||||
|
||||
//! \name Interaction with the PLL hardware
|
||||
//@{
|
||||
/**
|
||||
* \fn void pll_enable(const struct pll_config *cfg,
|
||||
* unsigned int pll_id)
|
||||
* \brief Activate the configuration \a cfg and enable PLL \a pll_id.
|
||||
*
|
||||
* \param cfg The PLL configuration to be activated.
|
||||
* \param pll_id The ID of the PLL to be enabled.
|
||||
*/
|
||||
/**
|
||||
* \fn void pll_disable(unsigned int pll_id)
|
||||
* \brief Disable the PLL identified by \a pll_id.
|
||||
*
|
||||
* After this function is called, the PLL identified by \a pll_id will
|
||||
* be disabled. The PLL configuration stored in hardware may be affected
|
||||
* by this, so if the caller needs to restore the same configuration
|
||||
* later, it should either do a pll_config_read() before disabling the
|
||||
* PLL, or remember the last configuration written to the PLL.
|
||||
*
|
||||
* \param pll_id The ID of the PLL to be disabled.
|
||||
*/
|
||||
/**
|
||||
* \fn bool pll_is_locked(unsigned int pll_id)
|
||||
* \brief Determine whether the PLL is locked or not.
|
||||
*
|
||||
* \param pll_id The ID of the PLL to check.
|
||||
*
|
||||
* \retval true The PLL is locked and ready to use as a clock source
|
||||
* \retval false The PLL is not yet locked, or has not been enabled.
|
||||
*/
|
||||
/**
|
||||
* \fn void pll_enable_source(enum pll_source src)
|
||||
* \brief Enable the source of the pll.
|
||||
* The source is enabled, if the source is not already running.
|
||||
*
|
||||
* \param src The ID of the PLL source to enable.
|
||||
*/
|
||||
/**
|
||||
* \fn void pll_enable_config_defaults(unsigned int pll_id)
|
||||
* \brief Enable the pll with the default configuration.
|
||||
* PLL is enabled, if the PLL is not already locked.
|
||||
*
|
||||
* \param pll_id The ID of the PLL to enable.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Wait for PLL \a pll_id to become locked
|
||||
*
|
||||
* \todo Use a timeout to avoid waiting forever and hanging the system
|
||||
*
|
||||
* \param pll_id The ID of the PLL to wait for.
|
||||
*
|
||||
* \retval STATUS_OK The PLL is now locked.
|
||||
* \retval ERR_TIMEOUT Timed out waiting for PLL to become locked.
|
||||
*/
|
||||
static inline int
|
||||
pll_wait_for_lock (unsigned int pll_id)
|
||||
{
|
||||
Assert (pll_id < NR_PLLS);
|
||||
|
||||
while (!pll_is_locked (pll_id))
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//@}
|
||||
//! @}
|
||||
|
||||
#endif /* CLK_PLL_H_INCLUDED */
|
||||
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief System clock management
|
||||
*
|
||||
* Copyright (c) 2010-2012 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 SYSCLK_H_INCLUDED
|
||||
#define SYSCLK_H_INCLUDED
|
||||
|
||||
#include "parts.h"
|
||||
#include "conf_clock.h"
|
||||
|
||||
#if SAM3S
|
||||
# include "sam3s/sysclk.h"
|
||||
#elif SAM3U
|
||||
# include "sam3u/sysclk.h"
|
||||
#elif SAM3N
|
||||
# include "sam3n/sysclk.h"
|
||||
#elif SAM3XA
|
||||
# include "sam3x/sysclk.h"
|
||||
#elif SAM4S
|
||||
# include "sam4s/sysclk.h"
|
||||
#elif SAM4E
|
||||
# include "sam4e/sysclk.h"
|
||||
#elif SAM4L
|
||||
# include "sam4l/sysclk.h"
|
||||
#elif (UC3A0 || UC3A1)
|
||||
# include "uc3a0_a1/sysclk.h"
|
||||
#elif UC3A3
|
||||
# include "uc3a3_a4/sysclk.h"
|
||||
#elif UC3B
|
||||
# include "uc3b0_b1/sysclk.h"
|
||||
#elif UC3C
|
||||
# include "uc3c/sysclk.h"
|
||||
#elif UC3D
|
||||
# include "uc3d/sysclk.h"
|
||||
#elif UC3L
|
||||
# include "uc3l/sysclk.h"
|
||||
#elif XMEGA
|
||||
# include "xmega/sysclk.h"
|
||||
#elif MEGA
|
||||
# include "mega/sysclk.h"
|
||||
#else
|
||||
# error Unsupported chip type
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \defgroup clk_group Clock Management
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup clk_group
|
||||
* \defgroup sysclk_group System Clock Management
|
||||
*
|
||||
* See \ref sysclk_quickstart.
|
||||
*
|
||||
* The <em>sysclk</em> API covers the <em>system clock</em> and all
|
||||
* clocks derived from it. The system clock is a chip-internal clock on
|
||||
* which all <em>synchronous clocks</em>, i.e. CPU and bus/peripheral
|
||||
* clocks, are based. The system clock is typically generated from one
|
||||
* of a variety of sources, which may include crystal and RC oscillators
|
||||
* as well as PLLs. The clocks derived from the system clock are
|
||||
* sometimes also known as <em>synchronous clocks</em>, since they
|
||||
* always run synchronously with respect to each other, as opposed to
|
||||
* <em>generic clocks</em> which may run from different oscillators or
|
||||
* PLLs.
|
||||
*
|
||||
* Most applications should simply call sysclk_init() to initialize
|
||||
* everything related to the system clock and its source (oscillator,
|
||||
* PLL or DFLL), and leave it at that. More advanced applications, and
|
||||
* platform-specific drivers, may require additional services from the
|
||||
* clock system, some of which may be platform-specific.
|
||||
*
|
||||
* \section sysclk_group_platform Platform Dependencies
|
||||
*
|
||||
* The sysclk API is partially chip- or platform-specific. While all
|
||||
* platforms provide mostly the same functionality, there are some
|
||||
* variations around how different bus types and clock tree structures
|
||||
* are handled.
|
||||
*
|
||||
* The following functions are available on all platforms with the same
|
||||
* parameters and functionality. These functions may be called freely by
|
||||
* portable applications, drivers and services:
|
||||
* - sysclk_init()
|
||||
* - sysclk_set_source()
|
||||
* - sysclk_get_main_hz()
|
||||
* - sysclk_get_cpu_hz()
|
||||
* - sysclk_get_peripheral_bus_hz()
|
||||
*
|
||||
* The following functions are available on all platforms, but there may
|
||||
* be variations in the function signature (i.e. parameters) and
|
||||
* behavior. These functions are typically called by platform-specific
|
||||
* parts of drivers, and applications that aren't intended to be
|
||||
* portable:
|
||||
* - sysclk_enable_peripheral_clock()
|
||||
* - sysclk_disable_peripheral_clock()
|
||||
* - sysclk_enable_module()
|
||||
* - sysclk_disable_module()
|
||||
* - sysclk_module_is_enabled()
|
||||
* - sysclk_set_prescalers()
|
||||
*
|
||||
* All other functions should be considered platform-specific.
|
||||
* Enabling/disabling clocks to specific peripherals as well as
|
||||
* determining the speed of these clocks should be done by calling
|
||||
* functions provided by the driver for that peripheral.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name System Clock Initialization
|
||||
//@{
|
||||
/**
|
||||
* \fn void sysclk_init(void)
|
||||
* \brief Initialize the synchronous clock system.
|
||||
*
|
||||
* This function will initialize the system clock and its source. This
|
||||
* includes:
|
||||
* - Mask all synchronous clocks except for any clocks which are
|
||||
* essential for normal operation (for example internal memory
|
||||
* clocks).
|
||||
* - Set up the system clock prescalers as specified by the
|
||||
* application's configuration file.
|
||||
* - Enable the clock source specified by the application's
|
||||
* configuration file (oscillator or PLL) and wait for it to become
|
||||
* stable.
|
||||
* - Set the main system clock source to the clock specified by the
|
||||
* application's configuration file.
|
||||
*
|
||||
* Since all non-essential peripheral clocks are initially disabled, it
|
||||
* is the responsibility of the peripheral driver to re-enable any
|
||||
* clocks that are needed for normal operation.
|
||||
*/
|
||||
//@}
|
||||
|
||||
//! @}
|
||||
|
||||
#endif /* SYSCLK_H_INCLUDED */
|
||||
@@ -0,0 +1,513 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Chip-specific oscillator management functions
|
||||
*
|
||||
* Copyright (c) 2010-2012 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 XMEGA_OSC_H_INCLUDED
|
||||
#define XMEGA_OSC_H_INCLUDED
|
||||
|
||||
#include <compiler.h>
|
||||
#include <board.h>
|
||||
|
||||
/**
|
||||
* \weakgroup osc_group
|
||||
*
|
||||
* \section osc_group_errata Errata
|
||||
* - Auto-calibration does not work on XMEGA A1 revision H and
|
||||
* earlier.
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name Oscillator identifiers
|
||||
//@{
|
||||
//! 2 MHz Internal RC Oscillator
|
||||
#define OSC_ID_RC2MHZ OSC_RC2MEN_bm
|
||||
//! 32 MHz Internal RC Oscillator
|
||||
#define OSC_ID_RC32MHZ OSC_RC32MEN_bm
|
||||
//! 32 KHz Internal RC Oscillator
|
||||
#define OSC_ID_RC32KHZ OSC_RC32KEN_bm
|
||||
//! External Oscillator
|
||||
#define OSC_ID_XOSC OSC_XOSCEN_bm
|
||||
#if XMEGA_E
|
||||
//! 8 MHz Internal RC Oscillator
|
||||
# define OSC_ID_RC8MHZ OSC_RC8MEN_bm
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Reference from USB Start Of Frame
|
||||
* \note This cannot be enabled or disabled, but can be used as a reference for
|
||||
* the autocalibration (DFLL).
|
||||
*/
|
||||
#define OSC_ID_USBSOF 0xff
|
||||
//@}
|
||||
|
||||
//! \name External oscillator types
|
||||
//@{
|
||||
#define XOSC_TYPE_EXTERNAL 0 //!< External clock signal
|
||||
#define XOSC_TYPE_32KHZ 2 //!< 32.768 kHz resonator on TOSC
|
||||
#define XOSC_TYPE_XTAL 3 //!< 0.4 to 16 MHz resonator on XTAL
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \def CONFIG_XOSC_32KHZ_LPM
|
||||
* \brief Define for enabling Low Power Mode for 32 kHz external oscillator.
|
||||
*/
|
||||
#ifdef __DOXYGEN__
|
||||
# define CONFIG_XOSC_32KHZ_LPM
|
||||
#endif /* __DOXYGEN__ */
|
||||
|
||||
/**
|
||||
* \def CONFIG_XOSC_STARTUP
|
||||
* \brief Board-dependent value that determines the number of start-up cycles
|
||||
* for external resonators, based on BOARD_XOSC_STARTUP_US. This is written to
|
||||
* the two MSB of the XOSCSEL field of OSC.XOSCCTRL.
|
||||
*
|
||||
* \note This is automatically computed from BOARD_XOSC_HZ and
|
||||
* BOARD_XOSC_STARTUP_US if it is not manually set.
|
||||
*/
|
||||
|
||||
//! \name XTAL resonator start-up cycles
|
||||
//@{
|
||||
#define XOSC_STARTUP_256 0 //!< 256 cycle start-up time
|
||||
#define XOSC_STARTUP_1024 1 //!< 1 k cycle start-up time
|
||||
#define XOSC_STARTUP_16384 2 //!< 16 k cycle start-up time
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \def CONFIG_XOSC_RANGE
|
||||
* \brief Board-dependent value that sets the frequency range of the external
|
||||
* oscillator. This is written to the FRQRANGE field of OSC.XOSCCTRL.
|
||||
*
|
||||
* \note This is automatically computed from BOARD_XOSC_HZ if it is not manually
|
||||
* set.
|
||||
*/
|
||||
|
||||
//! \name XTAL resonator frequency range
|
||||
//@{
|
||||
//! 0.4 to 2 MHz frequency range
|
||||
#define XOSC_RANGE_04TO2 OSC_FRQRANGE_04TO2_gc
|
||||
//! 2 to 9 MHz frequency range
|
||||
#define XOSC_RANGE_2TO9 OSC_FRQRANGE_2TO9_gc
|
||||
//! 9 to 12 MHz frequency range
|
||||
#define XOSC_RANGE_9TO12 OSC_FRQRANGE_9TO12_gc
|
||||
//! 12 to 16 MHz frequency range
|
||||
#define XOSC_RANGE_12TO16 OSC_FRQRANGE_12TO16_gc
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \def XOSC_STARTUP_TIMEOUT
|
||||
* \brief Number of us to wait for XOSC to start
|
||||
*
|
||||
* This is the number of slow clock cycles corresponding to
|
||||
* OSC0_STARTUP_VALUE with an additional 25% safety margin. If the
|
||||
* oscillator isn't running when this timeout has expired, it is assumed
|
||||
* to have failed to start.
|
||||
*/
|
||||
|
||||
// If application intends to use XOSC.
|
||||
#ifdef BOARD_XOSC_HZ
|
||||
// Get start-up config for XOSC, if not manually set.
|
||||
# ifndef CONFIG_XOSC_STARTUP
|
||||
# ifndef BOARD_XOSC_STARTUP_US
|
||||
# error BOARD_XOSC_STARTUP_US must be configured.
|
||||
# else
|
||||
//! \internal Number of start-up cycles for the board's XOSC.
|
||||
# define BOARD_XOSC_STARTUP_CYCLES \
|
||||
(BOARD_XOSC_HZ / 1000000 * BOARD_XOSC_STARTUP_US)
|
||||
|
||||
# if (BOARD_XOSC_TYPE == XOSC_TYPE_XTAL)
|
||||
# if (BOARD_XOSC_STARTUP_CYCLES > 16384)
|
||||
# error BOARD_XOSC_STARTUP_US is too high for current BOARD_XOSC_HZ.
|
||||
|
||||
# elif (BOARD_XOSC_STARTUP_CYCLES > 1024)
|
||||
# define CONFIG_XOSC_STARTUP XOSC_STARTUP_16384
|
||||
# define XOSC_STARTUP_TIMEOUT (16384*(1000000/BOARD_XOSC_HZ))
|
||||
|
||||
# elif (BOARD_XOSC_STARTUP_CYCLES > 256)
|
||||
# define CONFIG_XOSC_STARTUP XOSC_STARTUP_1024
|
||||
# define XOSC_STARTUP_TIMEOUT (1024*(1000000/BOARD_XOSC_HZ))
|
||||
|
||||
# else
|
||||
# define CONFIG_XOSC_STARTUP XOSC_STARTUP_256
|
||||
# define XOSC_STARTUP_TIMEOUT (256*(1000000/BOARD_XOSC_HZ))
|
||||
# endif
|
||||
# else /* BOARD_XOSC_TYPE == XOSC_TYPE_XTAL */
|
||||
# define CONFIG_XOSC_STARTUP 0
|
||||
# endif
|
||||
# endif /* BOARD_XOSC_STARTUP_US */
|
||||
# endif /* CONFIG_XOSC_STARTUP */
|
||||
|
||||
// Get frequency range setting for XOSC, if not manually set.
|
||||
# ifndef CONFIG_XOSC_RANGE
|
||||
# if (BOARD_XOSC_TYPE == XOSC_TYPE_XTAL)
|
||||
# if (BOARD_XOSC_HZ < 400000)
|
||||
# error BOARD_XOSC_HZ is below minimum frequency of 400 kHz.
|
||||
|
||||
# elif (BOARD_XOSC_HZ < 2000000)
|
||||
# define CONFIG_XOSC_RANGE XOSC_RANGE_04TO2
|
||||
|
||||
# elif (BOARD_XOSC_HZ < 9000000)
|
||||
# define CONFIG_XOSC_RANGE XOSC_RANGE_2TO9
|
||||
|
||||
# elif (BOARD_XOSC_HZ < 12000000)
|
||||
# define CONFIG_XOSC_RANGE XOSC_RANGE_9TO12
|
||||
|
||||
# elif (BOARD_XOSC_HZ <= 16000000)
|
||||
# define CONFIG_XOSC_RANGE XOSC_RANGE_12TO16
|
||||
|
||||
# else
|
||||
# error BOARD_XOSC_HZ is above maximum frequency of 16 MHz.
|
||||
# endif
|
||||
# else /* BOARD_XOSC_TYPE == XOSC_TYPE_XTAL */
|
||||
# define CONFIG_XOSC_RANGE 0
|
||||
# endif
|
||||
# endif /* CONFIG_XOSC_RANGE */
|
||||
#endif /* BOARD_XOSC_HZ */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* \brief Enable internal oscillator \a id
|
||||
*
|
||||
* Do not call this function directly. Use osc_enable() instead.
|
||||
*/
|
||||
static inline void
|
||||
osc_enable_internal (uint8_t id)
|
||||
{
|
||||
irqflags_t flags;
|
||||
|
||||
Assert (id != OSC_ID_USBSOF);
|
||||
|
||||
flags = cpu_irq_save ();
|
||||
OSC.CTRL |= id;
|
||||
#if (XMEGA_E && CONFIG_SYSCLK_RC8MHZ_LPM)
|
||||
if (id == OSC_ID_RC8MHZ)
|
||||
{
|
||||
OSC.CTRL |= OSC_RC8MLPM_bm;
|
||||
}
|
||||
#endif
|
||||
cpu_irq_restore (flags);
|
||||
}
|
||||
|
||||
#if defined(BOARD_XOSC_HZ) || defined(__DOXYGEN__)
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* \brief Enable external oscillator \a id
|
||||
*
|
||||
* Do not call this function directly. Use osc_enable() instead. Also
|
||||
* note that this function is only available if the board actually has
|
||||
* an external oscillator crystal.
|
||||
*/
|
||||
static inline void
|
||||
osc_enable_external (uint8_t id)
|
||||
{
|
||||
irqflags_t flags;
|
||||
|
||||
Assert (id == OSC_ID_XOSC);
|
||||
|
||||
#ifndef CONFIG_XOSC_32KHZ_LPM
|
||||
# if (XMEGA_E && (BOARD_XOSC_TYPE == XOSC_TYPE_EXTERNAL) && defined(CONFIG_XOSC_EXTERNAL_PC4))
|
||||
OSC.XOSCCTRL = OSC_XOSCSEL4_bm;
|
||||
# else
|
||||
OSC.XOSCCTRL = BOARD_XOSC_TYPE | (CONFIG_XOSC_STARTUP << 2) |
|
||||
CONFIG_XOSC_RANGE;
|
||||
# endif
|
||||
#else
|
||||
OSC.XOSCCTRL = BOARD_XOSC_TYPE | (CONFIG_XOSC_STARTUP << 2) |
|
||||
CONFIG_XOSC_RANGE | OSC_X32KLPM_bm;
|
||||
#endif /* CONFIG_XOSC_32KHZ_LPM */
|
||||
|
||||
flags = cpu_irq_save ();
|
||||
OSC.CTRL |= id;
|
||||
cpu_irq_restore (flags);
|
||||
}
|
||||
#else
|
||||
|
||||
static inline void
|
||||
osc_enable_external (uint8_t id)
|
||||
{
|
||||
Assert (false); // No external oscillator on the selected board
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
osc_disable (uint8_t id)
|
||||
{
|
||||
irqflags_t flags;
|
||||
|
||||
Assert (id != OSC_ID_USBSOF);
|
||||
|
||||
flags = cpu_irq_save ();
|
||||
OSC.CTRL &= ~id;
|
||||
cpu_irq_restore (flags);
|
||||
}
|
||||
|
||||
static inline void
|
||||
osc_enable (uint8_t id)
|
||||
{
|
||||
if (id != OSC_ID_XOSC)
|
||||
{
|
||||
osc_enable_internal (id);
|
||||
}
|
||||
else
|
||||
{
|
||||
osc_enable_external (id);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
osc_is_ready (uint8_t id)
|
||||
{
|
||||
Assert (id != OSC_ID_USBSOF);
|
||||
|
||||
return OSC.STATUS & id;
|
||||
}
|
||||
|
||||
//! \name XMEGA-Specific Oscillator Features
|
||||
//@{
|
||||
|
||||
/**
|
||||
* \brief Enable DFLL-based automatic calibration of an internal
|
||||
* oscillator.
|
||||
*
|
||||
* The XMEGA features two Digital Frequency Locked Loops (DFLLs) which
|
||||
* can be used to improve the accuracy of the 2 MHz and 32 MHz internal
|
||||
* RC oscillators. The DFLL compares the oscillator frequency with a
|
||||
* more accurate reference clock to do automatic run-time calibration of
|
||||
* the oscillator.
|
||||
*
|
||||
* This function enables auto-calibration for either the 2 MHz or 32 MHz
|
||||
* internal oscillator using either the 32.768 kHz calibrated internal
|
||||
* oscillator or an external crystal oscillator as a reference. If the
|
||||
* latter option is used, the crystal must be connected to the TOSC pins
|
||||
* and run at 32.768 kHz.
|
||||
*
|
||||
* \param id The ID of the oscillator for which to enable
|
||||
* auto-calibration:
|
||||
* \arg \c OSC_ID_RC2MHZ or \c OSC_ID_RC32MHZ.
|
||||
* \param ref_id The ID of the oscillator to use as a reference:
|
||||
* \arg \c OSC_ID_RC32KHZ or \c OSC_ID_XOSC for internal or external 32 kHz
|
||||
* reference, respectively.
|
||||
* \arg \c OSC_ID_USBSOF for 32 MHz only when USB is available and running.
|
||||
*/
|
||||
static inline void
|
||||
osc_enable_autocalibration (uint8_t id, uint8_t ref_id)
|
||||
{
|
||||
irqflags_t flags;
|
||||
|
||||
flags = cpu_irq_save ();
|
||||
switch (id)
|
||||
{
|
||||
case OSC_ID_RC2MHZ:
|
||||
#if !XMEGA_E
|
||||
Assert ((ref_id == OSC_ID_RC32KHZ) || (ref_id == OSC_ID_XOSC));
|
||||
if (ref_id == OSC_ID_XOSC)
|
||||
{
|
||||
osc_enable (OSC_ID_RC32KHZ);
|
||||
OSC.DFLLCTRL |= OSC_RC2MCREF_bm;
|
||||
}
|
||||
else
|
||||
{
|
||||
OSC.DFLLCTRL &= ~(OSC_RC2MCREF_bm);
|
||||
}
|
||||
DFLLRC2M.CTRL |= DFLL_ENABLE_bm;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OSC_ID_RC32MHZ:
|
||||
#if XMEGA_AU || XMEGA_B || XMEGA_C || XMEGA_E
|
||||
Assert ((ref_id == OSC_ID_RC32KHZ)
|
||||
|| (ref_id == OSC_ID_XOSC) || (ref_id == OSC_ID_USBSOF));
|
||||
|
||||
OSC.DFLLCTRL &= ~(OSC_RC32MCREF_gm);
|
||||
|
||||
if (ref_id == OSC_ID_XOSC)
|
||||
{
|
||||
osc_enable (OSC_ID_RC32KHZ);
|
||||
OSC.DFLLCTRL |= OSC_RC32MCREF_XOSC32K_gc;
|
||||
}
|
||||
else if (ref_id == OSC_ID_RC32KHZ)
|
||||
{
|
||||
OSC.DFLLCTRL |= OSC_RC32MCREF_RC32K_gc;
|
||||
}
|
||||
# if !XMEGA_E
|
||||
else if (ref_id == OSC_ID_USBSOF)
|
||||
{
|
||||
/*
|
||||
* Calibrate 32MRC at 48MHz using USB SOF
|
||||
* 48MHz / 1kHz = 0xBB80
|
||||
*/
|
||||
DFLLRC32M.COMP1 = 0x80;
|
||||
DFLLRC32M.COMP2 = 0xBB;
|
||||
OSC.DFLLCTRL |= OSC_RC32MCREF_USBSOF_gc;
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
Assert ((ref_id == OSC_ID_RC32KHZ) || (ref_id == OSC_ID_XOSC));
|
||||
|
||||
if (ref_id == OSC_ID_XOSC)
|
||||
{
|
||||
osc_enable (OSC_ID_RC32KHZ);
|
||||
OSC.DFLLCTRL |= OSC_RC32MCREF_bm;
|
||||
}
|
||||
else if (ref_id == OSC_ID_RC32KHZ)
|
||||
{
|
||||
OSC.DFLLCTRL &= ~(OSC_RC32MCREF_bm);
|
||||
}
|
||||
#endif
|
||||
DFLLRC32M.CTRL |= DFLL_ENABLE_bm;
|
||||
break;
|
||||
|
||||
default:
|
||||
Assert (false);
|
||||
break;
|
||||
}
|
||||
cpu_irq_restore (flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable DFLL-based automatic calibration of an internal
|
||||
* oscillator.
|
||||
*
|
||||
* \see osc_enable_autocalibration
|
||||
*
|
||||
* \param id The ID of the oscillator for which to disable
|
||||
* auto-calibration:
|
||||
* \arg \c OSC_ID_RC2MHZ or \c OSC_ID_RC32MHZ.
|
||||
*/
|
||||
static inline void
|
||||
osc_disable_autocalibration (uint8_t id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case OSC_ID_RC2MHZ:
|
||||
#if !XMEGA_E
|
||||
DFLLRC2M.CTRL = 0;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OSC_ID_RC32MHZ:
|
||||
DFLLRC32M.CTRL = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
Assert (false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Load a specific calibration value for the specified oscillator.
|
||||
*
|
||||
* \param id The ID of the oscillator for which to disable
|
||||
* auto-calibration:
|
||||
* \arg \c OSC_ID_RC2MHZ or \c OSC_ID_RC32MHZ.
|
||||
* \param calib The specific calibration value required:
|
||||
*
|
||||
*/
|
||||
static inline void
|
||||
osc_user_calibration (uint8_t id, uint16_t calib)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case OSC_ID_RC2MHZ:
|
||||
#if !XMEGA_E
|
||||
DFLLRC2M.CALA = LSB (calib);
|
||||
DFLLRC2M.CALB = MSB (calib);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case OSC_ID_RC32MHZ:
|
||||
DFLLRC32M.CALA = LSB (calib);
|
||||
DFLLRC32M.CALB = MSB (calib);
|
||||
break;
|
||||
|
||||
#if XMEGA_E
|
||||
case OSC_ID_RC8MHZ:
|
||||
OSC.RC8MCAL = LSB (calib);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
Assert (false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
static inline uint32_t
|
||||
osc_get_rate (uint8_t id)
|
||||
{
|
||||
Assert (id != OSC_ID_USBSOF);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case OSC_ID_RC2MHZ:
|
||||
return 2000000UL;
|
||||
|
||||
case OSC_ID_RC32MHZ:
|
||||
#ifdef CONFIG_OSC_RC32_CAL
|
||||
return CONFIG_OSC_RC32_CAL;
|
||||
#else
|
||||
return 32000000UL;
|
||||
#endif
|
||||
|
||||
case OSC_ID_RC32KHZ:
|
||||
return 32768UL;
|
||||
|
||||
#ifdef BOARD_XOSC_HZ
|
||||
case OSC_ID_XOSC:
|
||||
return BOARD_XOSC_HZ;
|
||||
#endif
|
||||
|
||||
default:
|
||||
Assert (false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
//! @}
|
||||
|
||||
#endif /* XMEGA_OSC_H_INCLUDED */
|
||||
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Chip-specific PLL management functions
|
||||
*
|
||||
* Copyright (c) 2010-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 XMEGA_PLL_H_INCLUDED
|
||||
#define XMEGA_PLL_H_INCLUDED
|
||||
|
||||
#include <compiler.h>
|
||||
|
||||
/**
|
||||
* \weakgroup pll_group
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define NR_PLLS 1
|
||||
#define PLL_MIN_HZ 10000000UL
|
||||
#define PLL_MAX_HZ 200000000UL
|
||||
#define PLL_NR_OPTIONS 0
|
||||
|
||||
enum pll_source
|
||||
{
|
||||
//! 2 MHz Internal RC Oscillator
|
||||
PLL_SRC_RC2MHZ = OSC_PLLSRC_RC2M_gc,
|
||||
//! 32 MHz Internal RC Oscillator
|
||||
PLL_SRC_RC32MHZ = OSC_PLLSRC_RC32M_gc,
|
||||
//! External Clock Source
|
||||
PLL_SRC_XOSC = OSC_PLLSRC_XOSC_gc,
|
||||
};
|
||||
|
||||
#define pll_get_default_rate(pll_id) \
|
||||
pll_get_default_rate_priv(CONFIG_PLL##pll_id##_SOURCE, \
|
||||
CONFIG_PLL##pll_id##_MUL, \
|
||||
CONFIG_PLL##pll_id##_DIV)
|
||||
|
||||
/**
|
||||
* \internal
|
||||
* \brief Return clock rate for specified PLL settings.
|
||||
*
|
||||
* \note Due to the hardware implementation of the PLL, \a div must be 4 if the
|
||||
* 32 MHz RC oscillator is used as reference and 1 otherwise. The reference must
|
||||
* be above 440 kHz, and the output between 10 and 200 MHz.
|
||||
*
|
||||
* \param src ID of the PLL's reference source oscillator.
|
||||
* \param mul Multiplier for the PLL.
|
||||
* \param div Divisor for the PLL.
|
||||
*
|
||||
* \retval Output clock rate from PLL.
|
||||
*/
|
||||
static inline uint32_t
|
||||
pll_get_default_rate_priv (enum pll_source src,
|
||||
unsigned int mul, unsigned int div)
|
||||
{
|
||||
uint32_t rate;
|
||||
|
||||
switch (src)
|
||||
{
|
||||
case PLL_SRC_RC2MHZ:
|
||||
rate = 2000000UL;
|
||||
Assert (div == 1);
|
||||
break;
|
||||
|
||||
case PLL_SRC_RC32MHZ:
|
||||
#ifdef CONFIG_OSC_RC32_CAL //32MHz oscillator is calibrated to another frequency
|
||||
rate = CONFIG_OSC_RC32_CAL / 4;
|
||||
#else
|
||||
rate = 8000000UL;
|
||||
#endif
|
||||
Assert (div == 4);
|
||||
break;
|
||||
|
||||
case PLL_SRC_XOSC:
|
||||
rate = osc_get_rate (OSC_ID_XOSC);
|
||||
Assert (div == 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Assert (rate >= 440000UL);
|
||||
|
||||
rate *= mul;
|
||||
|
||||
Assert (rate >= PLL_MIN_HZ);
|
||||
Assert (rate <= PLL_MAX_HZ);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
struct pll_config
|
||||
{
|
||||
uint8_t ctrl;
|
||||
};
|
||||
|
||||
/**
|
||||
* \note The XMEGA PLL hardware uses hard-wired input dividers, so the
|
||||
* user must ensure that \a div is set as follows:
|
||||
* - If \a src is PLL_SRC_32MHZ, \a div must be set to 4.
|
||||
* - Otherwise, \a div must be set to 1.
|
||||
*/
|
||||
static inline void
|
||||
pll_config_init (struct pll_config *cfg, enum pll_source src,
|
||||
unsigned int div, unsigned int mul)
|
||||
{
|
||||
Assert (mul >= 1 && mul <= 31);
|
||||
|
||||
if (src == PLL_SRC_RC32MHZ)
|
||||
{
|
||||
Assert (div == 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert (div == 1);
|
||||
}
|
||||
|
||||
/* Initialize the configuration */
|
||||
cfg->ctrl = src | (mul << OSC_PLLFAC_gp);
|
||||
}
|
||||
|
||||
#define pll_config_defaults(cfg, pll_id) \
|
||||
pll_config_init(cfg, \
|
||||
CONFIG_PLL##pll_id##_SOURCE, \
|
||||
CONFIG_PLL##pll_id##_DIV, \
|
||||
CONFIG_PLL##pll_id##_MUL)
|
||||
|
||||
static inline void
|
||||
pll_config_read (struct pll_config *cfg, unsigned int pll_id)
|
||||
{
|
||||
Assert (pll_id < NR_PLLS);
|
||||
|
||||
cfg->ctrl = OSC.PLLCTRL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pll_config_write (const struct pll_config *cfg, unsigned int pll_id)
|
||||
{
|
||||
Assert (pll_id < NR_PLLS);
|
||||
|
||||
OSC.PLLCTRL = cfg->ctrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note If a different PLL reference oscillator than those enabled by
|
||||
* \ref sysclk_init() is used, the user must ensure that the desired reference
|
||||
* is enabled prior to calling this function.
|
||||
*/
|
||||
static inline void
|
||||
pll_enable (const struct pll_config *cfg, unsigned int pll_id)
|
||||
{
|
||||
irqflags_t flags;
|
||||
|
||||
Assert (pll_id < NR_PLLS);
|
||||
|
||||
flags = cpu_irq_save ();
|
||||
pll_config_write (cfg, pll_id);
|
||||
OSC.CTRL |= OSC_PLLEN_bm;
|
||||
cpu_irq_restore (flags);
|
||||
}
|
||||
|
||||
/*! \note This will not automatically disable the reference oscillator that is
|
||||
* configured for the PLL.
|
||||
*/
|
||||
static inline void
|
||||
pll_disable (unsigned int pll_id)
|
||||
{
|
||||
irqflags_t flags;
|
||||
|
||||
Assert (pll_id < NR_PLLS);
|
||||
|
||||
flags = cpu_irq_save ();
|
||||
OSC.CTRL &= ~OSC_PLLEN_bm;
|
||||
cpu_irq_restore (flags);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pll_is_locked (unsigned int pll_id)
|
||||
{
|
||||
Assert (pll_id < NR_PLLS);
|
||||
|
||||
return OSC.STATUS & OSC_PLLRDY_bm;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pll_enable_source (enum pll_source src)
|
||||
{
|
||||
switch (src)
|
||||
{
|
||||
case PLL_SRC_RC2MHZ:
|
||||
break;
|
||||
|
||||
case PLL_SRC_RC32MHZ:
|
||||
if (!osc_is_ready (OSC_ID_RC32MHZ))
|
||||
{
|
||||
osc_enable (OSC_ID_RC32MHZ);
|
||||
osc_wait_ready (OSC_ID_RC32MHZ);
|
||||
#ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC
|
||||
if (CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC != OSC_ID_USBSOF)
|
||||
{
|
||||
osc_enable (CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
|
||||
osc_wait_ready (CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
|
||||
}
|
||||
osc_enable_autocalibration (OSC_ID_RC32MHZ,
|
||||
CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case PLL_SRC_XOSC:
|
||||
if (!osc_is_ready (OSC_ID_XOSC))
|
||||
{
|
||||
osc_enable (OSC_ID_XOSC);
|
||||
osc_wait_ready (OSC_ID_XOSC);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Assert (false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
pll_enable_config_defaults (unsigned int pll_id)
|
||||
{
|
||||
struct pll_config pllcfg;
|
||||
|
||||
if (pll_is_locked (pll_id))
|
||||
{
|
||||
return; // Pll already running
|
||||
}
|
||||
switch (pll_id)
|
||||
{
|
||||
#ifdef CONFIG_PLL0_SOURCE
|
||||
case 0:
|
||||
pll_enable_source (CONFIG_PLL0_SOURCE);
|
||||
pll_config_init (&pllcfg,
|
||||
CONFIG_PLL0_SOURCE, CONFIG_PLL0_DIV, CONFIG_PLL0_MUL);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
Assert (false);
|
||||
break;
|
||||
}
|
||||
pll_enable (&pllcfg, pll_id);
|
||||
while (!pll_is_locked (pll_id));
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
#endif /* XMEGA_PLL_H_INCLUDED */
|
||||
@@ -0,0 +1,255 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Chip-specific system clock management functions
|
||||
*
|
||||
* Copyright (c) 2010-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 <compiler.h>
|
||||
|
||||
#include <sysclk.h>
|
||||
#include <osc.h>
|
||||
#include <pll.h>
|
||||
|
||||
#if XMEGA_AU || XMEGA_B || XMEGA_C
|
||||
# include <nvm.h>
|
||||
#endif
|
||||
|
||||
|
||||
void sysclk_init(void)
|
||||
{
|
||||
uint8_t *reg = (uint8_t *) & PR.PRGEN;
|
||||
uint8_t i;
|
||||
#ifdef CONFIG_OSC_RC32_CAL
|
||||
uint16_t cal;
|
||||
/* avoid Cppcheck Warning */
|
||||
UNUSED(cal);
|
||||
#endif
|
||||
bool need_rc2mhz = false;
|
||||
|
||||
/* Turn off all peripheral clocks that can be turned off. */
|
||||
for (i = 0; i <= SYSCLK_PORT_F; i++) {
|
||||
*(reg++) = 0xff;
|
||||
}
|
||||
|
||||
/* Set up system clock prescalers if different from defaults */
|
||||
if ((CONFIG_SYSCLK_PSADIV != SYSCLK_PSADIV_1)
|
||||
|| (CONFIG_SYSCLK_PSBCDIV != SYSCLK_PSBCDIV_1_1)) {
|
||||
sysclk_set_prescalers(CONFIG_SYSCLK_PSADIV, CONFIG_SYSCLK_PSBCDIV);
|
||||
}
|
||||
#if (CONFIG_OSC_RC32_CAL==48000000UL)
|
||||
MSB(cal) =
|
||||
nvm_read_production_signature_row
|
||||
(nvm_get_production_signature_row_offset(USBRCOSC));
|
||||
LSB(cal) =
|
||||
nvm_read_production_signature_row
|
||||
(nvm_get_production_signature_row_offset(USBRCOSCA));
|
||||
/*
|
||||
* If a device has an uncalibrated value in the
|
||||
* production signature row (early sample part), load a
|
||||
* sane default calibration value.
|
||||
*/
|
||||
if (cal == 0xFFFF) {
|
||||
cal = 0x2340;
|
||||
}
|
||||
osc_user_calibration(OSC_ID_RC32MHZ, cal);
|
||||
#endif
|
||||
/*
|
||||
* Switch to the selected initial system clock source, unless
|
||||
* the default internal 2 MHz oscillator is selected.
|
||||
*/
|
||||
if (CONFIG_SYSCLK_SOURCE == SYSCLK_SRC_RC2MHZ) {
|
||||
need_rc2mhz = true;
|
||||
} else {
|
||||
switch (CONFIG_SYSCLK_SOURCE) {
|
||||
case SYSCLK_SRC_RC32MHZ:
|
||||
osc_enable(OSC_ID_RC32MHZ);
|
||||
osc_wait_ready(OSC_ID_RC32MHZ);
|
||||
#ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC
|
||||
if (CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC != OSC_ID_USBSOF) {
|
||||
osc_enable(CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
|
||||
osc_wait_ready(CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
|
||||
}
|
||||
osc_enable_autocalibration(OSC_ID_RC32MHZ,
|
||||
CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SYSCLK_SRC_RC32KHZ:
|
||||
osc_enable(OSC_ID_RC32KHZ);
|
||||
osc_wait_ready(OSC_ID_RC32KHZ);
|
||||
break;
|
||||
|
||||
case SYSCLK_SRC_XOSC:
|
||||
osc_enable(OSC_ID_XOSC);
|
||||
osc_wait_ready(OSC_ID_XOSC);
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_PLL0_SOURCE
|
||||
case SYSCLK_SRC_PLL:
|
||||
if (CONFIG_PLL0_SOURCE == PLL_SRC_RC2MHZ) {
|
||||
need_rc2mhz = true;
|
||||
}
|
||||
pll_enable_config_defaults(0);
|
||||
break;
|
||||
#endif
|
||||
#if XMEGA_E
|
||||
case SYSCLK_SRC_RC8MHZ:
|
||||
osc_enable(OSC_ID_RC8MHZ);
|
||||
osc_wait_ready(OSC_ID_RC8MHZ);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
//unhandled_case(CONFIG_SYSCLK_SOURCE);
|
||||
return;
|
||||
}
|
||||
|
||||
ccp_write_io((uint8_t *) & CLK.CTRL, CONFIG_SYSCLK_SOURCE);
|
||||
Assert(CLK.CTRL == CONFIG_SYSCLK_SOURCE);
|
||||
}
|
||||
|
||||
if (need_rc2mhz) {
|
||||
#ifdef CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC
|
||||
osc_enable(CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC);
|
||||
osc_wait_ready(CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC);
|
||||
osc_enable_autocalibration(OSC_ID_RC2MHZ,
|
||||
CONFIG_OSC_AUTOCAL_RC2MHZ_REF_OSC);
|
||||
#endif
|
||||
} else {
|
||||
osc_disable(OSC_ID_RC2MHZ);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RTC_SOURCE
|
||||
sysclk_rtcsrc_enable(CONFIG_RTC_SOURCE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sysclk_enable_module(enum sysclk_port_id port,
|
||||
uint8_t id)
|
||||
{
|
||||
irqflags_t flags = cpu_irq_save();
|
||||
|
||||
*((uint8_t *) & PR.PRGEN + port) &= ~id;
|
||||
|
||||
cpu_irq_restore(flags);
|
||||
}
|
||||
|
||||
void sysclk_disable_module(enum sysclk_port_id port,
|
||||
uint8_t id)
|
||||
{
|
||||
irqflags_t flags = cpu_irq_save();
|
||||
|
||||
*((uint8_t *) & PR.PRGEN + port) |= id;
|
||||
|
||||
cpu_irq_restore(flags);
|
||||
}
|
||||
|
||||
#if XMEGA_AU || XMEGA_B || XMEGA_C || defined(__DOXYGEN__)
|
||||
|
||||
/**
|
||||
* \brief Enable clock for the USB module
|
||||
*
|
||||
* \pre CONFIG_USBCLK_SOURCE must be defined.
|
||||
*
|
||||
* \param frequency The required USB clock frequency in MHz:
|
||||
* \arg \c 6 for 6 MHz
|
||||
* \arg \c 48 for 48 MHz
|
||||
*/
|
||||
void sysclk_enable_usb(uint8_t frequency)
|
||||
{
|
||||
uint8_t prescaler;
|
||||
|
||||
Assert((frequency == 6) || (frequency == 48));
|
||||
|
||||
/*
|
||||
* Enable or disable prescaler depending on if the USB frequency is 6
|
||||
* MHz or 48 MHz. Only 6 MHz USB frequency requires prescaling.
|
||||
*/
|
||||
if (frequency == 6) {
|
||||
prescaler = CLK_USBPSDIV_8_gc;
|
||||
} else {
|
||||
prescaler = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch to the system clock selected by the user.
|
||||
*/
|
||||
switch (CONFIG_USBCLK_SOURCE) {
|
||||
case USBCLK_SRC_RCOSC:
|
||||
if (!osc_is_ready(OSC_ID_RC32MHZ)) {
|
||||
osc_enable(OSC_ID_RC32MHZ);
|
||||
osc_wait_ready(OSC_ID_RC32MHZ);
|
||||
#ifdef CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC
|
||||
if (CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC != OSC_ID_USBSOF) {
|
||||
osc_enable(CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
|
||||
osc_wait_ready(CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
|
||||
}
|
||||
osc_enable_autocalibration(OSC_ID_RC32MHZ,
|
||||
CONFIG_OSC_AUTOCAL_RC32MHZ_REF_OSC);
|
||||
#endif
|
||||
}
|
||||
ccp_write_io((uint8_t *) & CLK.USBCTRL, (prescaler)
|
||||
| CLK_USBSRC_RC32M_gc | CLK_USBSEN_bm);
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_PLL0_SOURCE
|
||||
case USBCLK_SRC_PLL:
|
||||
pll_enable_config_defaults(0);
|
||||
ccp_write_io((uint8_t *) & CLK.USBCTRL, (prescaler)
|
||||
| CLK_USBSRC_PLL_gc | CLK_USBSEN_bm);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
Assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_USB);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable clock for the USB module
|
||||
*/
|
||||
void sysclk_disable_usb(void)
|
||||
{
|
||||
sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_USB);
|
||||
ccp_write_io((uint8_t *) & CLK.USBCTRL, 0);
|
||||
}
|
||||
#endif // XMEGA_AU || XMEGA_B || XMEGA_C
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user