From c094dcd960f812986079505495e99f9cc8d58e2a Mon Sep 17 00:00:00 2001 From: Bartosz Szczepanski Date: Fri, 27 May 2016 12:33:03 +0200 Subject: [PATCH 1/2] [STM32F0xx] LowPowerTicker implementation Change-Id: I3eb37aa7e35df901b7d3cd00069638425fb3fdc6 --- .../hal/TARGET_STM/TARGET_STM32F0/lp_ticker.c | 94 ++++++++++++++ .../hal/TARGET_STM/TARGET_STM32F0/rtc_api.c | 115 ++++++++++++++++++ .../TARGET_STM/TARGET_STM32F0/rtc_api_hal.h | 61 ++++++++++ 3 files changed, 270 insertions(+) create mode 100644 hal/targets/hal/TARGET_STM/TARGET_STM32F0/lp_ticker.c create mode 100644 hal/targets/hal/TARGET_STM/TARGET_STM32F0/rtc_api_hal.h diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F0/lp_ticker.c b/hal/targets/hal/TARGET_STM/TARGET_STM32F0/lp_ticker.c new file mode 100644 index 00000000000..7c3be3588bd --- /dev/null +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F0/lp_ticker.c @@ -0,0 +1,94 @@ +/* mbed Microcontroller Library + ******************************************************************************* + * Copyright (c) 2016, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************* + */ +#include "device.h" + +#if DEVICE_LOWPOWERTIMER + +#include "ticker_api.h" +#include "lp_ticker_api.h" +#include "rtc_api.h" +#include "rtc_api_hal.h" + +static uint8_t lp_ticker_inited = 0; +static uint8_t lp_ticker_reconf_presc = 0; + +void lp_ticker_init() { + if (lp_ticker_inited) return; + lp_ticker_inited = 1; + + rtc_init(); + rtc_set_irq_handler((uint32_t) lp_ticker_irq_handler); +} + +uint32_t lp_ticker_read() { + uint32_t sub_secs, milis; + time_t time; + + lp_ticker_init(); + + time = rtc_read(); + sub_secs = rtc_read_subseconds(); + milis = 1000 - (sub_secs * 1000 / rtc_ticker_get_synch_presc()); + + return (time * 1000000) + (milis * 1000); +} + +void lp_ticker_set_interrupt(timestamp_t timestamp) { + uint32_t sub_secs, delta, milis; + time_t secs; + struct tm *timeinfo; + + // Reconfigure RTC prescalers whenever the timestamp is below 30ms + if (!lp_ticker_reconf_presc && timestamp < 30000) { + rtc_reconfigure_prescalers(); + lp_ticker_reconf_presc = 1; + } + + milis = (timestamp % 1000000) / 1000; + + secs = rtc_read(); + delta = ((timestamp / 1000000) - secs); + + secs += delta; + sub_secs = (rtc_ticker_get_synch_presc() * (1000 - milis)) / 1000; + timeinfo = localtime(&secs); + + rtc_set_alarm(timeinfo, sub_secs); +} + +void lp_ticker_disable_interrupt() { + lp_ticker_reconf_presc = 0; + rtc_ticker_disable_irq(); +} + +void lp_ticker_clear_interrupt() { +} + +#endif diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F0/rtc_api.c b/hal/targets/hal/TARGET_STM/TARGET_STM32F0/rtc_api.c index 0cdf7cbf265..67db9a9990b 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F0/rtc_api.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F0/rtc_api.c @@ -28,6 +28,9 @@ ******************************************************************************* */ #include "rtc_api.h" +#include "rtc_api_hal.h" +#include "stm32f0xx.h" +#include "stm32f0xx_hal_rtc_ex.h" #if DEVICE_RTC @@ -39,6 +42,57 @@ static int rtc_inited = 0; static RTC_HandleTypeDef RtcHandle; +#if DEVICE_LOWPOWERTIMER +static uint32_t m_synch_prediv = RTC_SYNCH_PREDIV; +static uint32_t m_asynch_prediv = RTC_ASYNCH_PREDIV; + +static void (*irq_handler)(void); + +static void rtc_configure_time_and_date() +{ + RTC_TimeTypeDef mTime; + RTC_DateTypeDef mDate; + + mDate.WeekDay = 1; + mDate.Month = 1; + mDate.Date = 1; + mDate.Year = 1970; + if (HAL_RTC_SetDate(&RtcHandle, &mDate, RTC_FORMAT_BIN) != HAL_OK) { + error("Date set failed\n"); + } + + mTime.Hours = 0; + mTime.Minutes = 0; + mTime.Seconds = 0; + mTime.TimeFormat = RTC_HOURFORMAT12_AM; + mTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; + mTime.StoreOperation = RTC_STOREOPERATION_RESET; + if (HAL_RTC_SetTime(&RtcHandle, &mTime, RTC_FORMAT_BIN) != HAL_OK) { + error("Time set failed\n"); + } +} + +void RTC_IRQHandler() +{ + HAL_RTC_AlarmIRQHandler(&RtcHandle); +} + +void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) +{ + if (irq_handler) + { + // Fire the user callback + irq_handler(); + } +} + +void rtc_set_irq_handler(uint32_t handler) +{ + irq_handler = (void (*)(void)) handler; +} + +#endif + void rtc_init(void) { RCC_OscInitTypeDef RCC_OscInitStruct; uint32_t rtc_freq = 0; @@ -92,8 +146,14 @@ void rtc_init(void) { __HAL_RCC_RTC_ENABLE(); RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; +#if !DEVICE_LOWPOWERTIMER RtcHandle.Init.AsynchPrediv = 127; RtcHandle.Init.SynchPrediv = (rtc_freq / 128) - 1; +#else + RtcHandle.Init.AsynchPrediv = m_asynch_prediv; + RtcHandle.Init.SynchPrediv = m_synch_prediv; +#endif + RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; @@ -101,6 +161,12 @@ void rtc_init(void) { if (HAL_RTC_Init(&RtcHandle) != HAL_OK) { error("RTC error: RTC initialization failed."); } + +#if DEVICE_LOWPOWERTIMER + rtc_configure_time_and_date(); + NVIC_SetVector(RTC_IRQn, (uint32_t)&RTC_IRQHandler); + HAL_NVIC_EnableIRQ(RTC_IRQn); +#endif } void rtc_free(void) { @@ -177,7 +243,12 @@ time_t rtc_read(void) { timeinfo.tm_wday = dateStruct.WeekDay; timeinfo.tm_mon = dateStruct.Month - 1; timeinfo.tm_mday = dateStruct.Date; +#if DEVICE_LOWPOWERTIMER + //We need to add 52 to get the 1970 year + timeinfo.tm_year = dateStruct.Year + 52; +#else timeinfo.tm_year = dateStruct.Year + 100; +#endif timeinfo.tm_hour = timeStruct.Hours; timeinfo.tm_min = timeStruct.Minutes; timeinfo.tm_sec = timeStruct.Seconds; @@ -215,4 +286,48 @@ void rtc_write(time_t t) { HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN); } +#if DEVICE_LOWPOWERTIMER +void rtc_set_alarm(struct tm *ti, uint32_t subsecs) +{ + RTC_AlarmTypeDef mAlarm; + + mAlarm.AlarmTime.Hours = ti->tm_hour; + mAlarm.AlarmTime.Minutes = ti->tm_min; + mAlarm.AlarmTime.Seconds = ti->tm_sec; + mAlarm.AlarmTime.SubSeconds = subsecs; + mAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM; + mAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY; + mAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE; + mAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE; + mAlarm.AlarmDateWeekDay = 1; + mAlarm.Alarm = RTC_ALARM_A; + + if (HAL_RTC_SetAlarm_IT(&RtcHandle, &mAlarm, RTC_FORMAT_BIN) != HAL_OK) { + error("Set Alarm failed\n"); + } +} + +void rtc_reconfigure_prescalers() +{ + m_synch_prediv = 0x3FF; + m_asynch_prediv = 0x1F; + rtc_init(); +} + +uint32_t rtc_ticker_get_synch_presc() +{ + return m_synch_prediv; +} + +uint32_t rtc_read_subseconds() +{ + return RTC->SSR; +} + +void rtc_ticker_disable_irq() +{ + HAL_RTC_DeactivateAlarm(&RtcHandle, RTC_ALARM_A); +} +#endif // DEVICE_LOWPOWERTIMER + #endif diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F0/rtc_api_hal.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F0/rtc_api_hal.h new file mode 100644 index 00000000000..790e6dc9378 --- /dev/null +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F0/rtc_api_hal.h @@ -0,0 +1,61 @@ +/* mbed Microcontroller Library +******************************************************************************* +* Copyright (c) 2016, STMicroelectronics +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* 3. Neither the name of STMicroelectronics nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +******************************************************************************* +*/ + +#ifndef MBED_RTC_API_HAL_H +#define MBED_RTC_API_HAL_H + +#include +#include "rtc_api.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Extend rtc_api.h + */ + +// Prescaler values for LSE clock +#define RTC_ASYNCH_PREDIV 0x7F +#define RTC_SYNCH_PREDIV 0x00FF + +void rtc_set_irq_handler(uint32_t handler); + +void rtc_ticker_disable_irq(); +uint32_t rtc_ticker_get_synch_presc(); + +void rtc_set_alarm(struct tm *ti, uint32_t subsecs); +uint32_t rtc_read_subseconds(); +void rtc_reconfigure_prescalers(); + +#ifdef __cplusplus +} +#endif + +#endif From 4b5a3175f9097e42c4d19e7bb2966488c794cbaf Mon Sep 17 00:00:00 2001 From: Bartosz Szczepanski Date: Tue, 7 Jun 2016 09:58:30 +0200 Subject: [PATCH 2/2] [STM32F0xx] Enable LowPowerTimer Change-Id: Id23b9d3a0f9a9a3c8a8501a4ba8de6256bc591dd --- hal/targets.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hal/targets.json b/hal/targets.json index ce5b4af00a3..21c7382adae 100644 --- a/hal/targets.json +++ b/hal/targets.json @@ -569,7 +569,7 @@ "inherits": ["Target"], "progen": {"target": "nucleo-f030r8"}, "detect_code": ["0725"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "default_build": "small" }, "NUCLEO_F031K6": { @@ -605,7 +605,7 @@ "inherits": ["Target"], "progen": {"target": "nucleo-f070rb"}, "detect_code": ["0755"], - "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "default_build": "small" }, "NUCLEO_F072RB": { @@ -617,7 +617,7 @@ "inherits": ["Target"], "progen": {"target": "nucleo-f072rb"}, "detect_code": ["0730"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "default_build": "small" }, "NUCLEO_F091RC": { @@ -629,7 +629,7 @@ "inherits": ["Target"], "progen": {"target": "nucleo-f091rc"}, "detect_code": ["0750"], - "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "default_build": "small" }, "NUCLEO_F103RB": {