diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_DISCO_F334C8/device.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_DISCO_F334C8/device.h index 0ec2fdffa6f..bfb26e965ce 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_DISCO_F334C8/device.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_DISCO_F334C8/device.h @@ -54,6 +54,8 @@ #define DEVICE_SLEEP 1 +#define DEVICE_LOWPOWERTIMER 1 + //======================================= #define DEVICE_SEMIHOST 0 diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F302R8/device.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F302R8/device.h index 8b1f3d7ca23..bf81cc34f86 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F302R8/device.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F302R8/device.h @@ -54,6 +54,8 @@ #define DEVICE_SLEEP 1 +#define DEVICE_LOWPOWERTIMER 1 + //======================================= #define DEVICE_SEMIHOST 0 diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F303K8/device.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F303K8/device.h index 8b1f3d7ca23..bfb26e965ce 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F303K8/device.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F303K8/device.h @@ -48,12 +48,14 @@ #define DEVICE_SPISLAVE 1 #define DEVICE_RTC 1 -#define DEVICE_RTC_LSI 0 +#define DEVICE_RTC_LSI 1 #define DEVICE_PWMOUT 1 #define DEVICE_SLEEP 1 +#define DEVICE_LOWPOWERTIMER 1 + //======================================= #define DEVICE_SEMIHOST 0 diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F303RE/device.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F303RE/device.h index 8b1f3d7ca23..bf81cc34f86 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F303RE/device.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F303RE/device.h @@ -54,6 +54,8 @@ #define DEVICE_SLEEP 1 +#define DEVICE_LOWPOWERTIMER 1 + //======================================= #define DEVICE_SEMIHOST 0 diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F334R8/device.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F334R8/device.h index 8b1f3d7ca23..bf81cc34f86 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F334R8/device.h +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/TARGET_NUCLEO_F334R8/device.h @@ -54,6 +54,8 @@ #define DEVICE_SLEEP 1 +#define DEVICE_LOWPOWERTIMER 1 + //======================================= #define DEVICE_SEMIHOST 0 diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/lp_ticker.c b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/lp_ticker.c new file mode 100644 index 00000000000..9ee2e9dac23 --- /dev/null +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/lp_ticker.c @@ -0,0 +1,49 @@ +#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 uint32_t m_timestamp = 0; +static uint32_t m_offset = 0; + +void lp_ticker_init() { + /* + * At this stage we don't have the users requested time. + * This is only to cover the API implementation. + */ +} + +uint32_t lp_ticker_read() { + /* + * Becuase our RTC has a periodic wake-up timer we just want to simply + * return the desired timestamp value to configure RTC exactly with the value + * provided by the user and to fulfill the mBed ticker architecture. + */ + return m_timestamp; +} + +void lp_ticker_set_interrupt(timestamp_t timestamp) { + m_offset = timestamp; + + if (lp_ticker_inited) return; + lp_ticker_inited = 1; + + rtc_periodic_ticker_init(timestamp); + rtc_set_irq_handler((uint32_t) lp_ticker_irq_handler); +} + +void lp_ticker_disable_interrupt() { + lp_ticker_inited = 0; + rtc_periodic_ticker_disable_irq(); +} + +void lp_ticker_clear_interrupt() { + m_timestamp = m_offset; +} + +#endif diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api.c b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api.c index 838eb4083c2..68af3e4738f 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api.c @@ -28,6 +28,9 @@ ******************************************************************************* */ #include "rtc_api.h" +#include "rtc_api_hal.h" +#include "stm32f3xx.h" +#include "stm32f3xx_hal_rtc_ex.h" #if DEVICE_RTC @@ -38,9 +41,42 @@ static int rtc_inited = 0; #endif static RTC_HandleTypeDef RtcHandle; +static uint32_t m_synch_prediv; -void rtc_init(void) +#if DEVICE_LOWPOWERTIMER +static void (*irq_handler)(void); + +static void rtc_calc_periodic_vals(float req_time, uint32_t *periodic_cnt) +{ + uint16_t synch_div; + float requested_time = (float)(req_time / 1000000); + float ck; + + /* + * 38000 is LSI typical value. To be measured precisely using a timer input + * capture for example. + */ + float freq = (DEVICE_RTC_LSI ? 38000 : LSE_VALUE); + + for (synch_div = 0; synch_div < (int)freq; synch_div++) + { + ck = freq / ((synch_div + 1.0) * 128.0); + *periodic_cnt = ck * requested_time; + + if (*periodic_cnt < 0xFFFF) { + break; + } + } + m_synch_prediv = synch_div; +} + +void RTC_WKUP_IRQHandler() { + HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle); +} +#endif + +void rtc_init(void) { RCC_OscInitTypeDef RCC_OscInitStruct; uint32_t rtc_freq = 0; @@ -94,7 +130,12 @@ void rtc_init(void) RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; RtcHandle.Init.AsynchPrediv = 127; +#if !DEVICE_LOWPOWERTIMER RtcHandle.Init.SynchPrediv = (rtc_freq / 128) - 1; +#else + 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; @@ -216,4 +257,61 @@ void rtc_write(time_t t) HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN); } +#if DEVICE_LOWPOWERTIMER +void rtc_set_irq_handler(uint32_t handler) +{ + irq_handler = (void (*)(void)) handler; +} + +void rtc_periodic_ticker_init(uint32_t timestamp) +{ + uint32_t periodic_counter; + uint32_t rtcclk; + HAL_StatusTypeDef ret; + + /* + * For more informations how WakeUp unit values were calculated please follow + * this document: www.st.com/resource/en/application_note/dm00025071.pdf + */ + if (timestamp <= 4000000) { + periodic_counter = timestamp / 61.035; + rtcclk = RTC_WAKEUPCLOCK_RTCCLK_DIV2; + m_synch_prediv = 0; + } else { + rtc_calc_periodic_vals((float)(timestamp), &periodic_counter); + rtcclk = RTC_WAKEUPCLOCK_CK_SPRE_16BITS; + } + + rtc_init(); + + /* + * For some reason we need to clear the wakeup time flag to able to start + * the RTC periodic unit. + */ + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF); + ret = HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, periodic_counter - 1, rtcclk); + + if (ret != HAL_OK) { + error("SetWakeUpTimer_IT failed!\n"); + } + + NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t) &RTC_WKUP_IRQHandler); + HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn); +} + +void rtc_periodic_ticker_disable_irq() +{ + HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle); +} + +void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) +{ + if (irq_handler) + { + // Fire the user callback + irq_handler(); + } +} +#endif // DEVICE_LOWPOWERTIMER + #endif diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api_hal.h b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api_hal.h new file mode 100644 index 00000000000..e1299ec148d --- /dev/null +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api_hal.h @@ -0,0 +1,53 @@ +/* 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 + */ +void rtc_set_irq_handler(uint32_t handler); + +void rtc_periodic_ticker_init(uint32_t timestamp); +void rtc_periodic_ticker_disable_irq(); + +#ifdef __cplusplus +} +#endif + +#endif