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