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 <jerzy.kasenb...@codecoup.pl> 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 <je...@apache.org> --- 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