samples: board: stm32 pm: add adc power management sample
Add a sample for STM32 ADC power management Signed-off-by: Guillaume Gautier <guillaume.gautier-ext@st.com>
This commit is contained in:
parent
479ba144a7
commit
2caf720c51
8 changed files with 234 additions and 0 deletions
7
samples/boards/stm32/power_mgmt/adc/CMakeLists.txt
Normal file
7
samples/boards/stm32/power_mgmt/adc/CMakeLists.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(stm32_pm_adc)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
42
samples/boards/stm32/power_mgmt/adc/README.rst
Normal file
42
samples/boards/stm32/power_mgmt/adc/README.rst
Normal file
|
@ -0,0 +1,42 @@
|
|||
.. _stm32-pm-adc-sample:
|
||||
|
||||
STM32 PM ADC
|
||||
############
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
This sample is a minimum application to demonstrate basic power management
|
||||
behavior in a basic ADC set up in low power context.
|
||||
|
||||
.. _stm32-pm-adc-sample-requirements:
|
||||
|
||||
Requirements
|
||||
************
|
||||
|
||||
The board should support enabling PM. For a STM32 based target, it means that
|
||||
it should support a clock source alternative to Cortex Systick that can be used
|
||||
in core sleep states, as LPTIM (:dtcompatible:`st,stm32-lptim`).
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
|
||||
Build and flash as follows, changing ``nucleo_wb55rg`` for your board:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/boards/stm32/power_mgmt/adc
|
||||
:board: nucleo_wb55rg
|
||||
:goals: build flash
|
||||
:compact:
|
||||
|
||||
After flashing, the console shows the ADC measurement in the form:
|
||||
``ADC reading[0]:``
|
||||
``- adc@50040000, channel 3: 1158 = 932 mV``
|
||||
|
||||
PM configurations
|
||||
*****************
|
||||
|
||||
By default, :kconfig:option:`CONFIG_PM_DEVICE` and :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME` are
|
||||
enabled.
|
||||
On STM32WB, we can observe a power consumption of about 25µA with both kconfig
|
||||
enabled, 27.5µA without (each time with :kconfig:option:`CONFIG_PM` enabled).
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2023 STMicroelectronics
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/adc/adc.h>
|
||||
|
||||
/ {
|
||||
zephyr,user {
|
||||
/* adjust channel number according to pinmux in board.dts */
|
||||
io-channels = <&adc1 1>;
|
||||
};
|
||||
};
|
||||
|
||||
&adc1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@1 {
|
||||
reg = <1>;
|
||||
zephyr,gain = "ADC_GAIN_1";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2023 STMicroelectronics
|
||||
*/
|
||||
|
||||
/ {
|
||||
zephyr,user {
|
||||
/* adjust channel number according to pinmux in board.dts */
|
||||
io-channels = <&adc1 3>;
|
||||
};
|
||||
};
|
||||
|
||||
&adc1 {
|
||||
pinctrl-0 = <&adc1_in3_pc2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
channel@3 {
|
||||
reg = <3>;
|
||||
zephyr,gain = "ADC_GAIN_1";
|
||||
zephyr,reference = "ADC_REF_INTERNAL";
|
||||
zephyr,acquisition-time = <ADC_ACQ_TIME_MAX>;
|
||||
zephyr,resolution = <12>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2023 STMicroelectronics
|
||||
*/
|
||||
|
||||
/ {
|
||||
zephyr,user {
|
||||
/* adjust channel number according to pinmux in board.dts */
|
||||
io-channels = <&adc4 8>;
|
||||
};
|
||||
};
|
6
samples/boards/stm32/power_mgmt/adc/prj.conf
Normal file
6
samples/boards/stm32/power_mgmt/adc/prj.conf
Normal file
|
@ -0,0 +1,6 @@
|
|||
CONFIG_PM=y
|
||||
CONFIG_PM_DEVICE=y
|
||||
CONFIG_PM_DEVICE_RUNTIME=y
|
||||
CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n
|
||||
CONFIG_ADC=y
|
||||
#CONFIG_DEBUG=y
|
17
samples/boards/stm32/power_mgmt/adc/sample.yaml
Normal file
17
samples/boards/stm32/power_mgmt/adc/sample.yaml
Normal file
|
@ -0,0 +1,17 @@
|
|||
sample:
|
||||
name: STM32 ADC Power Management
|
||||
tests:
|
||||
sample.boards.stm32.power_mgmt.adc:
|
||||
tags:
|
||||
- ADC
|
||||
- power
|
||||
harness: console
|
||||
harness_config:
|
||||
type: one_line
|
||||
regex:
|
||||
- "Device ready"
|
||||
filter: dt_compat_enabled("zephyr,power-state") and
|
||||
dt_compat_enabled("st,stm32-adc") and
|
||||
dt_compat_enabled("st,stm32-lptim")
|
||||
extra_args: "CONFIG_DEBUG=y"
|
||||
platform_allow: nucleo_wb55rg
|
97
samples/boards/stm32/power_mgmt/adc/src/main.c
Normal file
97
samples/boards/stm32/power_mgmt/adc/src/main.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2023 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/adc.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
|
||||
#define SLEEP_TIME_MS 2000
|
||||
|
||||
#if !DT_NODE_EXISTS(DT_PATH(zephyr_user)) || \
|
||||
!DT_NODE_HAS_PROP(DT_PATH(zephyr_user), io_channels)
|
||||
#error "No suitable devicetree overlay specified"
|
||||
#endif
|
||||
|
||||
#define DT_SPEC_AND_COMMA(node_id, prop, idx) \
|
||||
ADC_DT_SPEC_GET_BY_IDX(node_id, idx),
|
||||
|
||||
/* Data of ADC io-channels specified in devicetree. */
|
||||
static const struct adc_dt_spec adc_channels[] = {
|
||||
DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels,
|
||||
DT_SPEC_AND_COMMA)
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err;
|
||||
uint32_t count = 0;
|
||||
uint16_t buf;
|
||||
struct adc_sequence sequence = {
|
||||
.buffer = &buf,
|
||||
/* buffer size in bytes, not number of samples */
|
||||
.buffer_size = sizeof(buf),
|
||||
};
|
||||
|
||||
/* Configure channels individually prior to sampling. */
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
|
||||
if (!adc_is_ready_dt(&adc_channels[i])) {
|
||||
printk("ADC controller device %s not ready\n", adc_channels[i].dev->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = adc_channel_setup_dt(&adc_channels[i]);
|
||||
if (err < 0) {
|
||||
printk("Could not setup channel #%d (%d)\n", i, err);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
printk("Device ready\n");
|
||||
|
||||
while (true) {
|
||||
printk("ADC reading[%u]:\n", count++);
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) {
|
||||
int32_t val_mv;
|
||||
|
||||
printk("- %s, channel %d: ",
|
||||
adc_channels[i].dev->name,
|
||||
adc_channels[i].channel_id);
|
||||
|
||||
(void)adc_sequence_init_dt(&adc_channels[i], &sequence);
|
||||
|
||||
err = adc_read_dt(&adc_channels[i], &sequence);
|
||||
if (err < 0) {
|
||||
printk("Could not read (%d)\n", err);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If using differential mode, the 16 bit value
|
||||
* in the ADC sample buffer should be a signed 2's
|
||||
* complement value.
|
||||
*/
|
||||
if (adc_channels[i].channel_cfg.differential) {
|
||||
val_mv = (int32_t)((int16_t)buf);
|
||||
} else {
|
||||
val_mv = (int32_t)buf;
|
||||
}
|
||||
printk("%"PRId32, val_mv);
|
||||
err = adc_raw_to_millivolts_dt(&adc_channels[i],
|
||||
&val_mv);
|
||||
/* conversion to mV may not be supported, skip if not */
|
||||
if (err < 0) {
|
||||
printk(" (value in mV not available)\n");
|
||||
} else {
|
||||
printk(" = %"PRId32" mV\n", val_mv);
|
||||
}
|
||||
}
|
||||
|
||||
k_msleep(SLEEP_TIME_MS);
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue