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

cpu/stm32: add VBAT for stm32

This commit is contained in:
Fabian Hüßler 2021-10-12 13:16:57 +02:00
parent 66a7a0a065
commit 33c2944076
38 changed files with 593 additions and 25 deletions

View File

@ -49,5 +49,8 @@ ifneq (,$(filter periph_adc,$(FEATURES_USED)))
endif
endif
ifneq (,$(filter periph_vbat,$(USEMODULE)))
FEATURES_REQUIRED += periph_adc
endif
include $(RIOTCPU)/cortexm_common/Makefile.dep

View File

@ -34,6 +34,25 @@ ifneq (,$(filter $(STM32_WITH_BKPRAM),$(CPU_MODEL)))
FEATURES_PROVIDED += backup_ram
endif
STM32_WITH_VBAT = stm32f031% stm32f038% stm32f042% stm32f048% \
stm32f051% stm32f058% stm32f071% stm32f072% \
stm32f078% stm32f091% stm32f098% \
stm32f2% \
stm32f3% \
stm32f4% \
stm32f7% \
stm32g0% \
stm32g4% stm32gbk1cb \
stm32l4% \
stm32l5% \
stm32u5% \
stm32wb% \
stm32wl%
ifneq (,$(filter $(STM32_WITH_VBAT),$(CPU_MODEL)))
FEATURES_PROVIDED += periph_vbat
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

@ -0,0 +1,41 @@
/*
* 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 CPU internal VBAT interface and definitions of the STM32 family
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
*/
#ifndef PERIPH_CPU_VBAT_H
#define PERIPH_CPU_VBAT_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enable the VBAT sampling channel
*/
void vbat_enable(void);
/**
* @brief Disable the VBAT sampling channel
*/
void vbat_disable(void);
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_VBAT_H */
/** @} */

View File

@ -61,6 +61,15 @@ typedef enum {
ADC_RES_16BIT = (0xff) /**< not applicable */
} adc_res_t;
/** @} */
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -58,6 +58,15 @@ typedef enum {
ADC_RES_16BIT = 2 /**< ADC resolution: 16 bit (not supported)*/
} adc_res_t;
/** @} */
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -69,6 +69,15 @@ typedef enum {
ADC_RES_16BIT = (0x2) /**< not applicable */
} adc_res_t;
/** @} */
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -69,6 +69,15 @@ typedef enum {
ADC_RES_16BIT = 2 /**< ADC resolution: 16 bit (not supported)*/
} adc_res_t;
/** @} */
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -52,6 +52,15 @@ typedef enum {
ADC_RES_16BIT = 2 /**< ADC resolution: 16 bit (not supported)*/
} adc_res_t;
/** @} */
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -32,6 +32,14 @@ extern "C" {
*/
#define STM32_BOOTLOADER_ADDR (0x1FFF0000)
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
/**

View File

@ -32,6 +32,14 @@ extern "C" {
*/
#define STM32_BOOTLOADER_ADDR (0x1FFF0000)
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -63,6 +63,15 @@ typedef enum {
ADC_RES_16BIT = (0x2) /**< not applicable */
} adc_res_t;
/** @} */
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -32,6 +32,14 @@ extern "C" {
*/
#define STM32_BOOTLOADER_ADDR (0x0BF90000)
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -32,6 +32,14 @@ extern "C" {
*/
#define STM32_BOOTLOADER_ADDR (0x0BF90000)
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_14BIT
#define VBAT_ADC_MAX 16383
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -32,6 +32,14 @@ extern "C" {
*/
#define STM32_BOOTLOADER_ADDR (0x1FFF0000)
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
#ifdef __cplusplus

View File

@ -57,6 +57,14 @@ typedef enum {
*/
#define STM32_BOOTLOADER_ADDR (0x1FFF0000)
/**
* @name Constants for internal VBAT ADC line
* @{
*/
#define VBAT_ADC_RES ADC_RES_12BIT
#define VBAT_ADC_MAX 4095
/** @} */
#endif /* ndef DOXYGEN */
/**

View File

@ -72,6 +72,7 @@
#include "periph/cpu_timer.h"
#include "periph/cpu_uart.h"
#include "periph/cpu_usbdev.h"
#include "periph/cpu_vbat.h"
#include "periph/cpu_wdt.h"
#ifdef MODULE_PERIPH_CAN

View File

@ -27,33 +27,39 @@ config CPU_LINE_STM32F031X6
bool
select CPU_FAM_F0
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F038XX
bool
select CPU_FAM_F0
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F042X6
bool
select CPU_FAM_F0
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F048XX
bool
select CPU_FAM_F0
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F051X8
bool
select CPU_FAM_F0
select CLOCK_HAS_NO_MCO_PRE
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F058XX
bool
select CPU_FAM_F0
select CLOCK_HAS_NO_MCO_PRE
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F070X6
bool
@ -67,23 +73,28 @@ config CPU_LINE_STM32F071XB
bool
select CPU_FAM_F0
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F072XB
bool
select CPU_FAM_F0
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F078XX
bool
select CPU_FAM_F0
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F091XC
bool
select CPU_FAM_F0
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
config CPU_LINE_STM32F098XX
bool
select CPU_FAM_F0
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT

View File

@ -15,6 +15,7 @@ config CPU_FAM_F2
select HAS_PERIPH_FLASHPAGE
select HAS_PERIPH_HWRNG
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -14,6 +14,7 @@ config CPU_FAM_F3
select HAS_PERIPH_FLASHPAGE_PAGEWISE
select HAS_PERIPH_FLASHPAGE_RAW
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -13,6 +13,7 @@ config CPU_FAM_F4
select HAS_CORTEXM_MPU
select HAS_PERIPH_FLASHPAGE
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -15,6 +15,7 @@ config CPU_FAM_F7
select HAS_PERIPH_FLASHPAGE
select HAS_PERIPH_HWRNG
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -13,6 +13,7 @@ config CPU_FAM_G0
select HAS_PERIPH_FLASHPAGE
select HAS_PERIPH_FLASHPAGE_PAGEWISE
select HAS_PERIPH_FLASHPAGE_RAW
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -14,6 +14,7 @@ config CPU_FAM_G4
select HAS_PERIPH_FLASHPAGE
select HAS_PERIPH_FLASHPAGE_PAGEWISE
select HAS_PERIPH_HWRNG
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -15,6 +15,7 @@ config CPU_FAM_L4
select HAS_PERIPH_FLASHPAGE_PAGEWISE
select HAS_PERIPH_HWRNG
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -14,6 +14,7 @@ config CPU_FAM_L5
select HAS_PERIPH_FLASHPAGE_PAGEWISE
select HAS_PERIPH_HWRNG
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -15,6 +15,7 @@ config CPU_FAM_U5
select HAS_PERIPH_FLASHPAGE_PAGEWISE
select HAS_PERIPH_HWRNG
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -14,6 +14,7 @@ config CPU_FAM_WB
select HAS_PERIPH_FLASHPAGE_PAGEWISE
select HAS_PERIPH_HWRNG
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -14,6 +14,7 @@ config CPU_FAM_WL
select HAS_PERIPH_FLASHPAGE
select HAS_PERIPH_FLASHPAGE_PAGEWISE
select HAS_PERIPH_RTC_MEM
select HAS_PERIPH_VBAT
select HAS_PERIPH_WDT
select HAS_BOOTLOADER_STM32

View File

@ -22,6 +22,14 @@
#include "cpu.h"
#include "mutex.h"
#include "periph/adc.h"
#include "periph/vbat.h"
/**
* @brief Default VBAT undefined value
*/
#ifndef VBAT_ADC
#define VBAT_ADC ADC_UNDEF
#endif
/**
* @brief Allocate lock for the ADC device
@ -62,7 +70,9 @@ int adc_init(adc_t line)
/* lock and power on the device */
prep();
/* configure the pin */
gpio_init_analog(adc_config[line].pin);
if (adc_config[line].pin != GPIO_UNDEF) {
gpio_init_analog(adc_config[line].pin);
}
/* reset configuration */
ADC1->CFGR2 = 0;
/* enable device */
@ -86,7 +96,10 @@ int32_t adc_sample(adc_t line, adc_res_t res)
/* lock and power on the ADC device */
prep();
/* check if this is the VBAT line */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_enable();
}
/* set resolution and channel */
ADC1->CFGR1 = res;
ADC1->CHSELR = (1 << adc_config[line].chan);
@ -95,7 +108,10 @@ int32_t adc_sample(adc_t line, adc_res_t res)
while (!(ADC1->ISR & ADC_ISR_EOC)) {}
/* read result */
sample = (int)ADC1->DR;
/* check if this is the VBAT line */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_disable();
}
/* unlock and power off device again */
done();

View File

@ -24,12 +24,20 @@
#include "mutex.h"
#include "periph/adc.h"
#include "periph_conf.h"
#include "periph/vbat.h"
/**
* @brief Maximum allowed ADC clock speed
*/
#define MAX_ADC_SPEED (12000000U)
/**
* @brief Default VBAT undefined value
*/
#ifndef VBAT_ADC
#define VBAT_ADC ADC_UNDEF
#endif
/**
* @brief Allocate locks for all three available ADC devices
*/
@ -73,7 +81,9 @@ int adc_init(adc_t line)
prep(line);
/* configure the pin */
gpio_init_analog(adc_config[line].pin);
if (adc_config[line].pin != GPIO_UNDEF) {
gpio_init_analog(adc_config[line].pin);
}
/* set clock prescaler to get the maximal possible ADC clock value */
for (clk_div = 2; clk_div < 8; clk_div += 2) {
if ((CLOCK_CORECLOCK / clk_div) <= MAX_ADC_SPEED) {
@ -85,17 +95,6 @@ int adc_init(adc_t line)
/* enable the ADC module */
dev(line)->CR2 = ADC_CR2_ADON;
/* check if this channel is an internal ADC channel, if so
* enable the internal temperature and Vref */
if (adc_config[line].chan == 16 || adc_config[line].chan == 17) {
/* check if the internal channels are configured to use ADC1 */
if (dev(line) != ADC1) {
return -3;
}
ADC->CCR |= ADC_CCR_TSVREFE;
}
/* free the device again */
done(line);
return 0;
@ -112,7 +111,15 @@ int32_t adc_sample(adc_t line, adc_res_t res)
/* lock and power on the ADC device */
prep(line);
/* check if this is the VBAT line or another internal ADC channel */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_enable();
}
else if (dev(line) == ADC1) {
if (adc_config[line].chan == 16 || adc_config[line].chan == 17) {
ADC->CCR |= ADC_CCR_TSVREFE;
}
}
/* set resolution and conversion channel */
dev(line)->CR1 = res;
dev(line)->SQR3 = adc_config[line].chan;
@ -121,7 +128,15 @@ int32_t adc_sample(adc_t line, adc_res_t res)
while (!(dev(line)->SR & ADC_SR_EOC)) {}
/* finally read sample and reset the STRT bit in the status register */
sample = (int)dev(line)->DR;
/* check if this is the VBAT line or another internal ADC channel */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_disable();
}
else if (dev(line) == ADC1) {
if (adc_config[line].chan == 16 || adc_config[line].chan == 17) {
ADC->CCR &= ~ADC_CCR_TSVREFE;
}
}
/* power off and unlock device again */
done(line);

View File

@ -24,6 +24,7 @@
#include "periph/adc.h"
#include "periph_conf.h"
#include "ztimer.h"
#include "periph/vbat.h"
#define SMP_MIN (0x2) /*< Sampling time for slow channels
(0x2 = 4.5 ADC clock cycles) */
@ -33,6 +34,13 @@
#define ADC_INSTANCE ADC12_COMMON
#endif
/**
* @brief Default VBAT undefined value
*/
#ifndef VBAT_ADC
#define VBAT_ADC ADC_UNDEF
#endif
/**
* @brief Allocate locks for all available ADC devices
*/
@ -128,8 +136,9 @@ int adc_init(adc_t line)
}
/* Configure the pin */
gpio_init_analog(adc_config[line].pin);
if (adc_config[line].pin != GPIO_UNDEF) {
gpio_init_analog(adc_config[line].pin);
}
/* Init ADC line only if it wasn't already initialized */
if (!(dev(line)->CR & ADC_CR_ADEN)) {
/* Enable ADC internal voltage regulator and wait for startup period */
@ -192,6 +201,11 @@ int32_t adc_sample(adc_t line, adc_res_t res)
/* Lock and power on the ADC device */
prep(line);
/* check if this is the VBAT line */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_enable();
}
/* Set resolution */
dev(line)->CFGR &= ~ADC_CFGR_RES;
dev(line)->CFGR |= res;
@ -206,6 +220,11 @@ int32_t adc_sample(adc_t line, adc_res_t res)
/* Read the sample */
sample = (int)dev(line)->DR;
/* check if this is the VBAT line */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_disable();
}
/* Power off and unlock device again */
done(line);

View File

@ -23,12 +23,20 @@
#include "mutex.h"
#include "periph/adc.h"
#include "periph_conf.h"
#include "periph/vbat.h"
/**
* @brief Maximum allowed ADC clock speed
*/
#define MAX_ADC_SPEED (12000000U)
/**
* @brief Default VBAT undefined value
*/
#ifndef VBAT_ADC
#define VBAT_ADC ADC_UNDEF
#endif
/**
* @brief Allocate locks for all three available ADC devices
*/
@ -72,7 +80,9 @@ int adc_init(adc_t line)
prep(line);
/* configure the pin */
gpio_init_analog(adc_config[line].pin);
if (adc_config[line].pin != GPIO_UNDEF) {
gpio_init_analog(adc_config[line].pin);
}
/* set sequence length to 1 conversion and enable the ADC device */
dev(line)->SQR1 = 0;
dev(line)->CR2 = ADC_CR2_ADON;
@ -100,7 +110,10 @@ int32_t adc_sample(adc_t line, adc_res_t res)
/* lock and power on the ADC device */
prep(line);
/* check if this channel is an internal ADC channel */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_enable();
}
/* set resolution and conversion channel */
dev(line)->CR1 = res;
dev(line)->SQR3 = adc_config[line].chan;
@ -109,7 +122,10 @@ int32_t adc_sample(adc_t line, adc_res_t res)
while (!(dev(line)->SR & ADC_SR_EOC)) {}
/* finally read sample and reset the STRT bit in the status register */
sample = (int)dev(line)->DR;
/* check if this channel was an internal ADC channel */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_disable();
}
/* power off and unlock device again */
done(line);

View File

@ -25,6 +25,7 @@
#include "mutex.h"
#include "periph/adc.h"
#include "periph_conf.h"
#include "periph/vbat.h"
#include "ztimer.h"
/**
@ -55,6 +56,13 @@
#define ADC_SMPR2_FIRST_CHAN (10)
#endif
/**
* @brief Default VBAT undefined value
*/
#ifndef VBAT_ADC
#define VBAT_ADC ADC_UNDEF
#endif
/**
* @brief Allocate locks for all three available ADC devices
*/
@ -122,8 +130,9 @@ int adc_init(adc_t line)
}
/* configure the pin */
gpio_init_analog(adc_config[line].pin);
if (adc_config[line].pin != GPIO_UNDEF) {
gpio_init_analog(adc_config[line].pin);
}
#if defined(CPU_MODEL_STM32L476RG) || defined(CPU_MODEL_STM32L475VG)
/* On STM32L475xx/476xx/486xx devices, before any conversion of an input channel coming
from GPIO pads, it is necessary to configure the corresponding GPIOx_ASCR register in
@ -192,6 +201,11 @@ int32_t adc_sample(adc_t line, adc_res_t res)
/* lock and power on the ADC device */
prep(line);
/* check if this is the VBAT line */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_enable();
}
/* first clear resolution */
dev(line)->CFGR &= ~(ADC_CFGR_RES);
@ -208,6 +222,11 @@ int32_t adc_sample(adc_t line, adc_res_t res)
/* read the sample */
sample = (int)dev(line)->DR;
/* check if this is the VBAT line */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_disable();
}
/* free the device again */
done(line);

View File

@ -27,8 +27,16 @@
#include "mutex.h"
#include "periph/adc.h"
#include "periph_conf.h"
#include "periph/vbat.h"
#include "ztimer.h"
/**
* @brief Default VBAT undefined value
*/
#ifndef VBAT_ADC
#define VBAT_ADC ADC_UNDEF
#endif
/**
* @brief Allocate lock for the ADC device
*
@ -59,7 +67,9 @@ int adc_init(adc_t line)
prep();
/* configure the pin */
gpio_init_analog(adc_config[line].pin);
if (adc_config[line].pin != GPIO_UNDEF) {
gpio_init_analog(adc_config[line].pin);
}
/* init ADC line only if it wasn't already initialized */
if (!(ADC->CR & (ADC_CR_ADEN))) {
@ -116,6 +126,11 @@ int32_t adc_sample(adc_t line, adc_res_t res)
/* lock and power on the ADC device */
prep();
/* check if this is the VBAT line */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_enable();
}
/* first clear resolution */
ADC->CFGR1 &= ~ADC_CFGR1_RES;
@ -132,6 +147,11 @@ int32_t adc_sample(adc_t line, adc_res_t res)
/* read the sample */
sample = (int)ADC->DR;
/* check if this is the VBAT line */
if (IS_USED(MODULE_PERIPH_VBAT) && line == VBAT_ADC) {
vbat_disable();
}
/* free the device again */
done();

230
cpu/stm32/periph/vbat.c Normal file
View File

@ -0,0 +1,230 @@
/*
* 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
* @ingroup drivers_periph_vbat
* @{
*
* @file
* @brief Implementation of STM32 backup battery monitoring
*
* @author Fabian Hüßler <fabian.huessler@ovgu.de>
* @}
*/
#include "board.h"
#include "periph_conf.h"
#include "periph/adc.h"
#include "periph/vbat.h"
/**
* @name Constants depending on CPU line
* @{
*
* @ref VBAT_ADC_SCALE is a scale factor to calculate the right voltage value
* as documented in the data sheet.
* @ref VBAT_ADC_MIN_MV <= VBAT[mV] is the smallest voltage level required
* to power the backup domain.
*/
/* f0 */
#if defined(CPU_LINE_STM32F031x6) || defined(CPU_LINE_STM32F038xx) || \
defined(CPU_LINE_STM32F042x6) || defined(CPU_LINE_STM32F048xx) || \
defined(CPU_LINE_STM32F051x8) || defined(CPU_LINE_STM32F058xx) || \
defined(CPU_LINE_STM32F071xB) || defined(CPU_LINE_STM32F072xB) || \
defined(CPU_LINE_STM32F078xx) || defined(CPU_LINE_STM32F091xC) || \
defined(CPU_LINE_STM32F098xx)
#define VBAT_ADC_SCALE 2
#define VBAT_ADC_MIN_MV 1650
/* f2 */
#elif defined(CPU_LINE_STM32F205xx) || defined(CPU_LINE_STM32F207xx) || \
defined(CPU_LINE_STM32F215xx) || defined(CPU_LINE_STM32F217xx)
#define VBAT_ADC_SCALE 2
#define VBAT_ADC_MIN_MV 1800
/* f3 */
#elif defined(CPU_LINE_STM32F301x8) || defined(CPU_LINE_STM32F302x8) || \
defined(CPU_LINE_STM32F302xC) || defined(CPU_LINE_STM32F302xE) || \
defined(CPU_LINE_STM32F303x8) || defined(CPU_LINE_STM32F303xC) || \
defined(CPU_LINE_STM32F303xE) || defined(CPU_LINE_STM32F318x8) || \
defined(CPU_LINE_STM32F318xx) || defined(CPU_LINE_STM32F328xx) || \
defined(CPU_LINE_STM32F334x8) || defined(CPU_LINE_STM32F358xx) || \
defined(CPU_LINE_STM32F373xC) || defined(CPU_LINE_STM32F378xx) || \
defined(CPU_LINE_STM32F398xx)
#define VBAT_ADC_SCALE 2
#define VBAT_ADC_MIN_MV 1650
/* f4 */
#elif defined(CPU_LINE_STM32F401xC) || defined(CPU_LINE_STM32F401xE) || \
defined(CPU_LINE_STM32F410Cx) || defined(CPU_LINE_STM32F410Rx) || \
defined(CPU_LINE_STM32F410Tx) || defined(CPU_LINE_STM32F411xE) || \
defined(CPU_LINE_STM32F412Cx) || defined(CPU_LINE_STM32F412Rx) || \
defined(CPU_LINE_STM32F412Vx) || defined(CPU_LINE_STM32F412Zx) || \
defined(CPU_LINE_STM32F413xx) || defined(CPU_LINE_STM32F423xx) || \
defined(CPU_LINE_STM32F427xx) || defined(CPU_LINE_STM32F429xx) || \
defined(CPU_LINE_STM32F437xx) || defined(CPU_LINE_STM32F439xx) || \
defined(CPU_LINE_STM32F446xx) || defined(CPU_LINE_STM32F469xx) || \
defined(CPU_LINE_STM32F479xx)
#define VBAT_ADC_SCALE 4
#define VBAT_ADC_MIN_MV 1650
#elif defined(CPU_LINE_STM32F405xx) || defined(CPU_LINE_STM32F407xx) || \
defined(CPU_LINE_STM32F415xx) || defined(CPU_LINE_STM32F417xx)
#define VBAT_ADC_SCALE 2
#define VBAT_ADC_MIN_MV 1650
/* f7 */
#elif defined(CPU_LINE_STM32F722xx) || defined(CPU_LINE_STM32F723xx) || \
defined(CPU_LINE_STM32F730xx) || defined(CPU_LINE_STM32F732xx) || \
defined(CPU_LINE_STM32F733xx) || defined(CPU_LINE_STM32F745xx) || \
defined(CPU_LINE_STM32F746xx) || defined(CPU_LINE_STM32F750xx) || \
defined(CPU_LINE_STM32F756xx) || defined(CPU_LINE_STM32F765xx) || \
defined(CPU_LINE_STM32F767xx) || defined(CPU_LINE_STM32F769xx) || \
defined(CPU_LINE_STM32F777xx) || defined(CPU_LINE_STM32F779xx)
#define VBAT_ADC_SCALE 4
#define VBAT_ADC_MIN_MV 1650
/* g0 */
#elif defined(CPU_LINE_STM32G030xx) || defined(CPU_LINE_STM32G031xx) || \
defined(CPU_LINE_STM32G041xx) || defined(CPU_LINE_STM32G050xx) || \
defined(CPU_LINE_STM32G051xx) || defined(CPU_LINE_STM32G061xx) || \
defined(CPU_LINE_STM32G070xx) || defined(CPU_LINE_STM32G071xx) || \
defined(CPU_LINE_STM32G081xx) || defined(CPU_LINE_STM32G0B0xx) || \
defined(CPU_LINE_STM32G0B1xx) || defined(CPU_LINE_STM32G0C1xx)
#define VBAT_ADC_SCALE 3
#define VBAT_ADC_MIN_MV 1550
/* g4 */
#elif defined(CPU_LINE_STM32G431xx) || defined(CPU_LINE_STM32G441xx) || \
defined(CPU_LINE_STM32G471xx) || defined(CPU_LINE_STM32G473xx) || \
defined(CPU_LINE_STM32G474xx) || defined(CPU_LINE_STM32G483xx) || \
defined(CPU_LINE_STM32G484xx) || defined(CPU_LINE_STM32G491xx) || \
defined(CPU_LINE_STM32G4A1xx) || defined(CPU_LINE_STM32G441xx) || \
defined(CPU_LINE_STM32GBK1CB)
#define VBAT_ADC_SCALE 3
#define VBAT_ADC_MIN_MV 1550
/* l4 */
#elif defined(CPU_LINE_STM32L412xx) || defined(CPU_LINE_STM32L422xx) || \
defined(CPU_LINE_STM32L431xx) || defined(CPU_LINE_STM32L432xx) || \
defined(CPU_LINE_STM32L433xx) || defined(CPU_LINE_STM32L442xx) || \
defined(CPU_LINE_STM32L443xx) || defined(CPU_LINE_STM32L451xx) || \
defined(CPU_LINE_STM32L452xx) || defined(CPU_LINE_STM32L462xx) || \
defined(CPU_LINE_STM32L471xx) || defined(CPU_LINE_STM32L475xx) || \
defined(CPU_LINE_STM32L476xx) || defined(CPU_LINE_STM32L485xx) || \
defined(CPU_LINE_STM32L486xx) || defined(CPU_LINE_STM32L496xx) || \
defined(CPU_LINE_STM32L4A6xx) || defined(CPU_LINE_STM32L4P5xx) || \
defined(CPU_LINE_STM32L4Q5xx) || defined(CPU_LINE_STM32L4R5xx) || \
defined(CPU_LINE_STM32L4R7xx) || defined(CPU_LINE_STM32L4R9xx) || \
defined(CPU_LINE_STM32L4S5xx) || defined(CPU_LINE_STM32L4S7xx) || \
defined(CPU_LINE_STM32L4S9xx)
#define VBAT_ADC_SCALE 3
#define VBAT_ADC_MIN_MV 1550
/* l5 */
#elif defined(CPU_LINE_STM32L552xx) || defined(CPU_LINE_STM32L562xx)
#define VBAT_ADC_SCALE 3
#define VBAT_ADC_MIN_MV 1550
/* u5 */
#elif defined(CPU_LINE_STM32U575xx) || defined(CPU_LINE_STM32U585xx)
#define VBAT_ADC_SCALE 4
#define VBAT_ADC_MIN_MV 1650
/* wb */
#elif defined(CPU_LINE_STM32WB10xx) || defined(CPU_LINE_STM32WB15xx) || \
defined(CPU_LINE_STM32WB30xx) || defined(CPU_LINE_STM32WB35xx) || \
defined(CPU_LINE_STM32WB50xx) || defined(CPU_LINE_STM32WB55xx) || \
defined(CPU_LINE_STM32WB5Mxx)
#define VBAT_ADC_SCALE 3
#define VBAT_ADC_MIN_MV 1550
/* wl */
#elif defined(CPU_LINE_STM32WL54xx) || defined(CPU_LINE_STM32WL55xx) || \
defined(CPU_LINE_STM32WLE4xx) || defined(CPU_LINE_STM32WLE5xx)
#define VBAT_ADC_SCALE 3
#define VBAT_ADC_MIN_MV 1550
#else
#error "VBAT: CPU line is not supported so far."
#endif
/** @} */
/**
* @name VBAT enable register
* @{
*/
#if defined(CPU_LINE_STM32F373xC) || defined(CPU_LINE_STM32F378xx)
#define ADC_CCR_REG (SYSCFG->CFGR1) /* ADCx_COMMON is also defined */
#elif defined(ADC_COMMON)
#define ADC_CCR_REG (ADC_COMMON->CCR)
#elif defined(ADC1_COMMON)
#define ADC_CCR_REG (ADC1_COMMON->CCR)
#elif defined(ADC12_COMMON)
#define ADC_CCR_REG (ADC12_COMMON->CCR)
#elif defined(ADC123_COMMON)
#define ADC_CCR_REG (ADC123_COMMON->CCR)
#elif defined(ADC12_COMMON_NS)
#define ADC_CCR_REG (ADC12_COMMON_NS->CCR)
#elif defined(ADC)
#define ADC_CCR_REG (ADC->CCR)
#else
#error "VBAT: CPU line is not supported so far."
#endif
/** @} */
/**
* @name VBAT enable flag
* @{
*/
#if defined(ADC_CCR_VBATEN)
#define VBAT_ENABLE ADC_CCR_VBATEN;
#elif defined(ADC_CCR_VBATE)
#define VBAT_ENABLE ADC_CCR_VBATE;
#elif defined(ADC_CCR_VBATSEL)
#define VBAT_ENABLE ADC_CCR_VBATSEL;
#elif defined(SYSCFG_CFGR1_VBAT)
#define VBAT_ENABLE SYSCFG_CFGR1_VBAT;
#else
#error "VBAT: CPU line is not supported so far."
#endif
/** @} */
#ifndef CONFIG_VBAT_ADC_VREF_MV
#define CONFIG_VBAT_ADC_VREF_MV 3300 /**< ADC reference voltage */
#endif
/**
* @brief Override this function if you know how to retrieve the accurate
* ADC supply voltage in mV for your board. The default behaviour is
* to return @ref CONFIG_VBAT_ADC_VREF_MV.
* Once there is a driver to sample VREFINT, this function is likely
* to be changed.
*/
int32_t __attribute__((weak)) vref_mv(void) {
return CONFIG_VBAT_ADC_VREF_MV;
}
#ifndef VBAT_ADC
#error "VBAT: Add internal VBAT ADC line to adc_config[] and #define VBAT_ADC."
#endif
int vbat_init(void)
{
return adc_init(VBAT_ADC);
}
void vbat_enable(void)
{
ADC_CCR_REG |= VBAT_ENABLE;
}
void vbat_disable(void)
{
ADC_CCR_REG &= ~VBAT_ENABLE;
}
int32_t vbat_sample_mv(void)
{
int32_t mv = adc_sample(VBAT_ADC, VBAT_ADC_RES);
mv = (mv * VBAT_ADC_SCALE * vref_mv()) / VBAT_ADC_MAX;
return mv;
}
bool vbat_is_empty(void)
{
return VBAT_ADC_MIN_MV > vbat_sample_mv();
}

View File

@ -170,4 +170,5 @@ config HAVE_SHARED_PERIPH_RTT_PERIPH_RTC
only one can be selected.
rsource "Kconfig.timer"
rsource "Kconfig.vbat"
rsource "Kconfig.wdt"

View File

@ -0,0 +1,39 @@
# 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.
#
menuconfig MODULE_PERIPH_VBAT
bool "Backup Battery monitoring driver"
depends on HAS_PERIPH_VBAT
depends on HAS_PERIPH_ADC
depends on TEST_KCONFIG
select MODULE_PERIPH_ADC
if MODULE_PERIPH_VBAT
config MODULE_PERIPH_INIT_VBAT
bool "Auto initialize VBAT ADC line"
default y if MODULE_PERIPH_INIT
config VBAT_ADC_VREF_MV
int "ADC reference voltage in mV"
default 3300
endif # MODULE_PERIPH_VBAT
menuconfig KCONFIG_USEMODULE_PERIPH_VBAT
bool "Configure backup battery monitoring peripheral driver"
depends on USEMODULE_PERIPH_VBAT
help
Configure backup battery monitoring peripheral driver using Kconfig.
config VBAT_ADC_VREF_MV
int "ADC reference voltage in mV"
default 3300
depends on KCONFIG_USEMODULE_PERIPH_VBAT
help
This is the reference voltage (VREF) of the ADC.
Often VREF is connected with VDDA, which is equal to VDD.

View File

@ -369,6 +369,11 @@ config HAS_PERIPH_USBDEV
help
Indicates that an USBDEV peripheral is present.
config HAS_PERIPH_VBAT
bool
help
Indicates that backup battery monitoring is supported
config HAS_PERIPH_WDT
bool
help