Add branch for the conversion of demos to use standard C header files for configurati...
[pub/lufa.git] / LUFA / Platform / XMEGA / ClockManagement.h
index dcde7dc..9b3b562 100644 (file)
  *
  *     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 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 48MHz using the USB SOF as a reference
+ *             // 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
  *
                        };
 
                /* 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.
                         *
 
                                if (SourceFreq > Frequency)
                                  return false;
+                                 
+                               if (MulFactor > 31)
+                                 return false;
 
                                switch (Source)
                                {
                                uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
                                GlobalInterruptDisable();
 
-                               CCP      = CCP_IOREG_gc;
-                               CLK_CTRL = ClockSourceMask;
+                               XMEGACLK_CCP_Write(&CLK.CTRL, ClockSourceMask);
 
                                SetGlobalInterruptMask(CurrentGlobalInt);