cpu/sam0_common: implement periph_rtc_mem

This commit is contained in:
Benjamin Valentin 2021-08-19 18:38:26 +02:00
parent 0ee0c5e40e
commit 3fbf473a07
5 changed files with 86 additions and 0 deletions

View File

@ -25,6 +25,7 @@
*/ */
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include "periph/rtc.h" #include "periph/rtc.h"
#include "periph/rtt.h" #include "periph/rtt.h"
#include "periph_conf.h" #include "periph_conf.h"
@ -215,10 +216,70 @@ static void _rtt_clock_setup(void)
#endif /* MODULE_PERIPH_RTT */ #endif /* MODULE_PERIPH_RTT */
#endif /* !CPU_COMMON_SAMD21 - Clock Setup */ #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 #ifdef MODULE_PERIPH_RTC
static void _rtc_init(void) static void _rtc_init(void)
{ {
#ifdef REG_RTC_MODE2_CTRLA #ifdef REG_RTC_MODE2_CTRLA
/* skip reset if already in RTC mode */
if (RTC->MODE2.CTRLA.bit.MODE == RTC_MODE2_CTRLA_MODE_CLOCK_Val) { if (RTC->MODE2.CTRLA.bit.MODE == RTC_MODE2_CTRLA_MODE_CLOCK_Val) {
return; 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.reg = RTC_MODE2_CTRLA_PRESCALER_DIV1024 /* CLK_RTC_CNT = 1KHz / 1024 -> 1Hz */
| RTC_MODE2_CTRLA_CLOCKSYNC /* Clock Read Synchronization Enable */ | RTC_MODE2_CTRLA_CLOCKSYNC /* Clock Read Synchronization Enable */
| RTC_MODE2_CTRLA_MODE_CLOCK; | 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 #else
if (RTC->MODE2.CTRL.bit.MODE == RTC_MODE2_CTRL_MODE_CLOCK_Val) { if (RTC->MODE2.CTRL.bit.MODE == RTC_MODE2_CTRL_MODE_CLOCK_Val) {
return; return;
@ -268,10 +334,26 @@ void rtc_init(void)
#ifdef MODULE_PERIPH_RTT #ifdef MODULE_PERIPH_RTT
void rtt_init(void) void rtt_init(void)
{ {
_rtt_clock_setup(); _rtt_clock_setup();
_poweron(); _poweron();
#ifdef MODULE_PERIPH_RTC_MEM
uint32_t backup[RTC_GPR_NUM_AVAIL];
_read_gp(backup);
#endif
_rtt_reset(); _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 */ /* set 32bit counting mode & enable the RTC */
#ifdef REG_RTC_MODE0_CTRLA #ifdef REG_RTC_MODE0_CTRLA
RTC->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_MODE(0) RTC->MODE0.CTRLA.reg = RTC_MODE0_CTRLA_MODE(0)

View File

@ -15,6 +15,7 @@ config CPU_COMMON_SAMD5X
select HAS_PERIPH_DMA select HAS_PERIPH_DMA
select HAS_PERIPH_GPIO_TAMPER_WAKE select HAS_PERIPH_GPIO_TAMPER_WAKE
select HAS_PERIPH_HWRNG select HAS_PERIPH_HWRNG
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_SPI_ON_QSPI select HAS_PERIPH_SPI_ON_QSPI
config CPU_FAM_SAMD51 config CPU_FAM_SAMD51

View File

@ -4,6 +4,7 @@ FEATURES_PROVIDED += periph_hwrng
FEATURES_PROVIDED += backup_ram FEATURES_PROVIDED += backup_ram
FEATURES_PROVIDED += cortexm_mpu FEATURES_PROVIDED += cortexm_mpu
FEATURES_PROVIDED += periph_gpio_tamper_wake FEATURES_PROVIDED += periph_gpio_tamper_wake
FEATURES_PROVIDED += periph_rtc_mem
FEATURES_PROVIDED += periph_spi_on_qspi FEATURES_PROVIDED += periph_spi_on_qspi
include $(RIOTCPU)/sam0_common/Makefile.features include $(RIOTCPU)/sam0_common/Makefile.features

View File

@ -13,6 +13,7 @@ config CPU_COMMON_SAML21
select HAS_CPU_SAML21 select HAS_CPU_SAML21
select HAS_PERIPH_DMA select HAS_PERIPH_DMA
select HAS_PERIPH_GPIO_FAST_READ select HAS_PERIPH_GPIO_FAST_READ
select HAS_PERIPH_RTC_MEM
config CPU_FAM_SAML21 config CPU_FAM_SAML21
bool bool

View File

@ -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 # 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. # being availiable during deep sleep / backup mode will not be portable here.
FEATURES_PROVIDED += backup_ram FEATURES_PROVIDED += backup_ram
FEATURES_PROVIDED += periph_rtc_mem
ifeq (,$(filter $(CPU_MODELS_WITHOUT_HWRNG),$(CPU_MODEL))) ifeq (,$(filter $(CPU_MODELS_WITHOUT_HWRNG),$(CPU_MODEL)))
FEATURES_PROVIDED += periph_hwrng FEATURES_PROVIDED += periph_hwrng