void SDI12Timer::configSDI12TimerPrescale(void) { // Select generic clock generator 4 (Arduino core uses 0-3) // Most examples use this clock generator.. consider yourself warned! // I would use a higher clock number, but some of the cores don't include them for some reason REG_GCLK_GENDIV = GCLK_GENDIV_ID(4) | // Select Generic Clock Generator 4 GCLK_GENDIV_DIV(3) ; // Divide the 48MHz clock source by divisor 3: 48MHz/3=16MHz while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization // Write the generic clock generator 5 configuration REG_GCLK_GENCTRL = GCLK_GENCTRL_ID(4) | // Select GCLK4 GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW GCLK_GENCTRL_GENEN; // Enable the generic clock clontrol while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization // Feed GCLK4 to TC4 (also feeds to TC5, the two must have the same source) REG_GCLK_CLKCTRL = GCLK_CLKCTRL_GEN_GCLK4 | // Select Generic Clock Generator 4 GCLK_CLKCTRL_CLKEN | // Enable the generic clock generator GCLK_CLKCTRL_ID_TC4_TC5; // Feed the Generic Clock Generator 4 to TC4 and TC5 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization REG_TC4_CTRLA |= TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 16MHz/1024 = 15.625kHz TC_CTRLA_WAVEGEN_NFRQ | // Put the timer TC4 into normal frequency (NFRQ) mode TC_CTRLA_MODE_COUNT8 | // Put the timer TC4 into 8-bit mode TC_CTRLA_ENABLE; // Enable TC4 while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization }
void RtcInit() { // SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_ENABLE | SYSCTRL_XOSC32K_EN32K; // //wait for crystal to warm up // while((SYSCTRL->PCLKSR.reg & (SYSCTRL_PCLKSR_XOSC32KRDY)) == 0); GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(8); GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_SRC(GCLK_SOURCE_OSC8M) | GCLK_GENCTRL_IDC | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN; while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); // Configure RTC GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(RTC_GCLK_ID) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(2); RTC->MODE1.CTRL.reg = RTC_MODE1_CTRL_MODE_COUNT16; while (RTC->MODE1.STATUS.bit.SYNCBUSY); // Prescaler needs to be enabled separately from the mode for some reason RTC->MODE1.CTRL.reg |= RTC_MODE1_CTRL_PRESCALER_DIV1; while (RTC->MODE1.STATUS.bit.SYNCBUSY); RTC->MODE1.PER.reg = 998; while (RTC->MODE1.STATUS.bit.SYNCBUSY); RTC->MODE1.READREQ.reg |= RTC_READREQ_RCONT | RTC_READREQ_ADDR(0x10); RTC->MODE1.INTENSET.reg = RTC_MODE1_INTENSET_OVF; RTC->MODE1.CTRL.bit.ENABLE = 1; while (RTC->MODE1.STATUS.bit.SYNCBUSY); NVIC_EnableIRQ(RTC_IRQn); }
void SystemInit(void) { // Setup flash to work with 48Mhz clock NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_RWS_HALF; // Enable external 32Khz crystal uint32_t val = (SYSCTRL_XOSC32K_STARTUP(6) | SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K); SYSCTRL->XOSC32K.reg = val; SYSCTRL->XOSC32K.reg = val | SYSCTRL_XOSC32K_ENABLE; while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY)) ; // Reset GCLK GCLK->CTRL.reg = GCLK_CTRL_SWRST; while (GCLK->CTRL.reg & GCLK_CTRL_SWRST) ; // Route 32Khz clock to DFLL48M GCLK->GENDIV.reg = GCLK_GENDIV_ID(CLK_32K); GCLK->GENCTRL.reg = (GCLK_GENCTRL_ID(CLK_32K) | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_GENEN); GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_ID(MCLK_DFLL48M) | GCLK_CLKCTRL_GEN(CLK_32K) | GCLK_CLKCTRL_CLKEN); // Configure DFLL48M clock SYSCTRL->DFLLCTRL.reg = 0; uint32_t mul = DIV_ROUND_CLOSEST(CONFIG_CLOCK_FREQ, CLK_32K_FREQ); SYSCTRL->DFLLMUL.reg = (SYSCTRL_DFLLMUL_CSTEP(31) | SYSCTRL_DFLLMUL_FSTEP(511) | SYSCTRL_DFLLMUL_MUL(mul)); SYSCTRL->DFLLCTRL.reg = (SYSCTRL_DFLLCTRL_MODE | SYSCTRL_DFLLCTRL_WAITLOCK | SYSCTRL_DFLLCTRL_QLDIS | SYSCTRL_DFLLCTRL_ENABLE); uint32_t ready = (SYSCTRL_PCLKSR_DFLLRDY | SYSCTRL_PCLKSR_DFLLLCKC | SYSCTRL_PCLKSR_DFLLLCKF); while ((SYSCTRL->PCLKSR.reg & ready) != ready) ; // Switch main clock to DFLL48M clock GCLK->GENDIV.reg = GCLK_GENDIV_ID(CLK_MAIN); GCLK->GENCTRL.reg = (GCLK_GENCTRL_ID(CLK_MAIN) | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_IDC | GCLK_GENCTRL_GENEN); }
/** * @brief Initialize RTT module * * The RTT is running at 32768 Hz by default, i.e. @ XOSC32K frequency without * divider. There are 2 cascaded dividers in the clock path: * * - GCLK_GENDIV_DIV(n): between 1 and 31 * - RTC_MODE0_CTRL_PRESCALER_DIVn: between 1 and 1024, see defines in `component_rtc.h` * * However the division scheme of GCLK_GENDIV_DIV can be changed by setting * GCLK_GENCTRL_DIVSEL: * * - GCLK_GENCTRL_DIVSEL = 0: Clock divided by GENDIV.DIV (default) * - GCLK_GENCTRL_DIVSEL = 1: Clock divided by 2^( GENDIV.DIV + 1 ) */ void rtt_init(void) { RtcMode0 *rtcMode0 = &(RTT_DEV); /* Turn on power manager for RTC */ PM->APBAMASK.reg |= PM_APBAMASK_RTC; /* RTC uses External 32,768KHz Oscillator because OSC32K isn't accurate * enough (p1075/1138). Also keep running in standby. */ SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_ONDEMAND | SYSCTRL_XOSC32K_EN32K | SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_STARTUP(6) | #if RTT_RUNSTDBY SYSCTRL_XOSC32K_RUNSTDBY | #endif SYSCTRL_XOSC32K_ENABLE; /* Setup clock GCLK2 with divider 1 */ GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(1); while (GCLK->STATUS.bit.SYNCBUSY) {} /* Enable GCLK2 with XOSC32K as source. Use divider without modification * and keep running in standby. */ GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_GENEN | #if RTT_RUNSTDBY GCLK_GENCTRL_RUNSTDBY | #endif GCLK_GENCTRL_SRC_XOSC32K; while (GCLK->STATUS.bit.SYNCBUSY) {} /* Connect GCLK2 to RTC */ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_GEN_GCLK2 | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_ID(RTC_GCLK_ID); while (GCLK->STATUS.bit.SYNCBUSY) {} /* Disable RTC */ rtt_poweroff(); /* Reset RTC */ rtcMode0->CTRL.bit.SWRST = 1; while (rtcMode0->STATUS.bit.SYNCBUSY || rtcMode0->CTRL.bit.SWRST) {} /* Configure as 32bit counter with no prescaler and no clear on match compare */ rtcMode0->CTRL.reg = RTC_MODE0_CTRL_MODE_COUNT32 | RTT_PRESCALER; while (rtcMode0->STATUS.bit.SYNCBUSY) {} /* Setup interrupt */ NVIC_EnableIRQ(RTT_IRQ); /* Enable RTC */ rtt_poweron(); }
/******************************************************************************************* *Description: Function responsible of RTC initialization *Input Parameters: bool timeRep this parameter can be TIME_H24 (24 hour mode) or TIME_H12 (12 hour mode) *Return Parameter: None *******************************************************************************************/ void RTCInt::begin(bool timeRep, int oscillatorType) { PM->APBAMASK.reg |= PM_APBAMASK_RTC; // turn on digital interface clock for RTC GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK4 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos))); while (GCLK->STATUS.bit.SYNCBUSY); //Set the oscillator to use - M0 only if(oscillatorType==HIGH_PRECISION) //External oscillator GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(4) | GCLK_GENCTRL_DIVSEL ); else //Internal low power oscillator (default configuration) GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(4) | GCLK_GENCTRL_DIVSEL ); while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); GCLK->GENDIV.reg = GCLK_GENDIV_ID(4); GCLK->GENDIV.bit.DIV=4; while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); RTCdisable(); RTCreset(); RTC->MODE2.CTRL.reg |= RTC_MODE2_CTRL_MODE_CLOCK; // set RTC operating mode RTC->MODE2.CTRL.reg |= RTC_MODE2_CTRL_PRESCALER_DIV1024; // set prescaler to 1024 for MODE2 RTC->MODE2.CTRL.bit.MATCHCLR = 0; // disable clear on match if (timeRep) { RTC->MODE2.CTRL.bit.CLKREP = 0; // 24h time representation time_Mode = true; } else { RTC->MODE2.CTRL.bit.CLKREP = 1; // 12h time representation time_Mode = false; } RTC->MODE2.READREQ.reg &= ~RTC_READREQ_RCONT; // disable continuously mode while (RTCSync()); RTCresetRemove(); RTCenable(); }
void WatchdogSAMD::_initialize_wdt() { // One-time initialization of watchdog timer. // Insights from rickrlh and rbrucemtl in Arduino forum! #if defined(__SAMD51__) // SAMD51 WDT uses OSCULP32k as input clock now // section: 20.5.3 OSC32KCTRL->OSCULP32K.bit.EN1K = 1; // Enable out 1K (for WDT) OSC32KCTRL->OSCULP32K.bit.EN32K = 0; // Disable out 32K // Enable WDT early-warning interrupt NVIC_DisableIRQ(WDT_IRQn); NVIC_ClearPendingIRQ(WDT_IRQn); NVIC_SetPriority(WDT_IRQn, 0); // Top priority NVIC_EnableIRQ(WDT_IRQn); while(WDT->SYNCBUSY.reg); USB->DEVICE.CTRLA.bit.ENABLE = 0; // Disable the USB peripheral while(USB->DEVICE.SYNCBUSY.bit.ENABLE); // Wait for synchronization USB->DEVICE.CTRLA.bit.RUNSTDBY = 0; // Deactivate run on standby USB->DEVICE.CTRLA.bit.ENABLE = 1; // Enable the USB peripheral while(USB->DEVICE.SYNCBUSY.bit.ENABLE); // Wait for synchronization #else // Generic clock generator 2, divisor = 32 (2^(DIV+1)) GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(4); // Enable clock generator 2 using low-power 32KHz oscillator. // With /32 divisor above, this yields 1024Hz(ish) clock. GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_DIVSEL; while(GCLK->STATUS.bit.SYNCBUSY); // WDT clock = clock gen 2 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_WDT | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2; // Enable WDT early-warning interrupt NVIC_DisableIRQ(WDT_IRQn); NVIC_ClearPendingIRQ(WDT_IRQn); NVIC_SetPriority(WDT_IRQn, 0); // Top priority NVIC_EnableIRQ(WDT_IRQn); #endif _initialized = true; }
void SaLBuzzerInit() { pinOut(BUZZER); pinCfg(BUZZER); // PM->APBCMASK.reg |= PM_APBCMASK_TC5; // GCLK->GENDIV.reg = GCLK_GENDIV_ID(5) | GCLK_GENDIV_DIV(1); GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(5) | GCLK_GENCTRL_SRC_OSC8M | GCLK_GENCTRL_GENEN; GCLK->CLKCTRL.reg = GCLK_CLKCTRL_GEN(0) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_ID(TC5_GCLK_ID); TC5->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16| TC_CTRLA_RUNSTDBY | // TC_CTRLA_PRESCSYNC_GCLK | TC_CTRLA_PRESCALER_DIV4; // TC5->COUNT16.EVCTRL.bit.EVACT = 0x1; TC5->COUNT16.CC[0].bit.CC = 700; //TC5->COUNT16.PER.reg = 0x02; TC5->COUNT16.INTENSET.reg = TC_INTENSET_MC0; TC5->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; TC5->COUNT16.EVCTRL.bit.EVACT = 0x1; NVIC_EnableIRQ(TC5_IRQn); NVIC_SetPriority(TC5_IRQn,0xFFF); TC5->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_STOP; }
void rtc_init(void) { RtcMode2 *rtcMode2 = &(RTC_DEV); /* Turn on power manager for RTC */ PM->APBAMASK.reg |= PM_APBAMASK_RTC; SYSCTRL->OSC32K.bit.ENABLE = 0; SYSCTRL->OSC32K.bit.ONDEMAND = 1; SYSCTRL->OSC32K.bit.RUNSTDBY = 0; SYSCTRL->OSC32K.bit.EN1K = 1; SYSCTRL->OSC32K.bit.EN32K = 1; SYSCTRL->OSC32K.bit.ENABLE = 1; /* Setup clock GCLK2 with OSC32K divided by 32 */ GCLK->GENDIV.reg = GCLK_GENDIV_ID(2)|GCLK_GENDIV_DIV(4); while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC32K | GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_DIVSEL ); while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos))); while (GCLK->STATUS.bit.SYNCBUSY); /* DISABLE RTC MASTER */ while (rtcMode2->STATUS.reg & RTC_STATUS_SYNCBUSY); rtc_poweroff(); /* Reset RTC */ while (rtcMode2->STATUS.bit.SYNCBUSY); rtcMode2->CTRL.reg= RTC_MODE2_CTRL_SWRST; while (rtcMode2->STATUS.bit.SYNCBUSY); /* RTC config with RTC_MODE2_CTRL_CLKREP = 0 (24h) */ rtcMode2->CTRL.reg = RTC_MODE2_CTRL_PRESCALER_DIV1024|RTC_MODE2_CTRL_MODE_CLOCK; while (rtcMode2->STATUS.bit.SYNCBUSY); rtcMode2->INTENSET.reg = RTC_MODE2_INTENSET_OVF; while (rtcMode2->STATUS.bit.SYNCBUSY); rtc_poweron(); }
void rtc_init(void) { RtcMode2 *rtcMode2 = &(RTC_DEV); /* Turn on power manager for RTC */ PM->APBAMASK.reg |= PM_APBAMASK_RTC; /* RTC uses External 32,768KHz Oscillator (OSC32K isn't accurate enough p1075/1138)*/ SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_ONDEMAND | SYSCTRL_XOSC32K_EN32K | SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_STARTUP(6) | SYSCTRL_XOSC32K_ENABLE; /* Setup clock GCLK2 with OSC32K divided by 32 */ GCLK->GENDIV.reg = GCLK_GENDIV_ID(2)|GCLK_GENDIV_DIV(4); while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_DIVSEL ); while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos))); while (GCLK->STATUS.bit.SYNCBUSY); /* DISABLE RTC MASTER */ while (rtcMode2->STATUS.reg & RTC_STATUS_SYNCBUSY); rtc_poweroff(); /* Reset RTC */ while (rtcMode2->STATUS.bit.SYNCBUSY); rtcMode2->CTRL.reg= RTC_MODE2_CTRL_SWRST; while (rtcMode2->STATUS.bit.SYNCBUSY); /* RTC config with RTC_MODE2_CTRL_CLKREP = 0 (24h) */ rtcMode2->CTRL.reg = RTC_MODE2_CTRL_PRESCALER_DIV1024|RTC_MODE2_CTRL_MODE_CLOCK; while (rtcMode2->STATUS.bit.SYNCBUSY); rtcMode2->INTENSET.reg = RTC_MODE2_INTENSET_OVF; while (rtcMode2->STATUS.bit.SYNCBUSY); rtc_poweron(); }
void SystemInit( void ) { /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */ NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val ; /* Turn on the digital interface clock */ PM->APBAMASK.reg |= PM_APBAMASK_GCLK ; /* ---------------------------------------------------------------------------------------------- * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator) */ SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */ SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ; SYSCTRL->XOSC32K.bit.ENABLE = 1 ; /* separate call, as described in chapter 15.6.3 */ while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 ) { /* Wait for oscillator stabilization */ } /* Software reset the module to ensure it is re-initialized correctly */ /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete. * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1 */ GCLK->CTRL.reg = GCLK_CTRL_SWRST ; while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) ) { /* Wait for reset to complete */ } /* ---------------------------------------------------------------------------------------------- * 2) Put XOSC32K as source of Generic Clock Generator 1 */ GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) ; // Generic Clock Generator 1 while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { /* Wait for synchronization */ } /* Write Generic Clock Generator 1 configuration */ GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1 GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator // GCLK_GENCTRL_OE | // Output clock to a pin for tests GCLK_GENCTRL_GENEN ; while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { /* Wait for synchronization */ } /* ---------------------------------------------------------------------------------------------- * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference) */ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_MULTIPLEXER_DFLL48M ) | // Generic Clock Multiplexer 0 GCLK_CLKCTRL_GEN_GCLK1 | // Generic Clock Generator 1 is source GCLK_CLKCTRL_CLKEN ; while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { /* Wait for synchronization */ } /* ---------------------------------------------------------------------------------------------- * 4) Enable DFLL48M clock */ /* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */ /* Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905 */ SYSCTRL->DFLLCTRL.bit.ONDEMAND = 0 ; while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) { /* Wait for synchronization */ } SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value SYSCTRL_DFLLMUL_MUL( (__CLOCK_48MHz/__CLOCK_32KHz) ) ; // External 32KHz is the reference while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) { /* Wait for synchronization */ } /* Write full configuration to DFLL control register */ SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */ SYSCTRL_DFLLCTRL_WAITLOCK | SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */ while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) { /* Wait for synchronization */ } /* Enable the DFLL */ SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ; while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 || (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 ) { /* Wait for locks flags */ } while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) { /* Wait for synchronization */ } /* ---------------------------------------------------------------------------------------------- * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz. */ GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ) ; // Generic Clock Generator 0 while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { /* Wait for synchronization */ } /* Write Generic Clock Generator 0 configuration */ GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0 GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz // GCLK_GENCTRL_OE | // Output clock to a pin for tests GCLK_GENCTRL_IDC | // Set 50/50 duty cycle GCLK_GENCTRL_GENEN ; while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { /* Wait for synchronization */ } /* ---------------------------------------------------------------------------------------------- * 6) Modify PRESCaler value of OSC8M to have 8MHz */ SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_0_Val ; SYSCTRL->OSC8M.bit.ONDEMAND = 0 ; /* ---------------------------------------------------------------------------------------------- * 7) Put OSC8M as source for Generic Clock Generator 3 */ GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) ; // Generic Clock Generator 3 /* Write Generic Clock Generator 3 configuration */ GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3 GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset) // GCLK_GENCTRL_OE | // Output clock to a pin for tests GCLK_GENCTRL_GENEN ; while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { /* Wait for synchronization */ } /* ---------------------------------------------------------------------------------------------- * 8) Put OSC8M as source for Generic Clock Generator 2, with freq/8 */ GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC1M ) | 8 << 8; // Generic Clock Generator 4 /* Write Generic Clock Generator 3 configuration */ GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC1M ) | // Generic Clock Generator 4 GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset) // GCLK_GENCTRL_OE | // Output clock to a pin for tests GCLK_GENCTRL_GENEN ; while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY ) { /* Wait for synchronization */ } /* * Now that all system clocks are configured, we can set CPU and APBx BUS clocks. * There values are normally the one present after Reset. */ PM->CPUSEL.reg = PM_CPUSEL_CPUDIV_DIV1 ; PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val ; PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val ; PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val ; SystemCoreClock=__CLOCK_48MHz ; return; }
/** * \brief Initializes generators */ void _gclk_init_generators(void) { void *hw = (void *)GCLK; # if CONF_GCLK_GEN_0_GENEN == 1 hri_gclk_write_GENDIV_reg(hw, GCLK_GENDIV_DIV(CONF_GCLK_GEN_0_DIV) | GCLK_GENDIV_ID(0)); hri_gclk_write_GENCTRL_reg(hw, (CONF_GCLK_GEN_0_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos) | (CONF_GCLK_GEN_0_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_0_OE << GCLK_GENCTRL_OE_Pos) | (CONF_GCLK_GEN_0_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_0_IDC << GCLK_GENCTRL_IDC_Pos) | (CONF_GCLK_GEN_0_GENEN << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_0_SRC | GCLK_GENCTRL_ID(0)); # endif # if CONF_GCLK_GEN_1_GENEN == 1 hri_gclk_write_GENDIV_reg(hw, GCLK_GENDIV_DIV(CONF_GCLK_GEN_1_DIV) | GCLK_GENDIV_ID(1)); hri_gclk_write_GENCTRL_reg(hw, (CONF_GCLK_GEN_1_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos) | (CONF_GCLK_GEN_1_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_1_OE << GCLK_GENCTRL_OE_Pos) | (CONF_GCLK_GEN_1_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_1_IDC << GCLK_GENCTRL_IDC_Pos) | (CONF_GCLK_GEN_1_GENEN << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_1_SRC | GCLK_GENCTRL_ID(1)); # endif # if CONF_GCLK_GEN_2_GENEN == 1 hri_gclk_write_GENDIV_reg(hw, GCLK_GENDIV_DIV(CONF_GCLK_GEN_2_DIV) | GCLK_GENDIV_ID(2)); hri_gclk_write_GENCTRL_reg(hw, (CONF_GCLK_GEN_2_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos) | (CONF_GCLK_GEN_2_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_2_OE << GCLK_GENCTRL_OE_Pos) | (CONF_GCLK_GEN_2_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_2_IDC << GCLK_GENCTRL_IDC_Pos) | (CONF_GCLK_GEN_2_GENEN << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_2_SRC | GCLK_GENCTRL_ID(2)); # endif # if CONF_GCLK_GEN_3_GENEN == 1 hri_gclk_write_GENDIV_reg(hw, GCLK_GENDIV_DIV(CONF_GCLK_GEN_3_DIV) | GCLK_GENDIV_ID(3)); hri_gclk_write_GENCTRL_reg(hw, (CONF_GCLK_GEN_3_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos) | (CONF_GCLK_GEN_3_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_3_OE << GCLK_GENCTRL_OE_Pos) | (CONF_GCLK_GEN_3_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_3_IDC << GCLK_GENCTRL_IDC_Pos) | (CONF_GCLK_GEN_3_GENEN << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_3_SRC | GCLK_GENCTRL_ID(3)); # endif # if CONF_GCLK_GEN_4_GENEN == 1 hri_gclk_write_GENDIV_reg(hw, GCLK_GENDIV_DIV(CONF_GCLK_GEN_4_DIV) | GCLK_GENDIV_ID(4)); hri_gclk_write_GENCTRL_reg(hw, (CONF_GCLK_GEN_4_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos) | (CONF_GCLK_GEN_4_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_4_OE << GCLK_GENCTRL_OE_Pos) | (CONF_GCLK_GEN_4_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_4_IDC << GCLK_GENCTRL_IDC_Pos) | (CONF_GCLK_GEN_4_GENEN << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_4_SRC | GCLK_GENCTRL_ID(4)); # endif # if CONF_GCLK_GEN_5_GENEN == 1 hri_gclk_write_GENDIV_reg(hw, GCLK_GENDIV_DIV(CONF_GCLK_GEN_5_DIV) | GCLK_GENDIV_ID(5)); hri_gclk_write_GENCTRL_reg(hw, (CONF_GCLK_GEN_5_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos) | (CONF_GCLK_GEN_5_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_5_OE << GCLK_GENCTRL_OE_Pos) | (CONF_GCLK_GEN_5_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_5_IDC << GCLK_GENCTRL_IDC_Pos) | (CONF_GCLK_GEN_5_GENEN << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_5_SRC | GCLK_GENCTRL_ID(5)); # endif # if CONF_GCLK_GEN_6_GENEN == 1 hri_gclk_write_GENDIV_reg(hw, GCLK_GENDIV_DIV(CONF_GCLK_GEN_6_DIV) | GCLK_GENDIV_ID(6)); hri_gclk_write_GENCTRL_reg(hw, (CONF_GCLK_GEN_6_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos) | (CONF_GCLK_GEN_6_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_6_OE << GCLK_GENCTRL_OE_Pos) | (CONF_GCLK_GEN_6_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_6_IDC << GCLK_GENCTRL_IDC_Pos) | (CONF_GCLK_GEN_6_GENEN << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_6_SRC | GCLK_GENCTRL_ID(6)); # endif # if CONF_GCLK_GEN_7_GENEN == 1 hri_gclk_write_GENDIV_reg(hw, GCLK_GENDIV_DIV(CONF_GCLK_GEN_7_DIV) | GCLK_GENDIV_ID(7)); hri_gclk_write_GENCTRL_reg(hw, (CONF_GCLK_GEN_7_RUNSTDBY << GCLK_GENCTRL_RUNSTDBY_Pos) | (CONF_GCLK_GEN_7_DIVSEL << GCLK_GENCTRL_DIVSEL_Pos) | (CONF_GCLK_GEN_7_OE << GCLK_GENCTRL_OE_Pos) | (CONF_GCLK_GEN_7_OOV << GCLK_GENCTRL_OOV_Pos) | (CONF_GCLK_GEN_7_IDC << GCLK_GENCTRL_IDC_Pos) | (CONF_GCLK_GEN_7_GENEN << GCLK_GENCTRL_GENEN_Pos) | CONF_GCLK_GEN_7_SRC | GCLK_GENCTRL_ID(7)); # endif }
/** * @brief Configure clock sources and the cpu frequency */ static void clk_init(void) { /* enable clocks for the power, sysctrl and gclk modules */ PM->APBAMASK.reg = (PM_APBAMASK_PM | PM_APBAMASK_SYSCTRL | PM_APBAMASK_GCLK); /* adjust NVM wait states, see table 42.30 (p. 1070) in the datasheet */ #if (CLOCK_CORECLOCK > 24000000) PM->APBAMASK.reg |= PM_AHBMASK_NVMCTRL; NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_RWS(1); PM->APBAMASK.reg &= ~PM_AHBMASK_NVMCTRL; #endif /* configure internal 8MHz oscillator to run without prescaler */ SYSCTRL->OSC8M.bit.PRESC = 0; SYSCTRL->OSC8M.bit.ONDEMAND = 1; SYSCTRL->OSC8M.bit.RUNSTDBY = 0; SYSCTRL->OSC8M.bit.ENABLE = 1; while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC8MRDY)) {} #if CLOCK_USE_PLL /* reset the GCLK module so it is in a known state */ GCLK->CTRL.reg = GCLK_CTRL_SWRST; while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {} /* setup generic clock 1 to feed DPLL with 1MHz */ GCLK->GENDIV.reg = (GCLK_GENDIV_DIV(8) | GCLK_GENDIV_ID(1)); GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC8M | GCLK_GENCTRL_ID(1)); GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_GEN(1) | GCLK_CLKCTRL_ID(1) | GCLK_CLKCTRL_CLKEN); while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {} /* enable PLL */ SYSCTRL->DPLLRATIO.reg = (SYSCTRL_DPLLRATIO_LDR(CLOCK_PLL_MUL)); SYSCTRL->DPLLCTRLB.reg = (SYSCTRL_DPLLCTRLB_REFCLK_GCLK); SYSCTRL->DPLLCTRLA.reg = (SYSCTRL_DPLLCTRLA_ENABLE); while(!(SYSCTRL->DPLLSTATUS.reg & (SYSCTRL_DPLLSTATUS_CLKRDY | SYSCTRL_DPLLSTATUS_LOCK))) {} /* select the PLL as source for clock generator 0 (CPU core clock) */ GCLK->GENDIV.reg = (GCLK_GENDIV_DIV(CLOCK_PLL_DIV) | GCLK_GENDIV_ID(0)); GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_FDPLL | GCLK_GENCTRL_ID(0)); #else /* do not use PLL, use internal 8MHz oscillator directly */ GCLK->GENDIV.reg = (GCLK_GENDIV_DIV(CLOCK_DIV) | GCLK_GENDIV_ID(0)); GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC8M | GCLK_GENCTRL_ID(0)); #endif /* make sure we synchronize clock generator 0 before we go on */ while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {} /* Setup Clock generator 2 with divider 1 (32.768kHz) */ GCLK->GENDIV.reg = (GCLK_GENDIV_ID(2) | GCLK_GENDIV_DIV(0)); GCLK->GENCTRL.reg = (GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_SRC_OSCULP32K); while (GCLK->STATUS.bit.SYNCBUSY) {} /* redirect all peripherals to a disabled clock generator (7) by default */ for (int i = 0x3; i <= 0x22; i++) { GCLK->CLKCTRL.reg = ( GCLK_CLKCTRL_ID(i) | GCLK_CLKCTRL_GEN_GCLK7 ); while (GCLK->STATUS.bit.SYNCBUSY) {} } }
// **************************************************************************** void HAL_hardware_init(bool is_servo_reader, bool servo_output_enabled, bool uart_output_enabled) { uint32_t *coarse_p; uint32_t coarse; // FIXME: output diagnostics on UART only if uart_output_enabled is false (void) uart_output_enabled; // ------------------------------------------------ // Perform GPIO initialization as early as possible HAL_gpio_set(HAL_GPIO_BLANK); HAL_gpio_out(HAL_GPIO_BLANK); HAL_gpio_clear(HAL_GPIO_SWITCHED_LIGHT_OUTPUT); HAL_gpio_out(HAL_GPIO_SWITCHED_LIGHT_OUTPUT); HAL_gpio_out(HAL_GPIO_XLAT); HAL_gpio_out(HAL_GPIO_SIN); HAL_gpio_pmuxen(HAL_GPIO_SIN); HAL_gpio_out(HAL_GPIO_SCK); HAL_gpio_pmuxen(HAL_GPIO_SCK); HAL_gpio_in(HAL_GPIO_CH3); HAL_gpio_pmuxen(HAL_GPIO_CH3); HAL_gpio_in(HAL_GPIO_PUSH_BUTTON); HAL_gpio_pmuxen(HAL_GPIO_USB_DM); HAL_gpio_pmuxen(HAL_GPIO_USB_DP); // Turn the status LED on to signify we are initializing HAL_gpio_out(HAL_GPIO_LED); HAL_gpio_out(HAL_GPIO_LED2); HAL_gpio_set(HAL_GPIO_LED); HAL_gpio_set(HAL_GPIO_LED2); // ------------------------------------------------ // Configure GPIOs shared between servo inputs, servo output and UART // Output UART Tx on OUT in all cases when the servo output is disabled if (servo_output_enabled) { HAL_gpio_out(HAL_GPIO_OUT); HAL_gpio_pmuxen(HAL_GPIO_OUT); } else { HAL_gpio_out(HAL_GPIO_TX_ON_OUT); HAL_gpio_pmuxen(HAL_GPIO_TX_ON_OUT); tx_pad = HAL_GPIO_TX_ON_OUT.txpo; } if (is_servo_reader) { HAL_gpio_in(HAL_GPIO_ST); HAL_gpio_pmuxen(HAL_GPIO_ST); HAL_gpio_in(HAL_GPIO_TH); HAL_gpio_pmuxen(HAL_GPIO_TH); } else { HAL_gpio_in(HAL_GPIO_RX); HAL_gpio_pmuxen(HAL_GPIO_RX); // In case we have a UART and a servi output, TH is unused. We can // use TH as Tx signal, just like in the LPC812 Mk4 light controller if (servo_output_enabled) { HAL_gpio_out(HAL_GPIO_TX_ON_TH); HAL_gpio_pmuxen(HAL_GPIO_TX_ON_TH); tx_pad = HAL_GPIO_TX_ON_TH.txpo; } else { HAL_gpio_in(HAL_GPIO_TH); HAL_gpio_pmuxen(HAL_GPIO_TH); } } // ------------------------------------------------ // Since we intend to run at 48 MHz system clock, we neeed to conigure // one wait state for the flash according to the datasheet. NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_RWS(1); // ------------------------------------------------ // Set up the PLL to provide a 48 MHz system clock SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD33RDY | SYSCTRL_INTFLAG_BOD33DET | SYSCTRL_INTFLAG_DFLLRDY; SYSCTRL->DFLLCTRL.reg = 0; while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY)); SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_MUL(48000); // Load PLL calibration values from NVRAM coarse_p = (uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR; coarse = (*coarse_p & FUSES_DFLL48M_COARSE_CAL_Msk) >> FUSES_DFLL48M_COARSE_CAL_Pos; SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(512); SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE | SYSCTRL_DFLLCTRL_USBCRM | SYSCTRL_DFLLCTRL_BPLCKC | SYSCTRL_DFLLCTRL_STABLE | SYSCTRL_DFLLCTRL_CCDIS; while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY)); // ------------------------------------------------ // Reset the generic clock control block GCLK->CTRL.reg = GCLK_CTRL_SWRST; while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); // Setup GENCLK0 to run at 48 MHz. This clock is used for high speed // peripherals such as SPI, USB and UART GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(1); GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(0) | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN; while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); // Setup GENCLK1 to run at 2 MHz. We use GENCLK1 for timers that need // microsecond resolution (e.g. servo output and servo reader). // We derive the clock from the 48 MHz PLL, so we use a clock divider of // 24 GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(24); GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(1) | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN; while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); // ------------------------------------------------ // Turn on power to the peripherals we use PM->APBCMASK.reg = UART_SERCOM_APBCMASK | SPI_SERCOM_APBCMASK | PM_APBAMASK_EIC | PM_APBCMASK_EVSYS | PM_APBCMASK_TCC0 | PM_APBCMASK_TC4 | PM_APBBMASK_USB; // ------------------------------------------------ // Initialize the Event System // Use GLKGEN0 (48 MHz) as clock source for the EVSYS0..2 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EVSYS_0 | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0); GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EVSYS_1 | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0); GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_EVSYS_2 | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0); // Always turn on the Generic Clock within EVSYS EVSYS->CTRL.reg = EVSYS_CTRL_GCLKREQ; // ------------------------------------------------ // Configure the SYSTICK to create an interrupt every 1 millisecond SysTick_Config(48000); NVIC_SetPriority(SysTick_IRQn, 0); // ------------------------ // The UART Tx can be used for diagnostics output if it is not in use. // The pin is in use when HAL gets passed "uart_output_enabled==true" // (UART used for pre-processor, winch or slave output), or when we // have a servo reader and the servo output is enabled. // // Or in other words: the UART can output diagnostics on the OUT pin // when it is not in use, or the UART can output diagnostics on the TH/Tx // pin when we the UART reader is in use and no UART output function is // configured. diagnostics_on_uart = !uart_output_enabled; if (is_servo_reader) { if (servo_output_enabled) { diagnostics_on_uart = false; } } __enable_irq(); }
void uart_init(uint32_t baud) { uint32_t UART_CLKGEN_F = 8000000UL; uint64_t br = (uint64_t)65536 * (UART_CLKGEN_F - 16 * baud) / UART_CLKGEN_F; //enable GPS pins // SaLPinMode(MTK3339_RX_PIN,INPUT); // SaLPinMode(MTK3339_TX_PIN,OUTPUT); SYSCTRL->OSC8M.reg -= SYSCTRL_OSC8M_ENABLE; SYSCTRL->OSC8M.reg -= SYSCTRL_OSC8M_PRESC_3; SYSCTRL->OSC8M.reg |= SYSCTRL_OSC8M_ENABLE; //portB22->PINCFG->reg = 0x44; // portB23->PINCFG->reg = 0x44; // GPS pin configs ((Port *)PORT)->Group[1].PINCFG[22].reg = 0x41; ((Port *)PORT)->Group[1].PINCFG[23].reg = 0x41; ((Port *)PORT)->Group[1].PMUX[11].reg = 0x32; // usb port configs // ((Port *)PORT)->Group[0].PINCFG[24].reg = 0x41; // ((Port *)PORT)->Group[0].PINCFG[25].reg = 0x41; // ((Port *)PORT)->Group[0].PMUX[12].reg = 0x24; //enable power to sercom 5 module PM->APBCMASK.reg |= PM_APBCMASK_SERCOM5; //enable and configure the sercom clock GCLK->GENDIV.reg = GCLK_GENDIV_ID(3) | GCLK_GENDIV_DIV(1); GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(3) | GCLK_GENCTRL_SRC_OSC8M | GCLK_GENCTRL_IDC | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN; GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM5_CORE | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_CLKEN; // GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOMX_SLOW | // GCLK_CLKCTRL_GEN_GCLK3 | // GCLK_CLKCTRL_CLKEN; GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM3_CORE | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_CLKEN; //configure the sercom module for the gps (sercom 5) SERCOM5->USART.CTRLA.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE_USART_INT_CLK | SERCOM_USART_CTRLA_RXPO(3) | SERCOM_USART_CTRLA_TXPO(1); uart_sync(SERCOM5); SERCOM5->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/); // SERCOM_USART_CTRLB_SFDE; uart_sync(SERCOM5); SERCOM5->USART.BAUD.reg = (uint16_t)br; uart_sync(SERCOM5); SERCOM5->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; uart_sync(SERCOM5); SaLInitUsart(&USART_0,SERCOM5); }