//----------------------------------------------------------------------------- static void sys_init(void) { OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_XTALEN | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_RUNSTDBY | OSC32KCTRL_XOSC32K_STARTUP(7); while (0 == OSC32KCTRL->STATUS.bit.XOSC32KRDY); #define LDR (((unsigned long)F_CPU * 32) / 32768) GCLK->GENCTRL[1].reg = GCLK_GENCTRL_SRC(GCLK_SOURCE_XOSC32K) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN; GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0].reg = GCLK_PCHCTRL_GEN(1) | GCLK_PCHCTRL_CHEN; while (0 == (GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0].reg & GCLK_PCHCTRL_CHEN)); GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL032K].reg = GCLK_PCHCTRL_GEN(1) | GCLK_PCHCTRL_CHEN; while (0 == (GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL032K].reg & GCLK_PCHCTRL_CHEN)); OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(LDR % 32) | OSCCTRL_DPLLRATIO_LDR((LDR / 32) - 1); OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK_XOSC32 | OSCCTRL_DPLLCTRLB_DIV(1) | OSCCTRL_DPLLCTRLB_WUF | OSCCTRL_DPLLCTRLB_LBYPASS; OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE | OSCCTRL_DPLLCTRLA_RUNSTDBY; while (0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY || 0 == OSCCTRL->Dpll[0].DPLLSTATUS.bit.LOCK); GCLK->GENCTRL[0].reg = GCLK_GENCTRL_SRC(GCLK_SOURCE_DPLL0) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN; }
//----------------------------------------------------------------------------- static void uart_init(uint32_t baud) { HAL_GPIO_UART_TX_out(); HAL_GPIO_UART_TX_pmuxen(HAL_GPIO_PMUX_D); HAL_GPIO_UART_RX_in(); HAL_GPIO_UART_RX_pmuxen(HAL_GPIO_PMUX_D); MCLK->APBBMASK.reg |= MCLK_APBBMASK_SERCOM2; GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN(0) | GCLK_PCHCTRL_CHEN; while (0 == (GCLK->PCHCTRL[SERCOM2_GCLK_ID_CORE].reg & GCLK_PCHCTRL_CHEN)); SERCOM2->USART.CTRLA.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE(1/*INT_CLK*/) | SERCOM_USART_CTRLA_RXPO(1/*PAD1*/) | SERCOM_USART_CTRLA_TXPO(0/*PAD0*/) | SERCOM_USART_CTRLA_SAMPR(1); SERCOM2->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/); #define BAUD_VAL (F_CPU / (16 * baud)) #define FP_VAL ((F_CPU / baud - 16 * BAUD_VAL) / 2) SERCOM2->USART.BAUD.reg = SERCOM_USART_BAUD_FRACFP_BAUD(BAUD_VAL) | SERCOM_USART_BAUD_FRACFP_FP(FP_VAL); SERCOM2->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; }
void sam_gclk_chan_enable(uint8_t channel, uint8_t srcgen) { irqstate_t flags; uint32_t regaddr; uint32_t regval; /* Get the address of the peripheral channel control register */ regaddr = SAM_GCLK_PCHCTRL(channel); /* Disable generic clock channel */ flags = enter_critical_section(); sam_gclk_chan_disable(channel); /* Configure the peripheral channel */ regval = GCLK_PCHCTRL_GEN(srcgen); putreg32(regval, regaddr); /* Enable the peripheral channel */ regval |= GCLK_PCHCTRL_CHEN; putreg32(regval, regaddr); /* Wait for clock synchronization */ while ((getreg32(regaddr) &GCLK_PCHCTRL_CHEN) == 0); leave_critical_section(flags); }
static void ADC_Init(void) { // - Enable TCC0 Bus clock (ADC control clock) MCLK->APBDMASK.reg |= MCLK_APBDMASK_ADC; // - Enable ADC_GCLK and link it to GCLK0 (see "PCHCTRLm Mapping" from product datasheet) GCLK->PCHCTRL[30].reg = (GCLK_PCHCTRL_CHEN|GCLK_PCHCTRL_GEN(0)); /* Disable ADC (required for configuration) */ ADC->CTRLA.bit.ENABLE = 0x00; /* Reset ADC configuration */ ADC->CTRLA.bit.SWRST = 0x01; /* configure GCLK_ADC prescaler */ ADC->CTRLB.bit.PRESCALER = ADC_CTRLB_PRESCALER_DIV2_Val; /* Set Reference voltage source as internal */ ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; /* Set ADC resolution to 12-bit */ ADC->CTRLC.bit.RESSEL = ADC_CTRLC_RESSEL_12BIT_Val; /* Set conversion type to single ended */ ADC->CTRLC.bit.DIFFMODE = 0x00; /* Enable Start conversion on event reception*/ ADC->EVCTRL.bit.STARTEI = 0x01; /* Enable ADC result ready interrupt */ ADC->INTENSET.bit.RESRDY = 0x01; /* Enable general ADC interrupt (ID 22)*/ NVIC_EnableIRQ(ADC_IRQn); /* Enable ADC */ ADC->CTRLA.bit.ENABLE = 0x01; }
//----------------------------------------------------------------------------- static void uart_init(uint32_t baud) { uint64_t br = (uint64_t)65536 * (F_CPU - 16 * baud) / F_CPU; HAL_GPIO_UART_TX_out(); HAL_GPIO_UART_TX_pmuxen(HAL_GPIO_PMUX_D); HAL_GPIO_UART_RX_in(); HAL_GPIO_UART_RX_pmuxen(HAL_GPIO_PMUX_D); MCLK->APBCMASK.reg |= MCLK_APBCMASK_SERCOM4; GCLK->PCHCTRL[SERCOM4_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN(0) | GCLK_PCHCTRL_CHEN; while (0 == (GCLK->PCHCTRL[SERCOM4_GCLK_ID_CORE].reg & GCLK_PCHCTRL_CHEN)); SERCOM4->USART.CTRLA.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE(1/*USART_INT_CLK*/) | SERCOM_USART_CTRLA_RXPO(3/*PAD3*/) | SERCOM_USART_CTRLA_TXPO(1/*PAD2*/); SERCOM4->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/); SERCOM4->USART.BAUD.reg = (uint16_t)br; SERCOM4->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; }
/** Configures and starts the DFLL in closed loop mode with the given reference * generator. * * \param[in] source_generator Reference generator to use for the DFLL */ static void init_dfll( const enum system_clock_source source_generator) { struct system_gclk_gen_config cpu_clock_conf; system_gclk_gen_get_config_defaults(&cpu_clock_conf); cpu_clock_conf.output_enable = ENABLE_CPU_CLOCK_OUT; /* Switch to OSC8M/OSC16M while the DFLL is being reconfigured */ #if SAML21 cpu_clock_conf.source_clock = SYSTEM_CLOCK_SOURCE_OSC16M; #else cpu_clock_conf.source_clock = SYSTEM_CLOCK_SOURCE_OSC8M; #endif system_gclk_gen_set_config(GCLK_GENERATOR_0, &cpu_clock_conf); /* Turn off DFLL before adjusting its configuration */ system_clock_source_disable(SYSTEM_CLOCK_SOURCE_DFLL); /* Configure DFLL reference clock, use raw register write to * force-configure the channel even if the currently selected generator * clock has failed */ #if SAML21 GCLK->PCHCTRL[SYSCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_GEN(source_generator); #else GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SYSCTRL_GCLK_ID_DFLL48) | GCLK_CLKCTRL_GEN(source_generator); #endif system_gclk_chan_enable(SYSCTRL_GCLK_ID_DFLL48); /* Configure DFLL */ struct system_clock_source_dfll_config config_dfll; system_clock_source_dfll_get_config_defaults(&config_dfll); config_dfll.on_demand = false; config_dfll.loop_mode = SYSTEM_CLOCK_DFLL_LOOP_MODE_CLOSED; config_dfll.multiply_factor = (48000000UL / system_gclk_chan_get_hz(SYSCTRL_GCLK_ID_DFLL48)); system_clock_source_dfll_set_config(&config_dfll); /* Restart DFLL */ system_clock_source_enable(SYSTEM_CLOCK_SOURCE_DFLL); while (system_clock_source_is_ready(SYSTEM_CLOCK_SOURCE_DFLL) == false) { /* Wait for DFLL to be stable before switch back */ } /* Switch back to the DFLL as the CPU clock source */ cpu_clock_conf.source_clock = SYSTEM_CLOCK_SOURCE_DFLL; system_gclk_gen_set_config(GCLK_GENERATOR_0, &cpu_clock_conf); };
/** * \brief Writes a Generic Clock configuration to the hardware module. * * Writes out a given configuration of a Generic Clock configuration to the * hardware module. If the clock is currently running, it will be stopped. * * \note Once called the clock will not be running; to start the clock, * call \ref system_gclk_chan_enable() after configuring a clock channel. * * \param[in] channel Generic Clock channel to configure * \param[in] config Configuration settings for the clock * */ void system_gclk_chan_set_config( const uint8_t channel, struct system_gclk_chan_config *const config) { /* Sanity check arguments */ Assert(config); /* Disable generic clock channel */ system_gclk_chan_disable(channel); /* Configure the peripheral channel */ GCLK->PCHCTRL[channel].reg = GCLK_PCHCTRL_GEN(config->source_generator); }
static void TCC0_Init(void){ // - Enable TCC0 Bus clock (Timer counter control clock) MCLK->APBCMASK.reg |= MCLK_APBCMASK_TCC0; //Enable GCLK for TCC0 and link it to GCLK0 see "PCHCTRLm Mapping" from product datasheet GCLK->PCHCTRL[25].reg = (GCLK_PCHCTRL_CHEN|GCLK_PCHCTRL_GEN(0)); // - Disable TCC0 TCC0->CTRLA.reg &=~(TCC_CTRLA_ENABLE); // - Set TCC0 in waveform mode Normal PWM TCC0->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; // - Set PER to maximum counter value (resolution : 0xFF) TCC0->PER.reg = 0xFF; // - Set WO[0] compare register to 0x7F (PWM duty cycle = 50%) TCC0->CC[0].reg = 0x7F; // - Enable Channel 0 Match Event Output TCC0->EVCTRL.bit.MCEO0 = 0x01; // - Set PB10 (LED) as TCC0 Waveform out (PMUX : F = 0x05) PORT->Group[1].WRCONFIG.reg = (uint32_t)(PORT_WRCONFIG_WRPINCFG|PORT_WRCONFIG_WRPMUX|1<<10|PORT_WRCONFIG_PMUXEN|(0x5<<PORT_WRCONFIG_PMUX_Pos)); // - ENABLE TCC0 TCC0->CTRLA.reg |= TCC_CTRLA_ENABLE; }
//----------------------------------------------------------------------------- static void timer_init(void) { MCLK->APBAMASK.reg |= MCLK_APBAMASK_TC0; GCLK->PCHCTRL[TC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN(0) | GCLK_PCHCTRL_CHEN; while (0 == (GCLK->PCHCTRL[TC0_GCLK_ID].reg & GCLK_PCHCTRL_CHEN)); TC0->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_PRESCALER_DIV1024 | TC_CTRLA_PRESCSYNC_RESYNC; TC0->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ; TC0->COUNT16.COUNT.reg = 0; timer_set_period(PERIOD_SLOW); TC0->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; TC0->COUNT16.INTENSET.reg = TC_INTENSET_MC(1); NVIC_EnableIRQ(TC0_IRQn); }
void _oscctrl_init_referenced_generators(void) { void * hw = (void *)OSCCTRL; hri_oscctrl_dfllctrl_reg_t tmp; #if CONF_DFLL_CONFIG == 1 #if CONF_DFLL_OVERWRITE_CALIBRATION == 0 #define NVM_DFLL_COARSE_POS 26 #define NVM_DFLL_COARSE_SIZE 6 uint32_t coarse; coarse = *((uint32_t *)(NVMCTRL_OTP5)) >> NVM_DFLL_COARSE_POS; #endif #if CONF_DFLL_USBCRM != 1 && CONF_DFLL_MODE != 0 hri_gclk_write_PCHCTRL_reg(GCLK, 0, (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(CONF_DFLL_GCLK)); #endif hri_oscctrl_write_DFLLCTRL_reg(hw, OSCCTRL_DFLLCTRL_ENABLE); while (!hri_oscctrl_get_STATUS_DFLLRDY_bit(hw)) ; hri_oscctrl_write_DFLLMUL_reg(hw, OSCCTRL_DFLLMUL_CSTEP(CONF_DFLL_CSTEP) | OSCCTRL_DFLLMUL_FSTEP(CONF_DFLL_FSTEP) | OSCCTRL_DFLLMUL_MUL(CONF_DFLL_MUL)); while (!hri_oscctrl_get_STATUS_DFLLRDY_bit(hw)) ; #if CONF_DFLL_OVERWRITE_CALIBRATION == 0 /* FINE is set to fixed value, which defined by DFLL48M Characteristics */ hri_oscctrl_write_DFLLVAL_reg(hw, OSCCTRL_DFLLVAL_COARSE(coarse) | OSCCTRL_DFLLVAL_FINE(512)); #else hri_oscctrl_write_DFLLVAL_reg(hw, OSCCTRL_DFLLVAL_COARSE(CONF_DFLL_COARSE) | OSCCTRL_DFLLVAL_FINE(CONF_DFLL_FINE)); #endif tmp = (CONF_DFLL_WAITLOCK << OSCCTRL_DFLLCTRL_WAITLOCK_Pos) | (CONF_DFLL_BPLCKC << OSCCTRL_DFLLCTRL_BPLCKC_Pos) | (CONF_DFLL_QLDIS << OSCCTRL_DFLLCTRL_QLDIS_Pos) | (CONF_DFLL_CCDIS << OSCCTRL_DFLLCTRL_CCDIS_Pos) | (CONF_DFLL_RUNSTDBY << OSCCTRL_DFLLCTRL_RUNSTDBY_Pos) | (CONF_DFLL_USBCRM << OSCCTRL_DFLLCTRL_USBCRM_Pos) | (CONF_DFLL_LLAW << OSCCTRL_DFLLCTRL_LLAW_Pos) | (CONF_DFLL_STABLE << OSCCTRL_DFLLCTRL_STABLE_Pos) | (CONF_DFLL_MODE << OSCCTRL_DFLLCTRL_MODE_Pos) | (CONF_DFLL_ENABLE << OSCCTRL_DFLLCTRL_ENABLE_Pos); hri_oscctrl_write_DFLLCTRL_reg(hw, tmp); #endif #if CONF_DPLL_CONFIG == 1 #if CONF_DPLL_REFCLK == 2 hri_gclk_write_PCHCTRL_reg(GCLK, 1, (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(CONF_DPLL_GCLK)); #endif hri_oscctrl_write_DPLLRATIO_reg( hw, OSCCTRL_DPLLRATIO_LDRFRAC(CONF_DPLL_LDRFRAC) | OSCCTRL_DPLLRATIO_LDR(CONF_DPLL_LDR)); hri_oscctrl_write_DPLLCTRLB_reg(hw, OSCCTRL_DPLLCTRLB_DIV(CONF_DPLL_DIV) | (CONF_DPLL_LBYPASS << OSCCTRL_DPLLCTRLB_LBYPASS_Pos) | OSCCTRL_DPLLCTRLB_LTIME(CONF_DPLL_LTIME) | OSCCTRL_DPLLCTRLB_REFCLK(CONF_DPLL_REFCLK) | (CONF_DPLL_WUF << OSCCTRL_DPLLCTRLB_WUF_Pos) | (CONF_DPLL_LPEN << OSCCTRL_DPLLCTRLB_LPEN_Pos) | OSCCTRL_DPLLCTRLB_FILTER(CONF_DPLL_FILTER)); hri_oscctrl_write_DPLLPRESC_reg(hw, OSCCTRL_DPLLPRESC_PRESC(CONF_DPLL_PRESC)); hri_oscctrl_write_DPLLCTRLA_reg(hw, (0 << OSCCTRL_DPLLCTRLA_ONDEMAND_Pos) | (CONF_DPLL_RUNSTDBY << OSCCTRL_DPLLCTRLA_RUNSTDBY_Pos) | (CONF_DPLL_ENABLE << OSCCTRL_DPLLCTRLA_ENABLE_Pos)); #endif #if CONF_DFLL_CONFIG == 1 if (hri_oscctrl_get_DFLLCTRL_MODE_bit(hw)) { hri_oscctrl_status_reg_t status_mask = OSCCTRL_STATUS_DFLLRDY | OSCCTRL_STATUS_DFLLLCKC; while (hri_oscctrl_get_STATUS_reg(hw, status_mask) != status_mask) ; } else { while (!hri_oscctrl_get_STATUS_DFLLRDY_bit(hw)) ; } #if CONF_DFLL_ONDEMAND == 1 hri_oscctrl_set_DFLLCTRL_ONDEMAND_bit(hw); #endif #endif #if CONF_DPLL_CONFIG == 1 #if CONF_DPLL_ENABLE == 1 while (!(hri_oscctrl_get_DPLLSTATUS_LOCK_bit(hw) || hri_oscctrl_get_DPLLSTATUS_CLKRDY_bit(hw))) ; #endif #if CONF_DPLL_ONDEMAND == 1 hri_oscctrl_set_DPLLCTRLA_ONDEMAND_bit(hw); #endif #endif #if CONF_DFLL_CONFIG == 1 while (hri_gclk_read_SYNCBUSY_reg(GCLK)) ; #endif (void)hw, (void)tmp; }