summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/samd/mcu/samd21/clock_config.c41
-rw-r--r--ports/samd/mcu/samd51/clock_config.c55
2 files changed, 56 insertions, 40 deletions
diff --git a/ports/samd/mcu/samd21/clock_config.c b/ports/samd/mcu/samd21/clock_config.c
index 4c05dd7cc..d84ee5267 100644
--- a/ports/samd/mcu/samd21/clock_config.c
+++ b/ports/samd/mcu/samd21/clock_config.c
@@ -52,7 +52,7 @@ uint32_t get_peripheral_freq(void) {
void set_cpu_freq(uint32_t cpu_freq_arg) {
- // Set 1 waitstate to be safe
+ // Set 1 wait state to be safe
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS(1);
int div = MAX(DFLL48M_FREQ / cpu_freq_arg, 1);
@@ -75,7 +75,7 @@ void set_cpu_freq(uint32_t cpu_freq_arg) {
while (GCLK->STATUS.bit.SYNCBUSY) {
}
// configure the FDPLL96
- // CtrlB: Set the ref ource to GCLK, set the Wakup-Fast Flag.
+ // CtrlB: Set the ref source to GCLK, set the Wakeup-Fast Flag.
SYSCTRL->DPLLCTRLB.reg = SYSCTRL_DPLLCTRLB_REFCLK_GCLK | SYSCTRL_DPLLCTRLB_WUF;
// Set the FDPLL ratio and enable the DPLL.
int ldr = cpu_freq / FDPLL_REF_FREQ;
@@ -106,25 +106,36 @@ void set_cpu_freq(uint32_t cpu_freq_arg) {
while (GCLK->STATUS.bit.SYNCBUSY) {
}
}
- // Set 0 waitstates for slower CPU clock
+ // Set 0 wait states for slower CPU clock
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_MANW | NVMCTRL_CTRLB_RWS(cpu_freq > 24000000 ? 1 : 0);
SysTick_Config(cpu_freq / 1000);
}
void check_usb_recovery_mode(void) {
#if !MICROPY_HW_XOSC32K
- mp_hal_delay_ms(500);
- // Check USB status. If not connected, switch DFLL48M back to open loop
- if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg == 0) {
- // Set/keep the open loop mode of the device.
- SYSCTRL->DFLLVAL.reg = dfll48m_calibration;
- SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE;
+ // Check USB status for up to 1 second. If not connected,
+ // switch DFLL48M back to open loop
+ for (int i = 0; i < 100; i++) {
+ if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg != 0) {
+ return;
+ }
+ mp_hal_delay_ms(10);
}
+ // Set/keep the open loop mode of the device.
+ SYSCTRL->DFLLVAL.reg = dfll48m_calibration;
+ SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_CCDIS | SYSCTRL_DFLLCTRL_ENABLE;
#endif // MICROPY_HW_XOSC32K
}
// Purpose of the #defines for the clock configuration.
//
+// The CPU is either driven by the FDPLL96 oscillator for f >= 48MHz,
+// or by the DFLL48M for lower frequencies. The FDPLL96 takes 32768 Hz
+// as reference frequency, supplied through GCLK1.
+//
+// DFLL48M is used for the peripheral clock, e.g. for PWM, UART, SPI, I2C.
+// DFLL48M is either free running, or controlled by the 32kHz crystal, or
+// Synchronized with the USB clock.
// Both CPU and peripheral devices are clocked by the DFLL48M clock.
// DFLL48M is either free running, or controlled by the 32kHz crystal, or
// Synchronized with the USB clock.
@@ -136,7 +147,7 @@ void check_usb_recovery_mode(void) {
// The crystal is used, unless MICROPY_HW_MCU_OSC32KULP is set.
// In that case GCLK1 (and the CPU clock) is driven by the 32K Low power oscillator.
// The reason for offering this option is a design flaw of the Adafruit
-// Feather boards, where the RGB Led and Debug signals interfere with the
+// Feather boards, where the RGB LED and Debug signals interfere with the
// crystal, causing the CPU to fail if it is driven by the crystal.
//
// If MICROPY_HW_XOSC32K = 0, the 32kHz signal for GCLK1 (and the CPU) is
@@ -144,10 +155,10 @@ void check_usb_recovery_mode(void) {
//
// If MICROPY_HW_DFLL_USB_SYNC = 0, the DFLL48M oscillator is free running using
// the pre-configured trim values. In that mode, the peripheral clock is
-// not exactly 48Mhz and has a substantional temperature drift.
+// not exactly 48Mhz and has a substitutional temperature drift.
//
// If MICROPY_HW_DFLL_USB_SYNC = 1, the DFLL48 is synchronized with the 1 kHz USB sync
-// signal. If after boot there is no USB sync within 500ms, the configuration falls
+// signal. If after boot there is no USB sync within 1000 ms, the configuration falls
// back to a free running 48Mhz oscillator.
//
// In all modes, the 48MHz signal has a substantial jitter, largest when
@@ -181,7 +192,7 @@ void init_clocks(uint32_t cpu_freq) {
NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz
#if MICROPY_HW_XOSC32K
- // Set up OSC32K according datasheet 17.6.3
+ // Set up OSC32K according data sheet 17.6.3
SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP(0x3) | SYSCTRL_XOSC32K_EN32K |
SYSCTRL_XOSC32K_XTALEN;
SYSCTRL->XOSC32K.bit.ENABLE = 1;
@@ -211,12 +222,12 @@ void init_clocks(uint32_t cpu_freq) {
while (GCLK->STATUS.bit.SYNCBUSY) {
}
- // Enable access to the DFLLCTRL reg acc. to Errata 1.2.1
+ // Enable access to the DFLLCTRL register according to Errata 1.2.1
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
while (SYSCTRL->PCLKSR.bit.DFLLRDY == 0) {
}
// Step 2: Set the coarse and fine values.
- // Get the coarse value from the calib data. In case it is not set,
+ // Get the coarse value from the calibration data. In case it is not set,
// set a midrange value.
uint32_t coarse = (*((uint32_t *)FUSES_DFLL48M_COARSE_CAL_ADDR) & FUSES_DFLL48M_COARSE_CAL_Msk)
>> FUSES_DFLL48M_COARSE_CAL_Pos;
diff --git a/ports/samd/mcu/samd51/clock_config.c b/ports/samd/mcu/samd51/clock_config.c
index 50912b77e..b30cc46f2 100644
--- a/ports/samd/mcu/samd51/clock_config.c
+++ b/ports/samd/mcu/samd51/clock_config.c
@@ -117,27 +117,32 @@ void set_cpu_freq(uint32_t cpu_freq_arg) {
void check_usb_recovery_mode(void) {
#if !MICROPY_HW_XOSC32K
- mp_hal_delay_ms(500);
- // Check USB status. If not connected, switch DFLL48M back to open loop
- if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg == 0) {
- // as per Errata 2.8.3
- OSCCTRL->DFLLMUL.reg = 0;
- while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) {
- }
- // Set the mode to open loop mode
- OSCCTRL->DFLLCTRLB.reg = 0;
- while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) {
- }
- OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_RUNSTDBY | OSCCTRL_DFLLCTRLA_ENABLE;
- while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) {
- }
- OSCCTRL->DFLLVAL.reg = dfll48m_calibration; // Reload DFLLVAL register
- while (OSCCTRL->DFLLSYNC.bit.DFLLVAL == 1) {
- }
- // Set the mode to open loop mode
- OSCCTRL->DFLLCTRLB.reg = 0;
- while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) {
+ // Check USB status for up to 1 second. If not connected,
+ // switch DFLL48M back to open loop
+ for (int i = 0; i < 100; i++) {
+ if (USB->DEVICE.DeviceEndpoint[0].EPCFG.reg != 0) {
+ return;
}
+ mp_hal_delay_ms(10);
+ }
+ // No connection. Switch back to open loop mode.
+ // as per Errata 2.8.3
+ OSCCTRL->DFLLMUL.reg = 0;
+ while (OSCCTRL->DFLLSYNC.bit.DFLLMUL == 1) {
+ }
+ // Set the mode to open loop mode
+ OSCCTRL->DFLLCTRLB.reg = 0;
+ while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) {
+ }
+ OSCCTRL->DFLLCTRLA.reg = OSCCTRL_DFLLCTRLA_RUNSTDBY | OSCCTRL_DFLLCTRLA_ENABLE;
+ while (OSCCTRL->DFLLSYNC.bit.ENABLE == 1) {
+ }
+ OSCCTRL->DFLLVAL.reg = dfll48m_calibration; // Reload DFLLVAL register
+ while (OSCCTRL->DFLLSYNC.bit.DFLLVAL == 1) {
+ }
+ // Set the mode to open loop mode
+ OSCCTRL->DFLLCTRLB.reg = 0;
+ while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB == 1) {
}
#endif // MICROPY_HW_XOSC32K
}
@@ -169,10 +174,10 @@ void check_usb_recovery_mode(void) {
//
// If MICROPY_HW_DFLL_USB_SYNC = 0, the DFLL48M oscillator is free running using
// the pre-configured trim values. In that mode, the peripheral clock is
-// not exactly 48Mhz and has a substantional temperature drift.
+// not exactly 48Mhz and has a substitutional temperature drift.
//
// If MICROPY_HW_DFLL_USB_SYNC = 1, the DFLL48 is synchronized with the 1 kHz USB sync
-// signal. If after boot there is no USB sync within 500ms, the configuration falls
+// signal. If after boot there is no USB sync within 1000 ms, the configuration falls
// back to a free running 48Mhz oscillator.
//
// In all modes, the 48MHz signal has a substantial jitter, largest when
@@ -223,16 +228,16 @@ void init_clocks(uint32_t cpu_freq) {
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K;
// Setup XOSC32K
OSC32KCTRL->INTFLAG.reg = OSC32KCTRL_INTFLAG_XOSC32KRDY | OSC32KCTRL_INTFLAG_XOSC32KFAIL;
- OSC32KCTRL->CFDCTRL.bit.CFDEN = 1; // Fall back to internal Osc on crystal fail
+ OSC32KCTRL->CFDCTRL.bit.CFDEN = 1; // Fall back to internal oscillator on crystal fail
OSC32KCTRL->XOSC32K.reg =
OSC32KCTRL_XOSC32K_CGM_HS |
OSC32KCTRL_XOSC32K_XTALEN |
OSC32KCTRL_XOSC32K_EN32K |
OSC32KCTRL_XOSC32K_EN1K |
OSC32KCTRL_XOSC32K_RUNSTDBY |
- OSC32KCTRL_XOSC32K_STARTUP(4) |
+ OSC32KCTRL_XOSC32K_STARTUP(3) |
OSC32KCTRL_XOSC32K_ENABLE;
- // make sure osc32kcrtl is ready
+ // Wait until the oscillator is running and stable
while (OSC32KCTRL->STATUS.bit.XOSC32KRDY == 0) {
}