drivers: sensor: add a stm32 sensor driver for the internal VBat
Similar to the internal temperature sensor of the stm32 this driver controls the Vbat monitoring in Volts, using an ADC internal input and the stm32-vbat node of the DTS. The ref voltage is given by the ADC. Note that stm32F1x does not propose the feature. Signed-off-by: Francois Ramu <francois.ramu@st.com>
This commit is contained in:
parent
4f7a490506
commit
32222e07a4
5 changed files with 146 additions and 0 deletions
|
@ -89,6 +89,7 @@ add_subdirectory_ifdef(CONFIG_SI7210 si7210)
|
|||
add_subdirectory_ifdef(CONFIG_SM351LT sm351lt)
|
||||
add_subdirectory_ifdef(CONFIG_HAS_STMEMSC stmemsc)
|
||||
add_subdirectory_ifdef(CONFIG_STM32_TEMP stm32_temp)
|
||||
add_subdirectory_ifdef(CONFIG_STM32_VBAT stm32_vbat)
|
||||
add_subdirectory_ifdef(CONFIG_STTS751 stts751)
|
||||
add_subdirectory_ifdef(CONFIG_SX9500 sx9500)
|
||||
add_subdirectory_ifdef(CONFIG_TH02 th02)
|
||||
|
|
|
@ -216,6 +216,8 @@ source "drivers/sensor/sm351lt/Kconfig"
|
|||
|
||||
source "drivers/sensor/stm32_temp/Kconfig"
|
||||
|
||||
source "drivers/sensor/stm32_vbat/Kconfig"
|
||||
|
||||
source "drivers/sensor/stts751/Kconfig"
|
||||
|
||||
source "drivers/sensor/sx9500/Kconfig"
|
||||
|
|
5
drivers/sensor/stm32_vbat/CMakeLists.txt
Normal file
5
drivers/sensor/stm32_vbat/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(stm32_vbat.c)
|
10
drivers/sensor/stm32_vbat/Kconfig
Normal file
10
drivers/sensor/stm32_vbat/Kconfig
Normal file
|
@ -0,0 +1,10 @@
|
|||
# STM32 battery sensor configuration options
|
||||
|
||||
# Copyright (c) 2022 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config STM32_VBAT
|
||||
bool "STM32 Vbat Sensor"
|
||||
depends on ADC && (SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X)
|
||||
help
|
||||
Enable driver for STM32 Vbat sensor and then also ADC
|
128
drivers/sensor/stm32_vbat/stm32_vbat.c
Normal file
128
drivers/sensor/stm32_vbat/stm32_vbat.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (c) 2022 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <device.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <drivers/adc.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(stm32_vbat, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_vbat)
|
||||
#define DT_DRV_COMPAT st_stm32_vbat
|
||||
#else
|
||||
#error "No compatible devicetree node found"
|
||||
#endif
|
||||
|
||||
struct stm32_vbat_data {
|
||||
const struct device *adc;
|
||||
const struct adc_channel_cfg adc_cfg;
|
||||
struct adc_sequence adc_seq;
|
||||
struct k_mutex mutex;
|
||||
int16_t sample_buffer;
|
||||
int16_t raw; /* raw adc Sensor value */
|
||||
};
|
||||
|
||||
struct stm32_vbat_config {
|
||||
uint16_t vref_mv;
|
||||
int ratio;
|
||||
};
|
||||
|
||||
static int stm32_vbat_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
struct stm32_vbat_data *data = dev->data;
|
||||
struct adc_sequence *sp = &data->adc_seq;
|
||||
int rc;
|
||||
|
||||
if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_VOLTAGE) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
k_mutex_lock(&data->mutex, K_FOREVER);
|
||||
|
||||
rc = adc_channel_setup(data->adc, &data->adc_cfg);
|
||||
|
||||
if (rc) {
|
||||
LOG_DBG("Setup AIN%u got %d", data->adc_cfg.channel_id, rc);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
rc = adc_read(data->adc, sp);
|
||||
if (rc == 0) {
|
||||
data->raw = data->sample_buffer;
|
||||
}
|
||||
|
||||
unlock:
|
||||
k_mutex_unlock(&data->mutex);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int stm32_vbat_channel_get(const struct device *dev, enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct stm32_vbat_data *data = dev->data;
|
||||
const struct stm32_vbat_config *cfg = dev->config;
|
||||
float voltage;
|
||||
|
||||
if (chan != SENSOR_CHAN_VOLTAGE) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
voltage = data->raw * cfg->vref_mv / 0x0FFF; /* Sensor value in millivolts */
|
||||
/* considering the vbat input through a resistor bridge */
|
||||
voltage = voltage * cfg->ratio / 1000; /* value of SENSOR_CHAN_VOLTAGE in Volt */
|
||||
|
||||
return sensor_value_from_double(val, voltage);
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api stm32_vbat_driver_api = {
|
||||
.sample_fetch = stm32_vbat_sample_fetch,
|
||||
.channel_get = stm32_vbat_channel_get,
|
||||
};
|
||||
|
||||
static int stm32_vbat_init(const struct device *dev)
|
||||
{
|
||||
struct stm32_vbat_data *data = dev->data;
|
||||
struct adc_sequence *asp = &data->adc_seq;
|
||||
|
||||
k_mutex_init(&data->mutex);
|
||||
|
||||
if (!device_is_ready(data->adc)) {
|
||||
LOG_ERR("Device %s is not ready", data->adc->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
*asp = (struct adc_sequence){
|
||||
.channels = BIT(data->adc_cfg.channel_id),
|
||||
.buffer = &data->sample_buffer,
|
||||
.buffer_size = sizeof(data->sample_buffer),
|
||||
.resolution = 12U,
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define STM32_VBAT DT_PROP(DT_INST_IO_CHANNELS_CTLR(0), vref_mv)
|
||||
|
||||
static struct stm32_vbat_config stm32_vbat_dev_config = {
|
||||
.vref_mv = DT_PROP(DT_INST_IO_CHANNELS_CTLR(0), vref_mv),
|
||||
.ratio = DT_INST_PROP(0, ratio),
|
||||
};
|
||||
|
||||
static struct stm32_vbat_data stm32_vbat_dev_data = {
|
||||
.adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(0)),
|
||||
.adc_cfg = {
|
||||
.gain = ADC_GAIN_1,
|
||||
.reference = ADC_REF_INTERNAL,
|
||||
.acquisition_time = ADC_ACQ_TIME_MAX,
|
||||
.channel_id = DT_INST_IO_CHANNELS_INPUT(0),
|
||||
.differential = 0,
|
||||
},
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, stm32_vbat_init, NULL, &stm32_vbat_dev_data, &stm32_vbat_dev_config,
|
||||
POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &stm32_vbat_driver_api);
|
Loading…
Add table
Add a link
Reference in a new issue