void rtcInit(void){ SUPC->SUPC_CR = SUPC_CR_KEY(0xA5) | SUPC_CR_XTALSEL_CRYSTAL_SEL; //enable oscillator RTC->RTC_IDR = 0x1f; RTC->RTC_IER = RTC_IER_SECEN; //enable interrupt NVIC_EnableIRQ(RTC_IRQn); }
/** * \brief Switch slow clock source selection to external 32k (Xtal or Bypass) oscillator. * This function disables the PLLs. * * \note Switching sclk back to 32krc is only possible by shutting down the VDDIO power supply. * * \param ul_bypass 0 for Xtal, 1 for bypass. */ void supc_switch_sclk_to_32kxtal(Supc *p_supc, uint32_t ul_bypass) { /* Set Bypass mode if required */ if (ul_bypass == 1) { p_supc->SUPC_MR |= SUPC_MR_KEY(SUPC_KEY) | SUPC_MR_OSCBYPASS; } p_supc->SUPC_CR |= SUPC_CR_KEY(SUPC_KEY) | SUPC_CR_XTALSEL; }
/** * \brief Enable Backup Mode. * Enter condition: WFE/(VROFF bit = 1) + (SLEEPDEEP bit = 1) */ void pmc_enable_backupmode(void) { SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; #if SAM4S SUPC->SUPC_CR = SUPC_CR_KEY(0xA5u) | SUPC_CR_VROFF_STOP_VREG; #else __WFE(); #endif }
/** * \brief Enable Backup Mode. Enter condition: WFE/(VROFF bit = 1) + * (SLEEPDEEP bit = 1) */ void pmc_enable_backupmode(void) { SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; #if (SAM4S || SAM4E || SAM4N) SUPC->SUPC_CR = SUPC_CR_KEY(SUPC_KEY_VALUE) | SUPC_CR_VROFF_STOP_VREG; #else __WFE(); #endif }
/** * \brief Switch slow clock source selection to external 32k (Xtal or Bypass). * * \note This function disables the PLLs. * * \note Switching SCLK back to 32krc is only possible by shutting down the VDDIO * power supply. * * \param ul_bypass 0 for Xtal, 1 for bypass. */ void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass) { /* Set Bypass mode if required */ if (ul_bypass == 1) { SUPC->SUPC_MR |= SUPC_MR_KEY(SUPC_KEY_VALUE) | SUPC_MR_OSCBYPASS; } SUPC->SUPC_CR |= SUPC_CR_KEY(SUPC_KEY_VALUE) | SUPC_CR_XTALSEL; }
/* TBD: move it to SUPC driver. */ extern void SUPC_SelectExtCrystal32K(void) { /* Select XTAL 32k instead of internal slow RC 32k for slow clock */ if ( (SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST ) { SUPC->SUPC_CR = SUPC_CR_KEY(0xA5u) | SUPC_CR_XTALSEL_CRYSTAL_SEL; while( !(SUPC->SUPC_SR & SUPC_SR_OSCSEL) ); } }
void pmc_sleep(int sleep_mode) { switch (sleep_mode) { case SAM_PM_SMODE_SLEEP_WFI: case SAM_PM_SMODE_SLEEP_WFE: #if (SAM4S || SAM4E) SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP; cpu_irq_enable(); __WFI(); break; #else PMC->PMC_FSMR &= (uint32_t)~PMC_FSMR_LPM; SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP; cpu_irq_enable(); if (sleep_mode == SAM_PM_SMODE_SLEEP_WFI) __WFI(); else __WFE(); break; #endif case SAM_PM_SMODE_WAIT: { uint32_t mor, pllr0, pllr1, mckr; cpu_irq_disable(); b_is_fastrc_used = true; pmc_save_clock_settings(&mor, &pllr0, &pllr1, &mckr); /* Enter wait mode */ cpu_irq_enable(); pmc_enable_waitmode(); cpu_irq_disable(); pmc_restore_clock_setting(mor, pllr0, pllr1, mckr); b_is_fastrc_used = false; if (callback_clocks_restored) { callback_clocks_restored(); callback_clocks_restored = NULL; } cpu_irq_enable(); break; } case SAM_PM_SMODE_BACKUP: SCB->SCR |= SCR_SLEEPDEEP; #if (SAM4S || SAM4E) SUPC->SUPC_CR = SUPC_CR_KEY(0xA5u) | SUPC_CR_VROFF_STOP_VREG; cpu_irq_enable(); __WFI() ; #else cpu_irq_enable(); __WFE() ; #endif break; } }
void clock_init(void) { uint32_t timeout; /* Disable watchdog */ WDT_MR = BV(WDT_WDDIS); /* Set 4 wait states for flash access, needed for higher CPU clock rates */ EEFC_FMR = EEFC_FMR_FWS(3); // Select external slow clock if (!(SUPC_SR & BV(SUPC_SR_OSCSEL))) { SUPC_CR = BV(SUPC_CR_XTALSEL) | SUPC_CR_KEY(0xA5); while (!(SUPC_SR & BV(SUPC_SR_OSCSEL))); } // Initialize main oscillator if (!(CKGR_MOR & BV(CKGR_MOR_MOSCSEL))) { CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSC_COUNT | BV(CKGR_MOR_MOSCRCEN) | BV(CKGR_MOR_MOSCXTEN); timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MOSCXTS)) && --timeout); } // Switch to external oscillator CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSC_COUNT | BV(CKGR_MOR_MOSCRCEN) | BV(CKGR_MOR_MOSCXTEN) | BV(CKGR_MOR_MOSCSEL); timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MOSCSELS)) && --timeout); PMC_MCKR = (PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_MASK) | PMC_MCKR_CSS_MAIN_CLK; timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MCKRDY)) && --timeout); // Initialize and enable PLL clock CKGR_PLLR = evaluate_pll() | BV(CKGR_PLLR_STUCKTO1) | CKGR_PLLR_PLLCOUNT(0x1); timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_LOCK)) && --timeout); PMC_MCKR = PMC_MCKR_CSS_MAIN_CLK; timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MCKRDY)) && --timeout); PMC_MCKR = PMC_MCKR_CSS_PLL_CLK; timeout = CLOCK_TIMEOUT; while (!(PMC_SR & BV(PMC_SR_MCKRDY)) && --timeout); /* Enable clock on PIO for inputs */ PMC_PCER = BV(PIOA_ID) | BV(PIOB_ID) | BV(PIOC_ID); }
/** * \brief Performs the low-level initialization of the chip. * This includes EFC and master clock configuration. * It also enable a low level on the pin NRST triggers a user reset. */ extern WEAK void LowLevelInit( void ) { uint32_t timeout = 0; /* Set 3 FWS for Embedded Flash Access */ EFC->EEFC_FMR = EEFC_FMR_FWS(3); /* Select external slow clock */ if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) { SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5)); timeout = 0; while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) ); } /* Initialize main oscillator */ if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) { PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; timeout = 0; while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT)); } /* Switch to 3-20MHz Xtal oscillator */ PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; timeout = 0; while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT)); PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); /* Initialize PLLA */ PMC->CKGR_PLLAR = BOARD_PLLAR; timeout = 0; while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT)); /* Switch to main clock */ PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); PMC->PMC_MCKR = BOARD_MCKR ; for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); }
/** * \brief Switch off the voltage regulator to put the device in backup mode. * * \param p_supc Pointer to a SUPC instance. */ void supc_enable_backup_mode(Supc *p_supc) { p_supc->SUPC_CR = SUPC_CR_KEY(SUPC_KEY) | SUPC_CR_VROFF; }