samd/mcu: Reduce the startup time after hard reset.
With Crystal: set the crystal startup wait time to 1 second. It was 2 seconds before, and that seeemed too long. With USB-Sync: scan for up to 1 second for the USB to be registered and carry on with boot as soon as it it. Before, the code just waited for 500ms. Side change: improve related comments. Signed-off-by: robert-hh <robert@hammelrath.com>
This commit is contained in:
parent
984456731b
commit
2a38531d73
|
@ -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) {
|
||||
// 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;
|
||||
|
|
|
@ -117,9 +117,15 @@ 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) {
|
||||
// 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) {
|
||||
|
@ -138,7 +144,6 @@ void check_usb_recovery_mode(void) {
|
|||
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) {
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue