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 94121fc  Add tickless sleep for STM32F1 CPU
94121fc is described below

commit 94121fc8b1e1c9c83eadc4b47d67bb225f0dec25
Author: J. Ipanienko <[email protected]>
AuthorDate: Sat Jun 20 16:58:41 2020 -0700

    Add tickless sleep for STM32F1 CPU
    
    Tickless sleep can be used when LSE oscillator is used
    and OS_TICKS_PER_SEC is set to power of 2.
    RTC that was not used before will be used as tick timer.
---
 hw/mcu/stm/stm32_common/src/hal_os_tick.c     |   6 +-
 hw/mcu/stm/stm32_common/syscfg.yml            |   5 +
 hw/mcu/stm/stm32f1xx/include/mcu/cortex_m3.h  |   3 +-
 hw/mcu/stm/stm32f1xx/src/rtc_tick_stm32f1xx.c | 136 ++++++++++++++++++++++++++
 4 files changed, 148 insertions(+), 2 deletions(-)

diff --git a/hw/mcu/stm/stm32_common/src/hal_os_tick.c 
b/hw/mcu/stm/stm32_common/src/hal_os_tick.c
index 05ceff4..375978d 100644
--- a/hw/mcu/stm/stm32_common/src/hal_os_tick.c
+++ b/hw/mcu/stm/stm32_common/src/hal_os_tick.c
@@ -22,7 +22,7 @@
 #include <hal/hal_os_tick.h>
 
 /*
- * XXX implement tickless mode.
+ * XXX implement tickless mode for MCU other then STM32F1.
  */
 
 /*
@@ -44,6 +44,8 @@ __WFI(void)
 }
 #endif
 
+#if MYNEWT_VAL(STM32_CLOCK_LSE) == 0 || (((32768 / OS_TICKS_PER_SEC) * 
OS_TICKS_PER_SEC) != 32768) || !defined(STM32F1)
+
 void
 os_tick_idle(os_time_t ticks)
 {
@@ -76,3 +78,5 @@ os_tick_init(uint32_t os_ticks_per_sec, int prio)
     DBGMCU->CR |= (DBGMCU_CR_DBG_STOP | DBGMCU_CR_DBG_STANDBY);
 #endif
 }
+
+#endif
diff --git a/hw/mcu/stm/stm32_common/syscfg.yml 
b/hw/mcu/stm/stm32_common/syscfg.yml
index 27d8f8d..f7fd2cb 100644
--- a/hw/mcu/stm/stm32_common/syscfg.yml
+++ b/hw/mcu/stm/stm32_common/syscfg.yml
@@ -374,3 +374,8 @@ syscfg.defs:
     ADC_2:
         description: "ADC_2"
         value:  0
+
+    OS_TICKS_PER_SEC:
+        description: >
+            Desired ticks frequency in Hz.
+        value: 1000
diff --git a/hw/mcu/stm/stm32f1xx/include/mcu/cortex_m3.h 
b/hw/mcu/stm/stm32f1xx/include/mcu/cortex_m3.h
index fa61e24..6f4cede 100644
--- a/hw/mcu/stm/stm32f1xx/include/mcu/cortex_m3.h
+++ b/hw/mcu/stm/stm32f1xx/include/mcu/cortex_m3.h
@@ -21,12 +21,13 @@
 #define __MCU_CORTEX_M3_H__
 
 #include "stm32f1xx.h"
+#include <syscfg/syscfg.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define OS_TICKS_PER_SEC    (1000)
+#define OS_TICKS_PER_SEC    MYNEWT_VAL(OS_TICKS_PER_SEC)
 
 static inline void
 hal_debug_break(void)
diff --git a/hw/mcu/stm/stm32f1xx/src/rtc_tick_stm32f1xx.c 
b/hw/mcu/stm/stm32f1xx/src/rtc_tick_stm32f1xx.c
new file mode 100644
index 0000000..4d678d5
--- /dev/null
+++ b/hw/mcu/stm/stm32f1xx/src/rtc_tick_stm32f1xx.c
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include "os/mynewt.h"
+#include <hal/hal_os_tick.h>
+#include <stm32_common/stm32_hal.h>
+
+#include <Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_ll_rtc.h>
+
+/* RTC tick only if LSE is enabled and OS_TICKS_PER_SEC can work with 32768 
oscillator */
+#if MYNEWT_VAL(STM32_CLOCK_LSE) && (((32768 / OS_TICKS_PER_SEC) * 
OS_TICKS_PER_SEC) == 32768)
+
+struct hal_os_tick {
+    uint32_t rtc_cnt;
+};
+
+struct hal_os_tick g_hal_os_tick;
+
+static void
+stm32_os_tick_update_rtc(void)
+{
+    int ticks;
+    uint32_t rtc_cnt;
+
+    /* Clear all flags. */
+    RTC->CRL = 0;
+    /* Read current value of counter. */
+    rtc_cnt = (RTC->CNTH << 16u) | RTC->CNTL;
+    if (RTC->CRL & RTC_CRL_SECF_Msk) {
+        /* Read again in case it was just incremented. */
+        rtc_cnt = (RTC->CNTH << 16u) | RTC->CNTL;
+    }
+    ticks = rtc_cnt - g_hal_os_tick.rtc_cnt;
+    g_hal_os_tick.rtc_cnt = rtc_cnt;
+
+    os_time_advance(ticks);
+}
+
+static void
+stm32_os_tick_rtc_handler(void)
+{
+    os_trace_isr_enter();
+    stm32_os_tick_update_rtc();
+    os_trace_isr_exit();
+}
+
+void
+os_tick_idle(os_time_t ticks)
+{
+    uint32_t rtc_cnt;
+    OS_ASSERT_CRITICAL();
+
+    if (ticks > 1) {
+        while (!LL_RTC_IsActiveFlag_RTOF(RTC));
+        LL_RTC_ClearFlag_SEC(RTC);
+        rtc_cnt = (RTC->CNTH << 16u) + RTC->CNTL;
+        if (LL_RTC_IsActiveFlag_SEC(RTC)) {
+            rtc_cnt = (RTC->CNTH << 16u) + RTC->CNTL;
+            ticks--;
+        }
+        rtc_cnt += ticks - 1;
+        /* All flags cleared, disable write protection */
+        RTC->CRL = RTC_CRL_CNF_Msk;
+
+        LL_RTC_ALARM_Set(RTC, rtc_cnt);
+        /* Enable alarm, disable tick interrupt */
+        RTC->CRH = RTC_CRH_ALRIE_Msk;
+        LL_RTC_EnableWriteProtection(RTC);
+    } else {
+        /* Disable alarm, enable tick interrupt. */
+        RTC->CRH = RTC_CRH_SECIE_Msk;
+    }
+
+    __DSB();
+    __WFI();
+
+    if (ticks > 0) {
+        /*
+         * Update OS time before anything else when coming out of
+         * the tickless regime.
+         */
+        stm32_os_tick_update_rtc();
+    }
+}
+
+void
+os_tick_init(uint32_t os_ticks_per_sec, int prio)
+{
+    uint32_t sr;
+    RCC_PeriphCLKInitTypeDef clock_init = {
+        .PeriphClockSelection = RCC_PERIPHCLK_RTC,
+        .RTCClockSelection = RCC_RTCCLKSOURCE_LSE,
+    };
+
+    HAL_RCCEx_PeriphCLKConfig(&clock_init);
+    __HAL_RCC_RTC_ENABLE();
+
+    OS_ENTER_CRITICAL(sr);
+    /* RTCCLK = 32768 Hz. */
+    /* Disable interrupts. */
+    RTC->CRH = 0;
+    /* Enter configuration mode, clear all flags. */
+    RTC->CRL = RTC_CRL_CNF_Msk;
+    /* TR_CLK = OS_TICKS_PER_SEC Hz. */
+    LL_RTC_SetAsynchPrescaler(RTC, ((32768 / OS_TICKS_PER_SEC) - 1));
+    LL_RTC_TIME_Set(RTC, 0);
+    LL_RTC_EnableIT_SEC(RTC);
+    /* Exit configuration mode. */
+    RTC->CRL = 0;
+
+    /* Set the system tick priority. */
+    NVIC_SetPriority(RTC_IRQn, prio);
+    NVIC_SetVector(RTC_IRQn, (uint32_t)stm32_os_tick_rtc_handler);
+    NVIC_EnableIRQ(RTC_IRQn);
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+#endif

Reply via email to