diff --git a/cpu/stm32/Makefile.dep b/cpu/stm32/Makefile.dep index a8fc68c9ebac..320b639217ac 100644 --- a/cpu/stm32/Makefile.dep +++ b/cpu/stm32/Makefile.dep @@ -35,4 +35,9 @@ ifneq (,$(filter periph_eth periph_ptp,$(USEMODULE))) USEMODULE += periph_eth_common endif +# periph_rtc_mem is currently tied to the peripg_rtc +ifneq (,$(filter periph_rtc_mem,$(USEMODULE))) + FEATURES_REQUIRED += periph_rtc +endif + include $(RIOTCPU)/cortexm_common/Makefile.dep diff --git a/cpu/stm32/Makefile.features b/cpu/stm32/Makefile.features index 030649304ff5..262ecbd2958a 100644 --- a/cpu/stm32/Makefile.features +++ b/cpu/stm32/Makefile.features @@ -17,6 +17,13 @@ ifneq (,$(filter $(CPU_FAM),f0 f1 f3 g0 g4 l0 l1 l4 l5 wb wl)) FEATURES_PROVIDED += periph_flashpage_pagewise endif +ifneq (,$(filter $(CPU_FAM),f0 f2 f3 f4 f7 l0 l1 l4 l5 wb wl)) + CPU_MODELS_WITHOUT_RTC_BKPR += stm32f030% stm32f070% + ifeq (,$(filter $(CPU_MODELS_WITHOUT_RTC_BKPR),$(CPU_MODEL))) + FEATURES_PROVIDED += periph_rtc_mem + endif +endif + # The f2, f4 and f7 do not support the pagewise api ifneq (,$(filter $(CPU_FAM),f2 f4 f7)) FEATURES_PROVIDED += periph_flashpage diff --git a/cpu/stm32/kconfigs/f0/Kconfig.lines b/cpu/stm32/kconfigs/f0/Kconfig.lines index ea0c5682f0c8..6a9d49432ccd 100644 --- a/cpu/stm32/kconfigs/f0/Kconfig.lines +++ b/cpu/stm32/kconfigs/f0/Kconfig.lines @@ -26,28 +26,34 @@ config CPU_LINE_STM32F030XC config CPU_LINE_STM32F031X6 bool select CPU_FAM_F0 + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F038XX bool select CPU_FAM_F0 + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F042X6 bool select CPU_FAM_F0 + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F048XX bool select CPU_FAM_F0 + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F051X8 bool select CPU_FAM_F0 select CLOCK_HAS_NO_MCO_PRE + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F058XX bool select CPU_FAM_F0 select CLOCK_HAS_NO_MCO_PRE + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F070X6 bool @@ -60,19 +66,24 @@ config CPU_LINE_STM32F070XB config CPU_LINE_STM32F071XB bool select CPU_FAM_F0 + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F072XB bool select CPU_FAM_F0 + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F078XX bool select CPU_FAM_F0 + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F091XC bool select CPU_FAM_F0 + select HAS_PERIPH_RTC_MEM config CPU_LINE_STM32F098XX bool select CPU_FAM_F0 + select HAS_PERIPH_RTC_MEM diff --git a/cpu/stm32/kconfigs/f2/Kconfig b/cpu/stm32/kconfigs/f2/Kconfig index 8956fbfa18a1..720a174bd391 100644 --- a/cpu/stm32/kconfigs/f2/Kconfig +++ b/cpu/stm32/kconfigs/f2/Kconfig @@ -13,6 +13,7 @@ config CPU_FAM_F2 select HAS_CORTEXM_MPU select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_HWRNG + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/kconfigs/f3/Kconfig b/cpu/stm32/kconfigs/f3/Kconfig index 5ee691fd6a47..93651422b5c5 100644 --- a/cpu/stm32/kconfigs/f3/Kconfig +++ b/cpu/stm32/kconfigs/f3/Kconfig @@ -13,6 +13,7 @@ config CPU_FAM_F3 select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_FLASHPAGE_PAGEWISE select HAS_PERIPH_FLASHPAGE_RAW + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/kconfigs/f4/Kconfig b/cpu/stm32/kconfigs/f4/Kconfig index 05eddcd7d92b..0d510fc4bed6 100644 --- a/cpu/stm32/kconfigs/f4/Kconfig +++ b/cpu/stm32/kconfigs/f4/Kconfig @@ -12,6 +12,7 @@ config CPU_FAM_F4 select HAS_CPU_STM32F4 select HAS_CORTEXM_MPU select HAS_PERIPH_FLASHPAGE + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/kconfigs/f7/Kconfig b/cpu/stm32/kconfigs/f7/Kconfig index 0a8303d8431b..d77034c8ce8d 100644 --- a/cpu/stm32/kconfigs/f7/Kconfig +++ b/cpu/stm32/kconfigs/f7/Kconfig @@ -13,6 +13,7 @@ config CPU_FAM_F7 select HAS_CORTEXM_MPU select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_HWRNG + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/kconfigs/l0/Kconfig b/cpu/stm32/kconfigs/l0/Kconfig index 66fd11e5842b..53c263dd2be0 100644 --- a/cpu/stm32/kconfigs/l0/Kconfig +++ b/cpu/stm32/kconfigs/l0/Kconfig @@ -13,6 +13,7 @@ config CPU_FAM_L0 select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_FLASHPAGE_PAGEWISE select HAS_PERIPH_EEPROM + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/kconfigs/l1/Kconfig b/cpu/stm32/kconfigs/l1/Kconfig index 15c0fc93c124..0e662839b82f 100644 --- a/cpu/stm32/kconfigs/l1/Kconfig +++ b/cpu/stm32/kconfigs/l1/Kconfig @@ -14,6 +14,7 @@ config CPU_FAM_L1 select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_FLASHPAGE_PAGEWISE select HAS_PERIPH_EEPROM + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/kconfigs/l4/Kconfig b/cpu/stm32/kconfigs/l4/Kconfig index 312d8ab210d4..6ccd9df6af3f 100644 --- a/cpu/stm32/kconfigs/l4/Kconfig +++ b/cpu/stm32/kconfigs/l4/Kconfig @@ -14,6 +14,7 @@ config CPU_FAM_L4 select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_FLASHPAGE_PAGEWISE select HAS_PERIPH_HWRNG + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/kconfigs/l5/Kconfig b/cpu/stm32/kconfigs/l5/Kconfig index ddb6169bb447..46d5f2485794 100644 --- a/cpu/stm32/kconfigs/l5/Kconfig +++ b/cpu/stm32/kconfigs/l5/Kconfig @@ -13,6 +13,7 @@ config CPU_FAM_L5 select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_FLASHPAGE_PAGEWISE select HAS_PERIPH_HWRNG + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/kconfigs/wb/Kconfig b/cpu/stm32/kconfigs/wb/Kconfig index 679e301dadc4..61f2f7444e3d 100644 --- a/cpu/stm32/kconfigs/wb/Kconfig +++ b/cpu/stm32/kconfigs/wb/Kconfig @@ -13,6 +13,7 @@ config CPU_FAM_WB select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_FLASHPAGE_PAGEWISE select HAS_PERIPH_HWRNG + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/kconfigs/wl/Kconfig b/cpu/stm32/kconfigs/wl/Kconfig index fb9406bd451d..7df178c43815 100644 --- a/cpu/stm32/kconfigs/wl/Kconfig +++ b/cpu/stm32/kconfigs/wl/Kconfig @@ -13,6 +13,7 @@ config CPU_FAM_WL select HAS_CPU_STM32WL select HAS_PERIPH_FLASHPAGE select HAS_PERIPH_FLASHPAGE_PAGEWISE + select HAS_PERIPH_RTC_MEM select HAS_PERIPH_WDT select HAS_BOOTLOADER_STM32 diff --git a/cpu/stm32/periph/rtc_all.c b/cpu/stm32/periph/rtc_all.c index afad2a20ecf1..d2b93bfccdfb 100644 --- a/cpu/stm32/periph/rtc_all.c +++ b/cpu/stm32/periph/rtc_all.c @@ -209,7 +209,7 @@ static int bcd2val(uint32_t val, int shift, uint32_t mask) return (((tmp >> 4) * 10) + (tmp & 0x0f)); } -static inline void rtc_unlock(void) +void rtc_unlock(void) { /* enable backup clock domain */ stmclk_dbp_unlock(); @@ -221,7 +221,7 @@ static inline void rtc_unlock(void) while (!(RTC_REG_ISR & RTC_ISR_INITF)) {} } -static inline void rtc_lock(void) +void rtc_lock(void) { /* exit RTC init mode */ RTC_REG_ISR &= ~RTC_ISR_INIT; diff --git a/cpu/stm32/periph/rtc_mem.c b/cpu/stm32/periph/rtc_mem.c new file mode 100644 index 000000000000..2dc00d81ad00 --- /dev/null +++ b/cpu/stm32/periph/rtc_mem.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2021 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_stm32 + * @{ + * @file + * @brief Low-level RTC backup memory implementation + * + * @author Kaspar Schleiser + * @author Francisco Molina + * @} + */ + +#include + +#include "cpu.h" +#include "periph/rtc_mem.h" + +#if defined(RTC_BKP31R) +#define RTC_MEM_SIZE 32 +#elif defined(RTC_BKP30R) +#define RTC_MEM_SIZE 31 +#elif defined(RTC_BKP29R) +#define RTC_MEM_SIZE 30 +#elif defined(RTC_BKP28R) +#define RTC_MEM_SIZE 29 +#elif defined(RTC_BKP27R) +#define RTC_MEM_SIZE 28 +#elif defined(RTC_BKP26R) +#define RTC_MEM_SIZE 27 +#elif defined(RTC_BKP25R) +#define RTC_MEM_SIZE 26 +#elif defined(RTC_BKP24R) +#define RTC_MEM_SIZE 25 +#elif defined(RTC_BKP23R) +#define RTC_MEM_SIZE 24 +#elif defined(RTC_BKP22R) +#define RTC_MEM_SIZE 23 +#elif defined(RTC_BKP21R) +#define RTC_MEM_SIZE 22 +#elif defined(RTC_BKP20R) +#define RTC_MEM_SIZE 21 +#elif defined(RTC_BKP19R) +#define RTC_MEM_SIZE 20 +#elif defined(RTC_BKP18R) +#define RTC_MEM_SIZE 19 +#elif defined(RTC_BKP17R) +#define RTC_MEM_SIZE 18 +#elif defined(RTC_BKP16R) +#define RTC_MEM_SIZE 17 +#elif defined(RTC_BKP15R) +#define RTC_MEM_SIZE 16 +#elif defined(RTC_BKP14R) +#define RTC_MEM_SIZE 15 +#elif defined(RTC_BKP13R) +#define RTC_MEM_SIZE 14 +#elif defined(RTC_BKP12R) +#define RTC_MEM_SIZE 13 +#elif defined(RTC_BKP11R) +#define RTC_MEM_SIZE 12 +#elif defined(RTC_BKP10R) +#define RTC_MEM_SIZE 11 +#elif defined(RTC_BKP9R) +#define RTC_MEM_SIZE 10 +#elif defined(RTC_BKP8R) +#define RTC_MEM_SIZE 9 +#elif defined(RTC_BKP7R) +#define RTC_MEM_SIZE 8 +#elif defined(RTC_BKP6R) +#define RTC_MEM_SIZE 8 +#elif defined(RTC_BKP5R) +#define RTC_MEM_SIZE 6 +#elif defined(RTC_BKP4R) +#define RTC_MEM_SIZE 5 +#elif defined(RTC_BKP3R) +#define RTC_MEM_SIZE 4 +#elif defined(RTC_BKP2R) +#define RTC_MEM_SIZE 3 +#elif defined(RTC_BKP1R) +#define RTC_MEM_SIZE 2 +#elif defined(RTC_BKP0R) +#define RTC_MEM_SIZE 1 +#else +#define RTC_MEM_SIZE 0 +#endif + +extern void rtc_lock(void); +extern void rtc_unlock(void); + +size_t rtc_mem_size(void) +{ + return RTC_MEM_SIZE * __SIZEOF_POINTER__; +} + +void rtc_mem_write(unsigned offset, const void *data, size_t len) +{ + if (offset + len > rtc_mem_size()) { + return; + } + + const uint8_t *in = data; + + volatile uint32_t *rtc_regs = &RTC->BKP0R + (offset / __SIZEOF_POINTER__); + offset %= __SIZEOF_POINTER__; + + rtc_unlock(); + + while (len) { + unsigned to_copy = (len >= __SIZEOF_POINTER__) ? + __SIZEOF_POINTER__ - offset : len; + uint32_t tmp = *rtc_regs; + memcpy(((uint8_t *)&tmp) + offset, in, to_copy); + offset = 0; + *rtc_regs++ = tmp; + len -= to_copy; + in += to_copy; + } + + rtc_lock(); +} + +void rtc_mem_read(unsigned offset, void *data, size_t len) +{ + if (offset + len > rtc_mem_size()) { + return; + } + + uint8_t *out = (uint8_t *)data; + + volatile uint32_t *rtc_regs = &RTC->BKP0R + (offset / __SIZEOF_POINTER__); + offset %= __SIZEOF_POINTER__; + + while (len) { + unsigned to_copy = (len >= __SIZEOF_POINTER__) ? + __SIZEOF_POINTER__ - offset : len; + uint32_t tmp = *rtc_regs++; + memcpy(out, ((uint8_t *)&tmp) + offset, to_copy); + offset = 0; + len -= to_copy; + out += to_copy; + } +}