samd/machine_rtc: Add the machine.RTC class.

Methods implemented are:
- rtc.init(date)
- rtc.datetime([new_date])
- rtc.calibration(value)

The presence of this class can be controlled by MICROPY_PY_MACHINE_RTC.  If
the RTC module is used, the time module uses the RTC as well.

For boards without a 32kHz crystal, using RTC makes no sense, since it will
then use the ULP32K oscillator, which is not precise at all.  Therefore, it
will by default only be enabled for boards using a crystal, but can be
enabled in the respective mpconfigboard.h.
This commit is contained in:
robert-hh
2022-09-15 15:58:54 +02:00
committed by Damien George
parent be31fde012
commit fc9d66fac6
11 changed files with 263 additions and 17 deletions

View File

@@ -141,7 +141,7 @@ void init_clocks(uint32_t cpu_freq) {
// GCLK3: 1Mhz for the us-counter (TC4/TC5)
// GCLK4: 32kHz from crystal, if present
// GCLK5: 48MHz from DFLL for USB
// GCLK8: 1kHz clock for WDT
// GCLK8: 1kHz clock for WDT and RTC
NVMCTRL->CTRLB.bit.MANW = 1; // errata "Spurious Writes"
NVMCTRL->CTRLB.bit.RWS = 1; // 1 read wait state for 48MHz
@@ -203,6 +203,11 @@ void init_clocks(uint32_t cpu_freq) {
SYSCTRL_DFLLCTRL_BPLCKC | SYSCTRL_DFLLCTRL_ENABLE;
while (SYSCTRL->PCLKSR.bit.DFLLLCKF == 0) {
}
// Set GCLK8 to 1 kHz.
GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32);
GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K | GCLK_GENCTRL_ID(8);
while (GCLK->STATUS.bit.SYNCBUSY) {
}
#else // MICROPY_HW_XOSC32K
@@ -242,6 +247,11 @@ void init_clocks(uint32_t cpu_freq) {
GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(1);
while (GCLK->STATUS.bit.SYNCBUSY) {
}
// Set GCLK8 to 1 kHz.
GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32);
GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8);
while (GCLK->STATUS.bit.SYNCBUSY) {
}
#endif // MICROPY_HW_XOSC32K
@@ -252,11 +262,6 @@ void init_clocks(uint32_t cpu_freq) {
GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M | GCLK_GENCTRL_ID(3);
while (GCLK->STATUS.bit.SYNCBUSY) {
}
// Set GCLK8 to 1 kHz.
GCLK->GENDIV.reg = GCLK_GENDIV_ID(8) | GCLK_GENDIV_DIV(32);
GCLK->GENCTRL.reg = GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(8);
while (GCLK->STATUS.bit.SYNCBUSY) {
}
}
void enable_sercom_clock(int id) {

View File

@@ -28,6 +28,12 @@
#define MICROPY_HW_UART_TXBUF (1)
#endif
#ifndef MICROPY_PY_MACHINE_RTC
#if MICROPY_HW_XOSC32K
#define MICROPY_PY_MACHINE_RTC (1)
#endif
#endif
#define CPU_FREQ (48000000)
#define DFLL48M_FREQ (48000000)
#define MAX_CPU_FREQ (48000000)

View File

@@ -215,16 +215,19 @@ void init_clocks(uint32_t cpu_freq) {
#if MICROPY_HW_XOSC32K
// OSCILLATOR CONTROL
// Enable the clock for RTC
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K;
// Setup XOSC32K
OSC32KCTRL->INTFLAG.reg = OSC32KCTRL_INTFLAG_XOSC32KRDY | OSC32KCTRL_INTFLAG_XOSC32KFAIL;
OSC32KCTRL->XOSC32K.bit.CGM = OSC32KCTRL_XOSC32K_CGM_HS_Val;
OSC32KCTRL->XOSC32K.bit.XTALEN = 1; // 0: Generator 1: Crystal
OSC32KCTRL->XOSC32K.bit.EN32K = 1;
OSC32KCTRL->XOSC32K.bit.ONDEMAND = 0;
OSC32KCTRL->XOSC32K.bit.RUNSTDBY = 1;
OSC32KCTRL->XOSC32K.bit.STARTUP = 4;
OSC32KCTRL->CFDCTRL.bit.CFDEN = 1; // Fall back to internal Osc on crystal fail
OSC32KCTRL->XOSC32K.bit.ENABLE = 1;
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_ENABLE;
// make sure osc32kcrtl is ready
while (OSC32KCTRL->STATUS.bit.XOSC32KRDY == 0) {
}
@@ -270,6 +273,9 @@ void init_clocks(uint32_t cpu_freq) {
#else // MICROPY_HW_XOSC32K
// Enable the clock for RTC
OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K;
// Derive GCLK1 from DFLL48M at DPLL0_REF_FREQ as defined in mpconfigboard.h (e.g. 32768 Hz)
GCLK->GENCTRL[1].reg = ((DFLL48M_FREQ + DPLLx_REF_FREQ / 2) / DPLLx_REF_FREQ) << GCLK_GENCTRL_DIV_Pos
| GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL;

View File

@@ -28,6 +28,12 @@
#define MICROPY_PY_URANDOM_SEED_INIT_FUNC (trng_random_u32())
unsigned long trng_random_u32(void);
#ifndef MICROPY_PY_MACHINE_RTC
#if MICROPY_HW_XOSC32K
#define MICROPY_PY_MACHINE_RTC (1)
#endif
#endif
// Due to a limitation in the TC counter for us, the ticks period is 2**29
#define MICROPY_PY_UTIME_TICKS_PERIOD (0x20000000)