This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new e8277f3a5 stm32/hal_timer: Improve timer power consumption
e8277f3a5 is described below
commit e8277f3a5a9ec4b8c56b0e8d7751af725da4a13f
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Sun Jun 2 15:30:02 2024 +0200
stm32/hal_timer: Improve timer power consumption
Code allows to disable hal timer after it was running
for some time (number over overflows) and it was not used
for anything.
This can reduce power consumption without sacrificing usability.
This can be useful for cputimer that is required but not used
extensively.
Signed-off-by: Jerzy Kasenberg <[email protected]>
---
hw/mcu/stm/stm32_common/src/hal_timer.c | 25 +++++++++++++++++++++++++
hw/mcu/stm/stm32_common/syscfg.yml | 12 ++++++++++++
2 files changed, 37 insertions(+)
diff --git a/hw/mcu/stm/stm32_common/src/hal_timer.c
b/hw/mcu/stm/stm32_common/src/hal_timer.c
index 023ace55e..de91262a3 100644
--- a/hw/mcu/stm/stm32_common/src/hal_timer.c
+++ b/hw/mcu/stm/stm32_common/src/hal_timer.c
@@ -40,6 +40,9 @@ struct stm32_hal_tmr {
TIM_TypeDef *sht_regs; /* Pointer to timer registers */
uint32_t sht_oflow; /* 16 bits of overflow to make timer 32bits */
TAILQ_HEAD(hal_timer_qhead, hal_timer) sht_timers;
+#if MYNEWT_VAL(STM32_TIMER_AUTO_OFF_COUNT)
+ uint8_t sht_empty_run;
+#endif
};
#if MYNEWT_VAL(TIMER_0)
@@ -94,6 +97,9 @@ stm32_tmr_cbs(struct stm32_hal_tmr *tmr)
}
ht = TAILQ_FIRST(&tmr->sht_timers);
if (ht) {
+#if MYNEWT_VAL(STM32_TIMER_AUTO_OFF_COUNT)
+ tmr->sht_empty_run = 0;
+#endif
tmr->sht_regs->CCR1 = ht->expiry & 0xFFFFU;
} else {
tmr->sht_regs->DIER &= ~TIM_DIER_CC1IE;
@@ -120,6 +126,9 @@ stm32_tmr_irq(struct stm32_hal_tmr *tmr)
*/
tmr->sht_oflow += STM32_OFLOW_VALUE;
clr |= TIM_SR_UIF;
+#if MYNEWT_VAL(STM32_TIMER_AUTO_OFF_COUNT)
+ tmr->sht_empty_run++;
+#endif
}
if (sr & TIM_SR_CC1IF) {
/*
@@ -130,6 +139,13 @@ stm32_tmr_irq(struct stm32_hal_tmr *tmr)
}
tmr->sht_regs->SR = ~clr;
+
+#if MYNEWT_VAL(STM32_TIMER_AUTO_OFF_COUNT)
+ if (tmr->sht_empty_run >= MYNEWT_VAL(STM32_TIMER_AUTO_OFF_COUNT)) {
+ /* Timer oveflowed few times without any usage, disable it till it
used again */
+ tmr->sht_regs->CR1 &= ~TIM_CR1_CEN;
+ }
+#endif
}
#endif
@@ -579,6 +595,10 @@ hal_timer_cnt(struct stm32_hal_tmr *tmr)
uint32_t cnt;
int sr;
+#if MYNEWT_VAL(STM32_TIMER_AUTO_OFF_COUNT)
+ tmr->sht_empty_run = 0;
+#endif
+
__HAL_DISABLE_INTERRUPTS(sr);
if (tmr->sht_regs->SR & TIM_SR_UIF) {
/*
@@ -590,6 +610,11 @@ hal_timer_cnt(struct stm32_hal_tmr *tmr)
cnt = tmr->sht_oflow + tmr->sht_regs->CNT;
__HAL_ENABLE_INTERRUPTS(sr);
+#if MYNEWT_VAL(STM32_TIMER_AUTO_OFF_COUNT)
+ /* Timer could be turned off, so turn it on */
+ tmr->sht_regs->CR1 |= TIM_CR1_CEN;
+#endif
+
return cnt;
}
diff --git a/hw/mcu/stm/stm32_common/syscfg.yml
b/hw/mcu/stm/stm32_common/syscfg.yml
index 1603bced6..a6bdc785e 100644
--- a/hw/mcu/stm/stm32_common/syscfg.yml
+++ b/hw/mcu/stm/stm32_common/syscfg.yml
@@ -472,5 +472,17 @@ syscfg.defs:
This may be needed for several MCU's including STM32F40x.
value:
+ STM32_TIMER_AUTO_OFF_COUNT:
+ description: >
+ Turn off hal timer if it is not used for a specific number of
overflows.
+ HAL timers are used for high frequency time measurement or delays.
+ Due to high frequency nature of the timer, counter overflows
interrupts
+ would interrupt sleep event if timer is not in use.
+ This value when set to value graters then 0 will all to turn off
timer
+ after number of overflow events without user code asking for timer
value
+ or scheduling event.
+ range: 0..255
+ value: 0
+
syscfg.vals:
OS_TICKS_PER_SEC: 1000