/** * Initialize the system * * @brief Setup the microcontroller system. * Initialize the System and update the SystemCoreClock variable. */ void SystemInit(void) { /*** Configure XOSC32KHz */ // - Set XOSC32K as external crystal oscillator OSC32KCTRL->XOSC32K.bit.XTALEN = 1; // - Enable 32.768kHz output OSC32KCTRL->XOSC32K.bit.EN32K = 1; // - Enable 1kHz output OSC32KCTRL->XOSC32K.bit.EN1K = 1; // - Behavior in Low power (see "XOSC32K Sleep Behavior" table from product datasheet) OSC32KCTRL->XOSC32K.bit.RUNSTDBY = 0; OSC32KCTRL->XOSC32K.bit.ONDEMAND = 0; // - Set XOSC32K Startup time (see "Start-Up Time for 32KHz External Crystal Oscillator" table from product datasheet) OSC32KCTRL->XOSC32K.bit.STARTUP = 2; // - Enable XOSC32K OSC32KCTRL->XOSC32K.bit.ENABLE = 1; while(!(OSC32KCTRL->STATUS.bit.XOSC32KRDY)); /*** Configure DPLL */ // - Select DPLL Reference clock (0:XOSC32K , 1:XOSC , 2:GCLK) OSCCTRL->DPLLCTRLB.bit.REFCLK = 0; // - Set DPLL Prescaler OSCCTRL->DPLLPRESC.reg = 0; // - Set DPLL Ratio (48000000 / 32768 = 1464.84375) OSCCTRL->DPLLRATIO.bit.LDR = 1464; OSCCTRL->DPLLRATIO.bit.LDRFRAC = 14; //(0.84375 * 16) // - Enable DPLL OSCCTRL->DPLLCTRLA.bit.ENABLE = 1; while(OSCCTRL->DPLLSYNCBUSY.bit.ENABLE); //** Set Flash wait State according to 48MHz CPU clock */ NVMCTRL->CTRLB.bit.RWS = 3; //** Set Performance level according to 48MHz CPU clock (0:PL0 2:PL2)*/ PM->PLCFG.bit.PLSEL = 2 ; while(!PM->INTFLAG.bit.PLRDY); /*** Set Generic clock 0 source as DPLL (MAIN clock for CPU and synchronous clock) */ while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL_GCLK0)); GCLK->GENCTRL[0].reg = (GCLK_GENCTRL_OE|GCLK_GENCTRL_SRC_DPLL96M|GCLK_GENCTRL_DIV(1)|GCLK_GENCTRL_GENEN); while((GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL_GCLK0)); //*** Set PA27 as GCLK0_IO (PMUX : H = 0x07) PORT->Group[0].WRCONFIG.reg = (uint32_t)( PORT_WRCONFIG_HWSEL | PORT_WRCONFIG_WRPINCFG | PORT_WRCONFIG_WRPMUX | PORT_WRCONFIG_PINMASK(1 << 11) | PORT_WRCONFIG_PMUXEN | (0x7 << PORT_WRCONFIG_PMUX_Pos) ); /*** Update System Core clock variable */ SystemCoreClock = 48000000; return; }
void sam_gclk_config(FAR const struct sam_gclkconfig_s *config) { irqstate_t flags; uintptr_t regaddr; uint32_t regval; uint32_t genctrl; /* Select the requested source clock for the generator */ genctrl = ((uint32_t)config->clksrc << GCLK_GENCTRL_SRC_SHIFT); #if 0 /* Not yet supported */ /* Configure the clock to be either high or low when disabled */ if (config->level) { genctrl |= GCLK_GENCTRL_OOV; } #endif /* Configure if the clock output to I/O pin should be enabled */ if (config->output) { genctrl |= GCLK_GENCTRL_OE; } /* Set the prescaler division factor */ if (config->prescaler > 1) { /* Check if division is a power of two */ if (((config->prescaler & (config->prescaler - 1)) == 0)) { /* Determine the index of the highest bit set to get the * division factor that must be loaded into the division * register. */ uint32_t count = 0; uint32_t mask; for (mask = 2; mask < (uint32_t)config->prescaler; mask <<= 1) { count++; } /* Set binary divider power of 2 division factor */ genctrl |= count << GCLK_GENCTRL_DIV_SHIFT; genctrl |= GCLK_GENCTRL_DIVSEL; } else { /* Set integer division factor */ genctrl |= GCLK_GENCTRL_DIV((uint32_t)config->prescaler); /* Enable non-binary division with increased duty cycle accuracy */ genctrl |= GCLK_GENCTRL_IDC; } } /* Enable or disable the clock in standby mode */ if (config->runstandby) { genctrl |= GCLK_GENCTRL_RUNSTDBY; } /* Wait for synchronization */ sam_gclck_waitsyncbusy(config->gclk); /* Preserve the GENEN bit */ regaddr = SAM_GCLK_GENCTRL(config->gclk); flags = enter_critical_section(); regval = getreg32(regaddr); regval &= GCLK_GENCTRL_GENEN; genctrl |= regval; /* Configure the generator */ putreg32(genctrl, regaddr); /* Wait for synchronization */ sam_gclck_waitsyncbusy(config->gclk); leave_critical_section(flags); sam_gclck_waitsyncbusy(config->gclk); /* Enable the clock generator */ flags = enter_critical_section(); genctrl |= GCLK_GENCTRL_GENEN; putreg32(genctrl, regaddr); /* Wait for synchronization */ sam_gclck_waitsyncbusy(config->gclk); leave_critical_section(flags); }