Power Driver for stm32l1

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Power Driver for stm32l1

Postby vrollei » Wed Mar 22, 2017 6:34 pm

Hi,

I implemented simple Power Driver for STM32L1,
it supports:
- low power sleep mode with active chibios ST timer (tickless mode)
- switching between HSI in run mode and MSI in LP sleep mode
- configurable MSI clock source for LP sleep mode
- configurable VOS for LP
- automatic clock switching to MSI for LP mode, timer prescaler modification and back to HSI for run mode
- hooks for disable/enable periphs
- chibios drivers state checking - activate LP sleep mode if all drivers are in stop state
- simple calibration to compensate delays in CH_CFG_IDLE_ENTER_HOOK/CH_CFG_IDLE_LEAVE_HOOK

result: about 5uA in LP deep sleep mode @ 65kHz MSI

so I would like to discuss high level driver interface, some chibios modification (MSI values at least, and new feature: bit field for all drivers state) and share the source code.
Vitaly

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Power Driver for stm32l1

Postby Giovanni » Wed Mar 22, 2017 6:39 pm

Hi,

Some of those features look too much L1-specific for an abstraction. You need to split them in:
- Required changes to existing infrastructure.
- An STM32L1-specific low power driver/library.
- Parts that can be abstracted.

Giovanni

vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Power Driver for stm32l1

Postby vrollei » Thu Mar 23, 2017 8:28 pm

Hi,

1. Required changes to existing infrastructure
1.1. Always inline attribute to support gcc -O0: static inline void port_wait_for_interrupt(void) __attribute__((always_inline));
1.2. Switching clock source HSI <-> MSI and MSI <-> MSI requires MSI frequencies values to be rounded to power of 2.
Temporary adde to stm32l1 hal_lld.h:
#if !defined(STM32_MSI_NOTROUNDED) || STM32_MSI_NOTROUNDED == FALSE
#if STM32_MSIRANGE == STM32_MSIRANGE_64K
#define STM32_MSICLK 65500
#elif STM32_MSIRANGE == STM32_MSIRANGE_128K
#define STM32_MSICLK 131000
#elif STM32_MSIRANGE == STM32_MSIRANGE_256K
#define STM32_MSICLK 262000
#elif STM32_MSIRANGE == STM32_MSIRANGE_512K
#define STM32_MSICLK 524000
#elif STM32_MSIRANGE == STM32_MSIRANGE_1M
#define STM32_MSICLK 1050000
#elif STM32_MSIRANGE == STM32_MSIRANGE_2M
#define STM32_MSICLK 2100000
#elif STM32_MSIRANGE == STM32_MSIRANGE_4M
#define STM32_MSICLK 4200000
#else
#error "invalid STM32_MSIRANGE value specified"
#endif

#else
#if STM32_MSIRANGE == STM32_MSIRANGE_64K
#define STM32_MSICLK 65536
#elif STM32_MSIRANGE == STM32_MSIRANGE_128K
#define STM32_MSICLK 131072
#elif STM32_MSIRANGE == STM32_MSIRANGE_256K
#define STM32_MSICLK 262144
#elif STM32_MSIRANGE == STM32_MSIRANGE_512K
#define STM32_MSICLK 524288
#elif STM32_MSIRANGE == STM32_MSIRANGE_1M
#define STM32_MSICLK 1048576
#elif STM32_MSIRANGE == STM32_MSIRANGE_2M
#define STM32_MSICLK 2097152
#elif STM32_MSIRANGE == STM32_MSIRANGE_4M
#define STM32_MSICLK 4194304
#else
#error "invalid STM32_MSIRANGE value specified"
#endif
#endif

1.3 New feature request: drivers state in one bit field. Reason: Power Driver has to check all active drivers state and activates Low Power Sleep mode only if all drivers are not in Active state. Currently it is implemented this way (example of one driver check):

#define PWR_IS_DRIVER_ACTIVE(driverType, driver) {if (driver.state == driverType ## _ACTIVE) return;}

#if HAL_USE_SPI == TRUE
#if STM32_SPI_USE_SPI1 == TRUE
PWR_IS_DRIVER_ACTIVE(SPI, SPID1);
#endif
#if STM32_SPI_USE_SPI2 == TRUE
PWR_IS_DRIVER_ACTIVE(SPI, SPID2);
#endif
#endif


As result there are a lot of if statements.
So with Drivers State bit field there will be only one if statement with comparison of bit field and mask.

2. An STM32L1-specific low power driver/library: how to share source code of driver? as a post?

3. Parts that can be abstracted:
3.1 types:
Driver state: PWR_UNINIT/PWR_STOP/PWR_ACTIVE
Driver mode: values are lld specific
3.2 interface:
// Driver initialisation
void pwrInit(void);
// Driver activation
void pwrStart(void);
// Driver deactivation
void pwrStop(void);
// State of driver
pwrstate_t pwrGetState(void);
// Driver mode selection (e.g. for STM32L1 PWR_MODE_LOW_POWER_RUN or PWR_MODE_LOW_POWER_SLEEP)
void pwrSetMode(pwrmode_t mode);
// Current mode
pwrmode_t pwrGetMode(void);

// CH_CFG_IDLE_ENTER_HOOK and CH_CFG_IDLE_LEAVE_HOOK hooks implementation
inline void pwrEnterSleepMode(void) __attribute__((always_inline));
inline void pwrExitSleepMode(void) __attribute__((always_inline));
Vitaly

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Power Driver for stm32l1

Postby Giovanni » Sat Mar 25, 2017 5:17 pm

Hi,

I see most of your points, could you explain why the rounding to power of two is required?

About the power manager, you suggest to check if any driver is active, this is complex for several reasons:
1) The active state is not always XXX_ACTIVE, it could be XXX_READY, XXX_TRANSMITTING etc.
2) Checking drivers is platform-dependent and an nightmare of preprocessor #if.

I don't like that approach much, a possible alternative solution is introduce in the power manager an API that the other drivers can use to communicate their minimum compatible power state. This API could be called in xxx_lld_start() and xxx_lld_stop() in the code path where activation and deactivation occurs. This manager would also require an abstraction of run states and sleep states that the various drivers can use to declare their capability, for example:

PWR_RUN_FULL
PWR_RUN_LOW

PWR_STATE_HALT
PWR_STATE_STOP
PWR_STATE_STANDBY

etc

The manager would just keep track of the current state and the current "minimum", an attempt to switch to a state below the minimum would trigger an assertion and not be executed anyway.

This kind of mechanisms will have to wait for the next development branch (HAL 6), the code in the repository trunk (HAL 5) is frozen for release except small bug fixes.

Please everybody, post power-related ideas in this thread.

Giovanni

vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Power Driver for stm32l1

Postby vrollei » Sat Mar 25, 2017 6:12 pm

Hi,

1. rounding is required to have common CH_CFG_ST_FREQUENCY 1024Hz for all MSI values and HSI 16MHz system clock frequencies.
E.g. 16MHz for run mode and 65536 Hz for low power sleep mode, there is greatest common divisor 1024.
We will only 500Hz CH_CFG_ST_FREQUENCY for 65500 Hz MSI and 16MHz HSI.

2. Support drivers state interface

2.1 STM32L1/L0 power modes:
- low power run (not implemented yet)
- sleep (implemented in chibios idle thread)
- low power sleep (implemented in power manager driver)
- stop (not implemented yet)
- standby (not implemented yet)

STM32F4 modes:
- sleep
- stop
- standby

So it is lld specific and all drivers need to know it to register in Power Driver with minimum compatible state.
Will we have some high level abstraction and mapping to low level microcontroller specific states or have lld compatibility declaration for
PWR_RUN_FULL
PWR_RUN_LOW

PWR_STATE_HALT
PWR_STATE_STOP
PWR_STATE_STANDBY


2.2. New interfaces to support driver registration and driver state change notification

void pwrDriverRegistration(driver_id, supported_min_level, current_state)
void pwrDriverNotification(driver_id, current_state);

Is this correct?
Vitaly

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Power Driver for stm32l1

Postby Giovanni » Sat Mar 25, 2017 7:53 pm

Hi,

It is correct overall, that is the general idea, it will require a huge rework of all drivers, F4 and others also have an option to clock/notclock a peripheral in sleep mode, currently it is not used.

Right now I want just to focus on next release, it is long overdue, this is work for the next development arc.

Giovanni

vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Power Driver for stm32l1

Postby vrollei » Sat Mar 25, 2017 8:10 pm

Hi,

ok, I will clean up current version to separate high level and low level and prepare new interface.
Just let me know how we will get drivers identification for registration/notification.
Vitaly

vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Power Driver for stm32l1

Postby vrollei » Tue Jun 13, 2017 8:02 pm

Hi,

is there any chance to continue discussion?
Vitaly

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Power Driver for stm32l1

Postby Giovanni » Tue Jun 13, 2017 8:24 pm

Hi,

We can discuss the topic but there are some unresolved issues in my mind.

My general idea is to have a counter for each "power state", each driver increases the counter of its minimal power state on start() and decreases it on stop(). The lowest counter != 0 is the power state compatible with current drivers situation.

Problem:
- Power states are dependent on the devices, we don't want to make SPI drivers for L0, L1, L4, F0 etc etc so we don't want drivers to "know" about states.

Giovanni

vrollei
Posts: 163
Joined: Sun Nov 13, 2016 8:44 am
Been thanked: 26 times

Re: Power Driver for stm32l1

Postby vrollei » Tue Jun 13, 2017 10:13 pm

Hi,

L0, L1, L4, F0 and F4 have the same low power modes:
sleep
low power sleep (only for Lx)
stop (L4 has submodes)
standby

if counter shows active driver counts then it is enough to make decision: not to enter low power mode below sleep.

optional submodes currently implemented as macro in lld and add optional method in high level:

#if PWR_HAS_STOP_MODES == TRUE

void pwrSetStopSubmode(pwr_stop_mode_t mode);

pwr_stop_mode_t pwrGetStopSubmode(void);

#endif

optional low power sleep mode can be implemented as well.

So I think counter of active drivers will be a good solution
Vitaly


Return to “Development and Feedback”

Who is online

Users browsing this forum: No registered users and 19 guests