Added example MS/TP port to ATxmega XPLAINED A3BU evaluation board.

This commit is contained in:
skarg
2015-04-16 13:23:29 +00:00
parent 086840a763
commit fe8e60dd3d
107 changed files with 33116 additions and 0 deletions
@@ -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