Split out bootloader HEX generation into separate directories for each bootloader...
[pub/USBasp.git] / LUFA / Platform / XMEGA / ClockManagement.h
index 20fb646..c824c89 100644 (file)
  *  Usage Example:
  *  \code
  *     #include <LUFA/Platform/XMEGA/ClockManagement.h>
- *
+ *      
  *     void main(void)
  *     {
- *             // Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it
- *             XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, 32000000);
- *             XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL, F_CPU);
- *
- *             // Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference
+ *             // Start the PLL to multiply the 2MHz RC oscillator to F_CPU and switch the CPU core to run from it
+ *             XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
+ *             XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
+ *          
+ *             // Start the 32MHz internal RC oscillator and start the DFLL to increase it to F_USB using the USB SOF as a reference
  *             XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
- *             XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, 48000000);
+ *             XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
  *     }
  *  \endcode
  *
@@ -70,7 +70,7 @@
 #define _XMEGA_CLOCK_MANAGEMENT_H_
 
        /* Includes: */
-               #include <LUFA/Common/Common.h>
+               #include "../../Common/Common.h"
 
        /* Enable C linkage for C++ Compilers: */
                #if defined(__cplusplus)
@@ -88,7 +88,7 @@
                                EXOSC_FREQ_16MHZ_MAX     = OSC_FRQRANGE_12TO16_gc, /**< External crystal oscillator equal to or slower than 16MHz. */
                        };
 
-                       /** Enum for the possible external oscillator statup times. */
+                       /** Enum for the possible external oscillator startup times. */
                        enum XMEGA_Extern_OSC_ClockStartup_t
                        {
                                EXOSC_START_6CLK         = OSC_XOSCSEL_EXTCLK_gc,      /**< Wait 6 clock cycles before startup (external clock). */
                        };
 
                /* Inline Functions: */
+                       /** Write a value to a location protected by the XMEGA CCP protection mechanism. This function uses inline assembly to ensure that
+                        *  the protected address is written to within four clock cycles of the CCP key being written.
+                        *
+                        *  \param[in] Address  Address to write to, a memory address protected by the CCP mechanism
+                        *  \param[in] Value    Value to write to the protected location
+                        */
+                       static inline void XMEGACLK_CCP_Write(volatile void* Address, const uint8_t Value) ATTR_ALWAYS_INLINE;
+                       static inline void XMEGACLK_CCP_Write(volatile void* Address, const uint8_t Value)
+                       {
+                               __asm__ __volatile__ (
+                                       "out %0, __zero_reg__" "\n\t" /* Zero RAMPZ using fixed zero value register */
+                                       "movw r30, %1"         "\n\t" /* Copy address to Z register pair */
+                                       "out %2, %3"           "\n\t" /* Write key to CCP register */
+                                       "st Z, %4"             "\n\t" /* Indirectly write value to address */
+                                       : /* No output operands */
+                                       : /* Input operands: */ "m" (RAMPZ), "e" (Address), "m" (CCP), "r" (CCP_IOREG_gc), "r" (Value)
+                                       : /* Clobbered registers: */ "r30", "r31"
+                               ); 
+                       }
+
                        /** Starts the external oscillator of the XMEGA microcontroller, with the given options. This routine blocks until
                         *  the oscillator is ready for use.
                         *
                         *  \param[in] FreqRange  Frequency range of the external oscillator, a value from \ref XMEGA_Extern_OSC_ClockFrequency_t.
-                        *  \param[in] Startup    Statup time of the external oscillator, a value from \ref XMEGA_Extern_OSC_ClockStartup_t.
+                        *  \param[in] Startup    Startup time of the external oscillator, a value from \ref XMEGA_Extern_OSC_ClockStartup_t.
                         *
                         *  \return Boolean \c true if the external oscillator was successfully started, \c false if invalid parameters specified.
                         */
 
                        /** Starts the PLL of the XMEGA microcontroller, with the given options. This routine blocks until the PLL is ready for use.
                         *
-                        *  \note The output frequency must be equal to or greater than the source frequency.
+                        *  \attention The output frequency must be equal to or greater than the source frequency.
                         *
                         *  \param[in] Source       Clock source for the PLL, a value from \ref XMEGA_System_ClockSource_t.
                         *  \param[in] SourceFreq   Frequency of the PLL's clock source, in Hz.
 
                                if (SourceFreq > Frequency)
                                  return false;
+                                 
+                               if (MulFactor > 31)
+                                 return false;
 
                                switch (Source)
                                {
                        /** Starts the DFLL of the XMEGA microcontroller, with the given options.
                         *
                         *  \param[in] Source     RC Clock source for the DFLL, a value from \ref XMEGA_System_ClockSource_t.
-                        *  \param[in] Reference  Reference clock source for the DFLL, an value from \ref XMEGA_System_DFLLReference_t
+                        *  \param[in] Reference  Reference clock source for the DFLL, an value from \ref XMEGA_System_DFLLReference_t.
                         *  \param[in] Frequency  Target frequency of the DFLL's output.
                         *
                         *  \return Boolean \c true if the DFLL was successfully started, \c false if invalid parameters specified.
                         *
                         *  \param[in] Source      Clock source for the CPU core, a value from \ref XMEGA_System_ClockSource_t.
                         *
-                        *  \return Boolean \c true if the CPU core clock was sucessfully altered, \c false if invalid parameters specified.
+                        *  \return Boolean \c true if the CPU core clock was successfully altered, \c false if invalid parameters specified.
                         */
                        static inline bool XMEGACLK_SetCPUClockSource(const uint8_t Source) ATTR_ALWAYS_INLINE;
                        static inline bool XMEGACLK_SetCPUClockSource(const uint8_t Source)
                                uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
                                GlobalInterruptDisable();
 
-                               CCP      = CCP_IOREG_gc;
-                               CLK_CTRL = ClockSourceMask;
+                               XMEGACLK_CCP_Write(&CLK.CTRL, ClockSourceMask);
 
                                SetGlobalInterruptMask(CurrentGlobalInt);