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

Reply via email to