Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix stm32wl adc driver with PM #72809

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Martdur
Copy link

@Martdur Martdur commented May 15, 2024

Description

This PR introduce a fix for the issue #37352 by reinitializing the adc when going outside LPM using the Device Runtime Power Management.

Type of change

  • Bug fix

Test steps

  • Add nucleo_wl55jc.overlay to samples/drivers/adc/boards
 / {
	zephyr,user {
		io-channels = <&adc1 11>;
	};
};

&adc1 {
	pinctrl-0 = <&adc_in11_pa15>;
	status = "okay";
};
  • Add CONFIG_PM=y
  • Build for the nucleo_wl55jc
  • Check that the sample work well with and without CONFIG_PM

@zephyrbot zephyrbot added platform: STM32 ST Micro STM32 area: ADC Analog-to-Digital Converter (ADC) labels May 15, 2024
@aurel32
Copy link
Collaborator

aurel32 commented May 15, 2024

Incidentally I was also trying to get the power management working for the ADC...

* Check that the sample work well with and without `CONFIG_PM`

As the code you added uses the runtime device power management, you probably want to also set `PM_DEVICE_RUNTIME=y'

Copy link
Collaborator

@aurel32 aurel32 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My finding is that enabling the runtime device power management for the ADC breaks the internal channels drivers. The calls to LL_ADC_SetCommonPathInternalCh have recently been moved out of the ADC driver to the stm32_temp, stm32_vbat and stm32_vref, which is not possible anymore once the ADC is suspended, as the clock is disabled.

@gautierg-st do you have any idea how to fix that?

@@ -613,6 +614,12 @@ static int adc_stm32_calibrate(const struct device *dev)
}
#endif /* CONFIG_SOC_SERIES_STM32H7X */

/* enable device runtime power management */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure it is the best place to do that, you probably rather want to do that in adc_stm32_init instead

@@ -1111,6 +1118,7 @@ static void adc_stm32_isr(const struct device *dev)
}

LOG_DBG("%s ISR triggered.", dev->name);
pm_device_runtime_put(dev);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is correct, but you probably want to do the same for the DMA case

@@ -1141,6 +1149,11 @@ static int adc_stm32_read(const struct device *dev,
struct adc_stm32_data *data = dev->data;
int error;

error = pm_device_runtime_get(dev);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

@aurel32
Copy link
Collaborator

aurel32 commented May 15, 2024

Note that I have been able to get the ADC in Stop 2 mode with the recently added PM ADC code. For that you need of course CONFIG_PM=y and also CONFIG_PM_DEVICE=y. In case CONFIG_PM_DEVICE_RUNTIME=y you also need to ensure that CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n, to avoid the assumptions that all devices are already sleeping when entering stop mode. Note that the default value is =y.

@aurel32
Copy link
Collaborator

aurel32 commented May 16, 2024

My finding is that enabling the runtime device power management for the ADC breaks the internal channels drivers. The calls to LL_ADC_SetCommonPathInternalCh have recently been moved out of the ADC driver to the stm32_temp, stm32_vbat and stm32_vref, which is not possible anymore once the ADC is suspended, as the clock is disabled.

@gautierg-st do you have any idea how to fix that?

Answering myself, this is as simple as calling pm device runtime functions from the stm32 sensors code:

diff --git a/drivers/sensor/st/stm32_vref/stm32_vref.c b/drivers/sensor/st/stm32_vref/stm32_vref.c
index 14412a6579a..d3060aed312 100644
--- a/drivers/sensor/st/stm32_vref/stm32_vref.c
+++ b/drivers/sensor/st/stm32_vref/stm32_vref.c
@@ -11,6 +11,7 @@
 #include <zephyr/drivers/sensor.h>
 #include <zephyr/drivers/adc.h>
 #include <zephyr/logging/log.h>
+#include <zephyr/pm/device_runtime.h>
 #include <stm32_ll_adc.h>
 #if defined(CONFIG_SOC_SERIES_STM32H5X)
 #include <stm32_ll_icache.h>
@@ -46,6 +47,7 @@ static int stm32_vref_sample_fetch(const struct device *dev, enum sensor_channel
 
        k_mutex_lock(&data->mutex, K_FOREVER);
 
+       pm_device_runtime_get(data->adc);
        rc = adc_channel_setup(data->adc, &data->adc_cfg);
        if (rc) {
                LOG_DBG("Setup AIN%u got %d", data->adc_cfg.channel_id, rc);
@@ -71,6 +73,7 @@ static int stm32_vref_sample_fetch(const struct device *dev, enum sensor_channel
 
 
 unlock:
+       pm_device_runtime_put(data->adc);
        k_mutex_unlock(&data->mutex);
 
        return rc;

I can open a proper PR later as it does not require the current changes to work.

That said that also pointed me that adding pm runtime support breaks the channel_setup method as it runs with the device suspended (and thus has no access to the ADC registers) and anyway we can't prevent the ADC to go into suspend between channel_setup and the read, which means erasing all registers, without asking users to also add pm device runtime functions to their code.

@Martdur
Copy link
Author

Martdur commented May 23, 2024

I'm not sure to understand all what you said @aurel32.
Is my PR still relevant ?
Do I have to force those configs if using STM32WL with adc and PM ?

@aurel32
Copy link
Collaborator

aurel32 commented May 23, 2024

I'm not sure to understand all what you said @aurel32. Is my PR still relevant ? Do I have to force those configs if using STM32WL with adc and PM ?

I think your PR is still relevant, and where we want to go long term. It however had some consequences that need to be fixed first. One of them is fixed in #72989. The other is that the adc_stm32_channel_setup will not work anymore with your patch applied.

In the meantime a workaround is to either use CONFIG_PM_DEVICE_RUNTIME=n or set CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n in case it is not possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: ADC Analog-to-Digital Converter (ADC) platform: STM32 ST Micro STM32
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants