/** * \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); }
void sysclk_init(void) { uint8_t *reg = (uint8_t *)&PR.PRGEN; uint8_t i; #ifdef CONFIG_OSC_RC32_CAL uint16_t 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 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_init(void) { uint8_t *reg = (uint8_t *)&PR.PRGEN; uint8_t i; #ifdef CONFIG_OSC_RC32_CAL uint16_t cal; #endif /* 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. * * MODIFIED 16-7-2012 by C.DOGGEN: * - commented the if statement, otherwise the USART won't work * - don't know exactly the problem, but this seems to be a workaround. */ 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) { bool need_rc2mhz = false; switch (CONFIG_SYSCLK_SOURCE) { case SYSCLK_SRC_RC32MHZ: osc_enable(OSC_ID_RC32MHZ); osc_wait_ready(OSC_ID_RC32MHZ); 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 default: //unhandled_case(CONFIG_SYSCLK_SOURCE); return; } ccp_write_io((uint8_t *)&CLK.CTRL, CONFIG_SYSCLK_SOURCE); Assert(CLK.CTRL == CONFIG_SYSCLK_SOURCE); #ifdef CONFIG_OSC_AUTOCAL osc_enable_autocalibration(CONFIG_OSC_AUTOCAL,CONFIG_OSC_AUTOCAL_REF_OSC); if (CONFIG_OSC_AUTOCAL == OSC_ID_RC2MHZ || CONFIG_OSC_AUTOCAL_REF_OSC == OSC_ID_RC2MHZ) { need_rc2mhz = true; } #endif if (!need_rc2mhz) { osc_disable(OSC_ID_RC2MHZ); } } }