Xmega Application Note


sysclk.c

Go to the documentation of this file.
00001 
00039 #include <compiler.h>
00040 
00041 #include <sysclk.h>
00042 #include <osc.h>
00043 #include <pll.h>
00044 #if (CONFIG_OSC_RC32_CAL==48000000UL)
00045 #include <nvm.h>
00046 #endif
00047 
00048 #ifdef CONFIG_PLL0_SOURCE
00049 static void sysclk_init_pll(void)
00050 {
00051         struct pll_config pllcfg;
00052 
00053         switch (CONFIG_PLL0_SOURCE) {
00054         case PLL_SRC_RC2MHZ:
00055                 break;
00056 
00057         case PLL_SRC_RC32MHZ:
00058                 osc_enable(OSC_ID_RC32MHZ);
00059                 osc_wait_ready(OSC_ID_RC32MHZ);
00060                 break;
00061 
00062         case PLL_SRC_XOSC:
00063                 osc_enable(OSC_ID_XOSC);
00064                 osc_wait_ready(OSC_ID_XOSC);
00065                 break;
00066 
00067         default:
00068                 //unhandled_case(CONFIG_PLL0_SOURCE);
00069                 break;
00070         }
00071 
00072         pll_config_defaults(&pllcfg, 0);
00073         pll_enable(&pllcfg, 0);
00074         pll_wait_for_lock(0);
00075 }
00076 #endif
00077 
00078 void sysclk_init(void)
00079 {
00080         uint8_t *reg = (uint8_t *)&PR.PRGEN;
00081         uint8_t i;
00082 #ifdef CONFIG_OSC_RC32_CAL
00083         uint16_t cal;
00084 #endif
00085 
00086         /* Turn off all peripheral clocks that can be turned off. */
00087         for (i = 0; i <= SYSCLK_PORT_F; i++) {
00088                 *(reg++) = 0xff;
00089         }
00090 
00091         /* Set up system clock prescalers if different from defaults */
00092         if ((CONFIG_SYSCLK_PSADIV != SYSCLK_PSADIV_1)
00093                         || (CONFIG_SYSCLK_PSBCDIV != SYSCLK_PSBCDIV_1_1)) {
00094                 sysclk_set_prescalers(CONFIG_SYSCLK_PSADIV,
00095                                 CONFIG_SYSCLK_PSBCDIV);
00096         }
00097 
00098         /*
00099          * Switch to the selected initial system clock source, unless
00100          * the default internal 2 MHz oscillator is selected.
00101          */
00102         if (CONFIG_SYSCLK_SOURCE != SYSCLK_SRC_RC2MHZ) {
00103                 bool need_rc2mhz = false;
00104 
00105                 switch (CONFIG_SYSCLK_SOURCE) {
00106                 case SYSCLK_SRC_RC32MHZ:
00107 #if (CONFIG_OSC_RC32_CAL==48000000UL)
00108                         MSB(cal) = nvm_read_production_signature_row(nvm_get_production_signature_row_offset(USBRCOSCB));
00109                         LSB(cal) = nvm_read_production_signature_row(nvm_get_production_signature_row_offset(USBRCOSCA));
00110                         osc_user_calibration(OSC_ID_RC32MHZ,cal);
00111 #endif
00112                         osc_enable(OSC_ID_RC32MHZ);
00113                         osc_wait_ready(OSC_ID_RC32MHZ);
00114                         break;
00115 
00116                 case SYSCLK_SRC_RC32KHZ:
00117                         osc_enable(OSC_ID_RC32KHZ);
00118                         osc_wait_ready(OSC_ID_RC32KHZ);
00119                         break;
00120 
00121                 case SYSCLK_SRC_XOSC:
00122                         osc_enable(OSC_ID_XOSC);
00123                         osc_wait_ready(OSC_ID_XOSC);
00124                         break;
00125 
00126 #ifdef CONFIG_PLL0_SOURCE
00127                 case SYSCLK_SRC_PLL:
00128                         if (CONFIG_PLL0_SOURCE == PLL_SRC_RC2MHZ) {
00129                                 need_rc2mhz = true;
00130                         }
00131                         sysclk_init_pll();
00132                         break;
00133 #endif
00134 
00135                 default:
00136                         //unhandled_case(CONFIG_SYSCLK_SOURCE);
00137                         return;
00138                 }
00139 
00140                 ccp_write_io((uint8_t *)&CLK.CTRL, CONFIG_SYSCLK_SOURCE);
00141                 Assert(CLK.CTRL == CONFIG_SYSCLK_SOURCE);
00142 
00143 #ifdef CONFIG_OSC_AUTOCAL
00144                 osc_enable_autocalibration(CONFIG_OSC_AUTOCAL,CONFIG_OSC_AUTOCAL_REF_OSC);
00145                 if (CONFIG_OSC_AUTOCAL == OSC_ID_RC2MHZ\
00146                         || CONFIG_OSC_AUTOCAL_REF_OSC == OSC_ID_RC2MHZ) {
00147                                 need_rc2mhz = true;
00148                 }
00149 #endif
00150                 
00151                 if (!need_rc2mhz) {
00152                         osc_disable(OSC_ID_RC2MHZ);
00153                 }
00154         }
00155 }
00156 
00157 void sysclk_enable_module(enum sysclk_port_id port, uint8_t id)
00158 {
00159         irqflags_t flags = cpu_irq_save();
00160 
00161         *((uint8_t *)&PR.PRGEN + port) &= ~id;
00162 
00163         cpu_irq_restore(flags);
00164 }
00165 
00166 void sysclk_disable_module(enum sysclk_port_id port, uint8_t id)
00167 {
00168         irqflags_t flags = cpu_irq_save();
00169 
00170         *((uint8_t *)&PR.PRGEN + port) |= id;
00171 
00172         cpu_irq_restore(flags);
00173 }
00174 
00175 #if XMEGA_USB
00176 # if defined(CONFIG_USBCLK_SOURCE) || defined(__DOXYGEN__)
00177 
00186 void sysclk_enable_usb(uint8_t freq)
00187 {
00188         uint8_t prescaler;
00189 
00190         // Prescale to 6 MHz.
00191         if (freq == 6) {
00192                 prescaler = CLK_USBPSDIV_8_gc;
00193         } else {
00194         // No prescaling.
00195                 Assert(freq == 48);
00196                 prescaler = 0;
00197         }
00198         ccp_write_io((uint8_t *)&CLK.USBCTRL, (prescaler)
00199                         | (CONFIG_USBCLK_SOURCE) 
00200                         | CLK_USBEN_bm);
00201 
00202         sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_USB);
00203 }
00204 
00208 void sysclk_disable_usb(void)
00209 {
00210         sysclk_disable_module(SYSCLK_PORT_GEN, SYSCLK_USB);
00211         ccp_write_io((uint8_t *)&CLK.USBCTRL, 0);
00212 }
00213 # endif // CONFIG_USBCLK_SOURCE
00214 #endif // XMEGA_USB
@DOC_TITLE@
Generated on Fri Oct 22 12:15:25 2010 for AVR1300 Using the Xmega ADC by doxygen 1.6.3