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 0000000000..564905fa9c --- /dev/null +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/lp_ticker.c @@ -0,0 +1,83 @@ +/* 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; + +void lp_ticker_init(void) +{ + 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(void) +{ + uint32_t usecs; + time_t time; + + lp_ticker_init(); + + do { + time = rtc_read(); + usecs = rtc_read_subseconds(); + } while (time != rtc_read()); + + return (time * 1000000) + usecs; +} + +void lp_ticker_set_interrupt(timestamp_t timestamp) +{ + uint32_t delta; + + delta = timestamp - lp_ticker_read(); + rtc_set_wake_up_timer(delta); +} + +void lp_ticker_disable_interrupt(void) +{ + rtc_deactivate_wake_up_timer(); +} + +void lp_ticker_clear_interrupt(void) +{ + +} + +#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 0fef5db8e9..08f51f7a57 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api.c @@ -1,6 +1,6 @@ /* mbed Microcontroller Library ******************************************************************************* - * Copyright (c) 2014, STMicroelectronics + * Copyright (c) 2016, STMicroelectronics * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,23 +28,43 @@ ******************************************************************************* */ #include "rtc_api.h" +#include "rtc_api_hal.h" #if DEVICE_RTC #include "mbed_error.h" #if DEVICE_RTC_LSI -static int rtc_inited = 0; + static int rtc_inited = 0; #endif static RTC_HandleTypeDef RtcHandle; +#if DEVICE_RTC_LSI + #define RTC_CLOCK LSI_VALUE +#else + #define RTC_CLOCK LSE_VALUE +#endif + +#if DEVICE_LOWPOWERTIMER + #define RTC_ASYNCH_PREDIV ((RTC_CLOCK - 1) / 0x8000) + #define RTC_SYNCH_PREDIV (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1) +#else + #define RTC_ASYNCH_PREDIV (0x007F) + #define RTC_SYNCH_PREDIV (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1) +#endif + +#if DEVICE_LOWPOWERTIMER + static void (*irq_handler)(void); + static void RTC_IRQHandler(); +#endif + void rtc_init(void) { RCC_OscInitTypeDef RCC_OscInitStruct; - uint32_t rtc_freq = 0; #if DEVICE_RTC_LSI + if (rtc_inited) return; rtc_inited = 1; #endif @@ -58,13 +78,11 @@ void rtc_init(void) if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) { // Connect LSE to RTC __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); - rtc_freq = LSE_VALUE; - } - else { - error("RTC error: LSE clock initialization failed."); + } else { + error("RTC error: LSE clock initialization failed."); } #else - // Enable Power clock + // Enable Power clock __PWR_CLK_ENABLE(); // Enable access to Backup domain @@ -73,28 +91,25 @@ void rtc_init(void) // Reset Backup domain __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); - - // Enable LSI clock - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! - RCC_OscInitStruct.LSEState = RCC_LSE_OFF; - RCC_OscInitStruct.LSIState = RCC_LSI_ON; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - error("RTC error: LSI clock initialization failed."); - } - // Connect LSI to RTC - __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI); - // Note: The LSI clock can be measured precisely using a timer input capture. - rtc_freq = LSI_VALUE; -#endif + // Enable LSI clock + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! + RCC_OscInitStruct.LSEState = RCC_LSE_OFF; + RCC_OscInitStruct.LSIState = RCC_LSI_ON; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + error("RTC error: LSI clock initialization failed."); + } + // Connect LSI to RTC + __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI); +#endif // Enable RTC __HAL_RCC_RTC_ENABLE(); RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; - RtcHandle.Init.AsynchPrediv = 127; - RtcHandle.Init.SynchPrediv = (rtc_freq / 128) - 1; + RtcHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV; + RtcHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV; RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; @@ -102,6 +117,20 @@ void rtc_init(void) if (HAL_RTC_Init(&RtcHandle) != HAL_OK) { error("RTC error: RTC initialization failed."); } + +#if DEVICE_LOWPOWERTIMER +#if DEVICE_RTC_LSI + rtc_write(0); +#else + if (!rtc_isenabled()) { + rtc_write(0); + } +#endif + NVIC_ClearPendingIRQ(RTC_WKUP_IRQn); + NVIC_DisableIRQ(RTC_WKUP_IRQn); + NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); + NVIC_EnableIRQ(RTC_WKUP_IRQn); +#endif } void rtc_free(void) @@ -218,4 +247,50 @@ void rtc_write(time_t t) HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN); } +#if DEVICE_LOWPOWERTIMER + +static void RTC_IRQHandler() +{ + HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle); +} + +void HAL_RTCEx_WakeUpTimerEventCallback(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; +} + +uint32_t rtc_read_subseconds(void) +{ + return 1000000.f * ((double)(RTC_SYNCH_PREDIV - RTC->SSR) / (RTC_SYNCH_PREDIV + 1)); +} + +void rtc_set_wake_up_timer(uint32_t delta) +{ + uint32_t wake_up_counter = delta / (2000000 / RTC_CLOCK); + + if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, wake_up_counter, + RTC_WAKEUPCLOCK_RTCCLK_DIV2) != HAL_OK) { + error("Set wake up timer failed\n"); + } +} + +void rtc_deactivate_wake_up_timer(void) +{ + HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle); +} + +void rtc_synchronize(void) +{ + HAL_RTC_WaitForSynchro(&RtcHandle); +} +#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 0000000000..14a345438d --- /dev/null +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/rtc_api_hal.h @@ -0,0 +1,79 @@ +/* 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 + */ + +/** Set the given function as handler of wakeup timer event. + * + * @param handler The function to set as handler + */ +void rtc_set_irq_handler(uint32_t handler); + +/** Read the subsecond register. + * + * @return The remaining time as microseconds (0-999999) + */ +uint32_t rtc_read_subseconds(void); + +/** Program a wake up timer event in delta microseconds. + * + * @param delta The time to wait + */ +void rtc_set_wake_up_timer(uint32_t delta); + +/** Disable the wake up timer event. + * + * The wake up timer use auto reload, you have to deactivate it manually. + */ +void rtc_deactivate_wake_up_timer(void); + +/** Synchronise the RTC shadow registers. + * + * Must be called after a deepsleep. + */ +void rtc_synchronize(void); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/sleep.c b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/sleep.c index f56f5e0378..0c028275df 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32F3/sleep.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32F3/sleep.c @@ -28,6 +28,7 @@ ******************************************************************************* */ #include "sleep_api.h" +#include "rtc_api_hal.h" #if DEVICE_SLEEP @@ -51,6 +52,10 @@ void deepsleep(void) // After wake-up from STOP reconfigure the PLL SetSysClock(); + +#if DEVICE_LOWPOWERTIMER + rtc_synchronize(); +#endif } #endif