diff --git a/cpu/sam0_common/periph/rtc_rtt.c b/cpu/sam0_common/periph/rtc_rtt.c index bb0c2d6705..3d3d1f1b52 100644 --- a/cpu/sam0_common/periph/rtc_rtt.c +++ b/cpu/sam0_common/periph/rtc_rtt.c @@ -25,6 +25,7 @@ */ #include +#include #include "periph/rtc.h" #include "periph/rtt.h" #include "periph_conf.h" @@ -215,10 +216,70 @@ static void _rtt_clock_setup(void) #endif /* MODULE_PERIPH_RTT */ #endif /* !CPU_COMMON_SAMD21 - Clock Setup */ +#ifdef MODULE_PERIPH_RTC_MEM +/* first two GP registers are shared with COMP[0] / ALARM[0] */ +#ifdef RTC_MODE2_CTRLB_GP2EN +#define RTC_GPR_START (2) +#else +#define RTC_GPR_START (0) +#endif + +#define RTC_GPR_NUM_AVAIL (RTC_GPR_NUM - RTC_GPR_START) +#define RTC_MEM_SIZE (RTC_GPR_NUM_AVAIL * sizeof(uint32_t)) + +size_t rtc_mem_size(void) +{ + return RTC_MEM_SIZE; +} + +static void _read_gp(uint32_t *dst) +{ + for (unsigned i = RTC_GPR_START; i < RTC_GPR_NUM; ++i) { + dst[i - RTC_GPR_START] = RTC->MODE0.GP[i].reg; + } +} + +static void _write_gp(const uint32_t *src) +{ + for (unsigned i = RTC_GPR_START; i < RTC_GPR_NUM; ++i) { + _wait_syncbusy(); + RTC->MODE0.GP[i].reg = src[i - RTC_GPR_START]; + } +} + +void rtc_mem_read(unsigned offset, void *data, size_t len) +{ + uint32_t tmp[RTC_GPR_NUM_AVAIL]; + + if (offset + len > RTC_MEM_SIZE) { + assert(0); + return; + } + + _read_gp(tmp); + memcpy(data, ((uint8_t *)tmp) + offset, len); +} + +void rtc_mem_write(unsigned offset, void *data, size_t len) +{ + uint32_t tmp[RTC_GPR_NUM_AVAIL]; + + if (offset + len > RTC_MEM_SIZE) { + assert(0); + return; + } + + _read_gp(tmp); + memcpy(((uint8_t *)tmp) + offset, data, len); + _write_gp(tmp); +} +#endif /* MODULE_PERIPH_RTC_MEM */ + #ifdef MODULE_PERIPH_RTC static void _rtc_init(void) { #ifdef REG_RTC_MODE2_CTRLA + /* skip reset if already in RTC mode */ if (RTC->MODE2.CTRLA.bit.MODE == RTC_MODE2_CTRLA_MODE_CLOCK_Val) { return; } @@ -229,6 +290,11 @@ static void _rtc_init(void) RTC->MODE2.CTRLA.reg = RTC_MODE2_CTRLA_PRESCALER_DIV1024 /* CLK_RTC_CNT = 1KHz / 1024 -> 1Hz */ | RTC_MODE2_CTRLA_CLOCKSYNC /* Clock Read Synchronization Enable */ | RTC_MODE2_CTRLA_MODE_CLOCK; +#ifdef RTC_MODE2_CTRLB_GP2EN + /* RTC driver does not use COMP[1] or ALARM[1] */ + /* Use second set of Compare registers as general purpose register */ + RTC->MODE2.CTRLB.reg = RTC_MODE2_CTRLB_GP2EN; +#endif #else if (RTC->MODE2.CTRL.bit.MODE == RTC_MODE2_CTRL_MODE_CLOCK_Val) { return; @@ -268,10 +334,26 @@ void rtc_init(void) #ifdef MODULE_PERIPH_RTT void rtt_init(void) { + _rtt_clock_setup(); _poweron(); + +#ifdef MODULE_PERIPH_RTC_MEM + uint32_t backup[RTC_GPR_NUM_AVAIL]; + _read_gp(backup); +#endif + _rtt_reset(); +#ifdef MODULE_PERIPH_RTC_MEM +#ifdef RTC_MODE2_CTRLB_GP2EN + /* RTC driver does not use COMP[1] or ALARM[1] */ + /* Use second set of Compare registers as general purpose register */ + RTC->MODE2.CTRLB.reg = RTC_MODE2_CTRLB_GP2EN; +#endif + _write_gp(backup); +#endif /* MODULE_PERIPH_RTC_MEM */ + /* set 32bit counting mode & enable the RTC */ #ifdef REG_RTC_MODE0_CTRLA RTC->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_MODE(0) diff --git a/cpu/samd5x/Kconfig b/cpu/samd5x/Kconfig index 07f6a9d150..0531548781 100644 --- a/cpu/samd5x/Kconfig +++ b/cpu/samd5x/Kconfig @@ -15,6 +15,7 @@ config CPU_COMMON_SAMD5X select HAS_PERIPH_DMA select HAS_PERIPH_GPIO_TAMPER_WAKE select HAS_PERIPH_HWRNG + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_SPI_ON_QSPI config CPU_FAM_SAMD51 diff --git a/cpu/samd5x/Makefile.features b/cpu/samd5x/Makefile.features index ff059dc677..e024c5e1bc 100644 --- a/cpu/samd5x/Makefile.features +++ b/cpu/samd5x/Makefile.features @@ -4,6 +4,7 @@ FEATURES_PROVIDED += periph_hwrng FEATURES_PROVIDED += backup_ram FEATURES_PROVIDED += cortexm_mpu FEATURES_PROVIDED += periph_gpio_tamper_wake +FEATURES_PROVIDED += periph_rtc_mem FEATURES_PROVIDED += periph_spi_on_qspi include $(RIOTCPU)/sam0_common/Makefile.features diff --git a/cpu/saml21/Kconfig b/cpu/saml21/Kconfig index b9091cc836..97c99c2540 100644 --- a/cpu/saml21/Kconfig +++ b/cpu/saml21/Kconfig @@ -13,6 +13,7 @@ config CPU_COMMON_SAML21 select HAS_CPU_SAML21 select HAS_PERIPH_DMA select HAS_PERIPH_GPIO_FAST_READ + select HAS_PERIPH_RTC_MEM config CPU_FAM_SAML21 bool diff --git a/cpu/saml21/Makefile.features b/cpu/saml21/Makefile.features index cdd972d64c..85685fb27f 100644 --- a/cpu/saml21/Makefile.features +++ b/cpu/saml21/Makefile.features @@ -10,6 +10,7 @@ FEATURES_PROVIDED += periph_gpio_fast_read # It can still be used in normal and standby mode, but code that relies on it # being availiable during deep sleep / backup mode will not be portable here. FEATURES_PROVIDED += backup_ram +FEATURES_PROVIDED += periph_rtc_mem ifeq (,$(filter $(CPU_MODELS_WITHOUT_HWRNG),$(CPU_MODEL))) FEATURES_PROVIDED += periph_hwrng