1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

cpu/{cortexm_common, stm32}: add support for backup RAM

This commit is contained in:
Fabian Hüßler 2021-09-16 09:58:37 +02:00
parent 5fdf8d2d88
commit 70d3d647d1
17 changed files with 230 additions and 4 deletions

View File

@ -137,6 +137,9 @@ void reset_handler_default(void)
}
#ifdef CPU_HAS_BACKUP_RAM
#if BACKUP_RAM_HAS_INIT
backup_ram_init();
#endif
if (!cpu_woke_from_backup() ||
CPU_BACKUP_RAM_NOT_RETAINED) {

View File

@ -24,6 +24,16 @@ ifneq (,$(filter $(CPU_FAM),f0 f2 f3 f4 f7 l0 l1 l4 l5 u5 wb wl))
endif
endif
STM32_WITH_BKPRAM = stm32f205% stm32f207% stm32f215% stm32f217% \
stm32f405% stm32f407% stm32f415% stm32f417% \
stm32f427% stm32f429% stm32f437% stm32f439% \
stm32f446% stm32f469% stm32f479% \
stm32f7% \
stm32u5%
ifneq (,$(filter $(STM32_WITH_BKPRAM),$(CPU_MODEL)))
FEATURES_PROVIDED += backup_ram
endif
# The f2, f4 and f7 do not support the pagewise api
ifneq (,$(filter $(CPU_FAM),f2 f4 f7))
FEATURES_PROVIDED += periph_flashpage

View File

@ -372,3 +372,43 @@ void cpu_init(void)
_wlx5xx_init_subghz_debug_pins();
}
}
void backup_ram_init(void)
{
/* see reference manual "Battery backup domain" */
#if defined(RCC_APB1ENR_PWREN)
periph_clk_en(APB1, RCC_APB1ENR_PWREN);
#elif defined(RCC_APBENR1_PWREN)
periph_clk_en(APB1, RCC_APBENR1_PWREN);
#elif defined(RCC_APB1ENR1_PWREN)
periph_clk_en(APB1, RCC_APB1ENR1_PWREN);
#elif defined(RCC_AHB3ENR_PWREN)
periph_clk_en(AHB3, RCC_AHB3ENR_PWREN);
#endif
stmclk_dbp_unlock();
#if defined(RCC_AHB1ENR_BKPSRAMEN)
periph_clk_en(AHB1, RCC_AHB1ENR_BKPSRAMEN);
#endif
}
#ifndef BACKUP_RAM_MAGIC
#define BACKUP_RAM_MAGIC {'R', 'I', 'O', 'T'}
#endif
bool cpu_woke_from_backup(void)
{
#if IS_ACTIVE(CPU_HAS_BACKUP_RAM)
static const char _signature[] BACKUP_RAM_DATA = BACKUP_RAM_MAGIC;
/* switch off regulator to save power */
#ifndef RIOTBOOT
pm_backup_regulator_off();
#endif
for (unsigned i = 0; i < sizeof(_signature); i++) {
if (_signature[i] != ((char[])BACKUP_RAM_MAGIC)[i]) {
return false;
}
}
return true;
#endif /* CPU_HAS_BACKUP_RAM */
return false;
}

View File

@ -67,7 +67,7 @@
#elif CPU_FAM_STM32U5
#include "stm32u5xx.h"
#include "irqs/u5/irqs.h"
#define NUM_HEAPS 2
#define NUM_HEAPS 3
#elif CPU_FAM_STM32WB
#include "stm32wbxx.h"
#include "irqs/wb/irqs.h"

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg
*
* 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 Backup SRAM CPU specific definitions for the STM32 family
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*/
#ifndef PERIPH_CPU_BACKUP_RAM_H
#define PERIPH_CPU_BACKUP_RAM_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Backup RAM must be initialized with @ref backup_ram_init on reset
*/
#define BACKUP_RAM_HAS_INIT 1
/**
* @brief Enable backup RAM access
*/
void backup_ram_init(void);
/**
* @brief Returns true if the CPU woke up from deep sleep (backup/standby)
*/
bool cpu_woke_from_backup(void);
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_BACKUP_RAM_H */
/** @} */

View File

@ -50,6 +50,22 @@ extern "C" {
#endif
/** @} */
/**
* @brief Check whether the backup domain voltage regulator is on
*/
bool pm_backup_regulator_is_on(void);
/**
* @brief Enable the backup domain voltage regulator to retain backup
* register content during standby and VBAT mode
*/
void pm_backup_regulator_on(void);
/**
* @brief Disable the backup domain voltage regulator
*/
void pm_backup_regulator_off(void);
#ifdef __cplusplus
}
#endif

View File

@ -58,6 +58,7 @@
#include "periph/wl/periph_cpu.h"
#endif
#include "periph/cpu_backup_ram.h"
#include "periph/cpu_common.h"
#include "periph/cpu_dma.h"
#include "periph/cpu_eth.h"

View File

@ -22,6 +22,8 @@
#ifndef STMCLK_H
#define STMCLK_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
@ -84,6 +86,14 @@ void stmclk_dbp_unlock(void);
*/
void stmclk_dbp_lock(void);
/**
* @brief Check whether write access to the backup domain is locked
*
* @retval true: locked
* @retval false: unlocked
*/
bool stmclk_dbp_is_locked(void);
#ifdef __cplusplus
}
#endif

View File

@ -9,6 +9,7 @@ config CPU_FAM_F2
bool
select CPU_STM32
select CPU_CORE_CORTEX_M3
select HAS_BACKUP_RAM
select HAS_CPU_STM32F2
select HAS_CORTEXM_MPU
select HAS_PERIPH_FLASHPAGE

View File

@ -23,12 +23,14 @@ config CPU_LINE_STM32F401XE
config CPU_LINE_STM32F405XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select HAS_PERIPH_HWRNG
select CLOCK_MAX_180MHZ
config CPU_LINE_STM32F407XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select HAS_PERIPH_HWRNG
select CLOCK_MAX_180MHZ
@ -83,12 +85,14 @@ config CPU_LINE_STM32F413XX
config CPU_LINE_STM32F415XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select HAS_PERIPH_HWRNG
select CLOCK_MAX_180MHZ
config CPU_LINE_STM32F417XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select CLOCK_MAX_180MHZ
config CPU_LINE_STM32F423XX
@ -99,37 +103,44 @@ config CPU_LINE_STM32F423XX
config CPU_LINE_STM32F427XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select CLOCK_MAX_180MHZ
config CPU_LINE_STM32F429XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select HAS_PERIPH_HWRNG
select CLOCK_MAX_180MHZ
config CPU_LINE_STM32F437XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select HAS_PERIPH_HWRNG
select CLOCK_MAX_180MHZ
config CPU_LINE_STM32F439XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select CLOCK_MAX_180MHZ
config CPU_LINE_STM32F446XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select CLOCK_MAX_180MHZ
config CPU_LINE_STM32F469XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select HAS_PERIPH_HWRNG
select CLOCK_MAX_180MHZ
config CPU_LINE_STM32F479XX
bool
select CPU_FAM_F4
select HAS_BACKUP_RAM
select CLOCK_MAX_180MHZ

View File

@ -9,6 +9,7 @@ config CPU_FAM_F7
bool
select CPU_STM32
select CPU_CORE_CORTEX_M7
select HAS_BACKUP_RAM
select HAS_CPU_STM32F7
select HAS_CORTEXM_MPU
select HAS_PERIPH_FLASHPAGE

View File

@ -9,6 +9,7 @@ config CPU_FAM_U5
bool
select CPU_STM32
select CPU_CORE_CORTEX_M33
select HAS_BACKUP_RAM
select HAS_CPU_STM32U5
select HAS_PERIPH_FLASHPAGE
select HAS_PERIPH_FLASHPAGE_PAGEWISE

View File

@ -31,8 +31,8 @@ SECTIONS
{
.heap2 ALIGN(4) (NOLOAD) :
{
_sheap1 = . ;
_eheap1 = ORIGIN(sram4) + LENGTH(sram4);
_sheap2 = . ;
_eheap2 = ORIGIN(sram4) + LENGTH(sram4);
} > sram4
}

View File

@ -29,6 +29,7 @@
#include "irq.h"
#include "periph/pm.h"
#include "periph/cpu_pm.h"
#include "stmclk.h"
#define ENABLE_DEBUG 0
@ -137,6 +138,7 @@ void pm_set(unsigned mode)
PWR_WUP_REG |= PM_EWUP_CONFIG;
/* Set SLEEPDEEP bit of system control block */
deep = 1;
pm_backup_regulator_on();
break;
#endif
case STM32_PM_STOP:
@ -159,3 +161,61 @@ void pm_set(unsigned mode)
#endif
}
}
/**
* @name Registers and related configuration bits to retain
* the backup domain registers, using the backup regulator
* @{
*/
#if defined(PWR_CSR1_BRE)
#define PWR_BACKUP_REGULATOR_REG PWR->CSR1
#define BKPREG_CONFIG (PWR_CSR1_BRE | PWR_CSR1_EIWUP)
#define BKPREG_READY (PWR_CSR1_BRR)
#elif defined(PWR_CSR_BRE)
#define PWR_BACKUP_REGULATOR_REG PWR->CSR
#define BKPREG_CONFIG (PWR_CSR_BRE)
#define BKPREG_READY (PWR_CSR_BRR)
#elif defined(PWR_CR2_BREN)
#define PWR_BACKUP_REGULATOR_REG PWR->CR2
#define BKPREG_CONFIG (PWR_CR2_BREN)
#define BKPREG_READY (PWR_CR2_BRRDY)
#endif
/** @} */
bool pm_backup_regulator_is_on(void)
{
#if defined(PWR_BACKUP_REGULATOR_REG)
return (PWR_BACKUP_REGULATOR_REG & BKPREG_READY) == BKPREG_READY;
#else
return false;
#endif
}
void pm_backup_regulator_on(void)
{
#if defined(PWR_BACKUP_REGULATOR_REG)
bool locked = stmclk_dbp_is_locked();
if (locked) {
stmclk_dbp_unlock();
}
PWR_BACKUP_REGULATOR_REG |= BKPREG_CONFIG;
while (!(PWR_BACKUP_REGULATOR_REG & BKPREG_READY));
if (locked) {
stmclk_dbp_lock();
}
#endif
}
void pm_backup_regulator_off(void)
{
#if defined(PWR_BACKUP_REGULATOR_REG)
bool locked = stmclk_dbp_is_locked();
if (locked) {
stmclk_dbp_unlock();
}
PWR_BACKUP_REGULATOR_REG &= ~BKPREG_CONFIG;
if (locked) {
stmclk_dbp_lock();
}
#endif
}

View File

@ -90,6 +90,10 @@ ifeq ($(STM32_TYPE), F)
else ifeq ($(STM32_MODEL3), 7)
RAM_LEN = 128K
endif
ifneq (, $(filter $(STM32_MODEL), 205 207 215 217))
BACKUP_RAM_ADDR = 0x40024000
BACKUP_RAM_LEN = 0x4K
endif
else ifeq ($(STM32_FAMILY), 3)
ifeq ($(STM32_MODEL), 301)
RAM_LEN = 16K
@ -167,6 +171,10 @@ ifeq ($(STM32_TYPE), F)
ifneq (, $(filter $(STM32_MODEL3), 5 7 9))
CCMRAM_LEN = 64K
endif
ifneq (, $(filter $(STM32_MODEL), 405 407 415 417 427 429 437 439 446 469 479))
BACKUP_RAM_ADDR = 0x40024000
BACKUP_RAM_LEN = 0x4K
endif
else ifeq ($(STM32_FAMILY),7)
ifneq (, $(filter $(STM32_MODEL2), 2 3))
RAM_LEN = 256K
@ -175,6 +183,8 @@ ifeq ($(STM32_TYPE), F)
else ifneq (, $(filter $(STM32_MODEL2), 6 7))
RAM_LEN = 512K
endif
BACKUP_RAM_ADDR = 0x40024000
BACKUP_RAM_LEN = 0x4K
endif
else ifeq ($(STM32_TYPE), G)
ifeq ($(STM32_FAMILY), 0)
@ -271,6 +281,8 @@ else ifeq ($(STM32_TYPE), U)
ifneq (, $(filter $(STM32_MODEL2), 7 8))
RAM_LEN = 768K
SRAM4_LEN = 16K
BACKUP_RAM_ADDR = 0x40036400
BACKUP_RAM_LEN = 0x2K
endif
endif
else ifeq ($(STM32_TYPE), W)

View File

@ -115,5 +115,14 @@ void stmclk_dbp_unlock(void)
void stmclk_dbp_lock(void)
{
PWR->REG_PWR_CR &= ~(BIT_CR_DBP);
if (!IS_ACTIVE(CPU_HAS_BACKUP_RAM)) {
/* The DBP must be unlocked all the time, if we modify
backup RAM content by comfortable BACKUP_RAM variables */
PWR->REG_PWR_CR &= ~(BIT_CR_DBP);
}
}
bool stmclk_dbp_is_locked(void)
{
return !(PWR->REG_PWR_CR & BIT_CR_DBP);
}

View File

@ -246,6 +246,11 @@ void stmclk_init_sysclk(void)
/* Wait Until the Voltage Regulator is ready */
while (!(PWR->VOSR & PWR_VOSR_VOSRDY)) {}
/* Backup RAM retention in Standby and VBAT modes:
This bit can be written only when the regulator is LDO,
which must be configured before switching to SMPS */
PWR->BDCR1 |= PWR_BDCR1_BREN;
/* Switch to SMPS regulator instead of LDO */
PWR->CR3 |= PWR_CR3_REGSEL;
while (!(PWR->SVMSR & PWR_SVMSR_REGS)) {}