diff --git a/hal/targets.json b/hal/targets.json index b948d3de9df..a94f4ac5980 100644 --- a/hal/targets.json +++ b/hal/targets.json @@ -965,7 +965,7 @@ "inherits": ["Target"], "progen": {"target": "nucleo-l152re"}, "detect_code": ["0710"], - "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], + "device_has": ["ANALOGIN", "ANALOGOUT", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "STDIO_MESSAGES"], "release_versions": ["2", "5"] }, "NUCLEO_L432KC": { diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32L1/lp_ticker.c b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/lp_ticker.c new file mode 100644 index 00000000000..4415f74c9c9 --- /dev/null +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/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 \ No newline at end of file diff --git a/hal/targets/hal/TARGET_STM/TARGET_STM32L1/rtc_api.c b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/rtc_api.c index 79b32432fad..3bcde9b584b 100755 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32L1/rtc_api.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/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,6 +28,7 @@ ******************************************************************************* */ #include "rtc_api.h" +#include "rtc_api_hal.h" #if DEVICE_RTC @@ -37,12 +38,30 @@ static int rtc_inited = 0; #endif -RTC_HandleTypeDef RtcHandle; +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(void); +#endif void rtc_init(void) { RCC_OscInitTypeDef RCC_OscInitStruct; - uint32_t rtc_freq = 0; #if DEVICE_RTC_LSI if (rtc_inited) return; @@ -61,7 +80,6 @@ void rtc_init(void) // Connect LSE to RTC __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE); __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); - rtc_freq = LSE_VALUE; } else { error("Cannot initialize RTC with LSE\n"); } @@ -87,8 +105,6 @@ void rtc_init(void) // Connect LSI to RTC __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSI); __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI); - // This value is LSI typical value. To be measured precisely using a timer input capture for example. - rtc_freq = 40000; #endif // Enable RTC @@ -98,10 +114,10 @@ void rtc_init(void) #ifdef TARGET_MOTE_L152RC /* SubSecond resolution of 16384Hz */ RtcHandle.Init.AsynchPrediv = 1; - RtcHandle.Init.SynchPrediv = (rtc_freq / 2) - 1; + RtcHandle.Init.SynchPrediv = (RTC_CLOCK / 2) - 1; #else - RtcHandle.Init.AsynchPrediv = 127; - RtcHandle.Init.SynchPrediv = (rtc_freq / 128) - 1; + RtcHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV; + RtcHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV; #endif RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; @@ -110,6 +126,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) @@ -229,4 +259,50 @@ void rtc_write(time_t t) HAL_RTC_SetTime(&RtcHandle, &timeStruct, FORMAT_BIN); } +#if DEVICE_LOWPOWERTIMER + +static void RTC_IRQHandler(void) +{ + 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_STM32L1/rtc_api_hal.h b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/rtc_api_hal.h new file mode 100644 index 00000000000..14a345438d3 --- /dev/null +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/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_STM32L1/sleep.c b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/sleep.c index 5e951335067..99b6ef9ed9a 100644 --- a/hal/targets/hal/TARGET_STM/TARGET_STM32L1/sleep.c +++ b/hal/targets/hal/TARGET_STM/TARGET_STM32L1/sleep.c @@ -29,6 +29,7 @@ */ #include "sleep_api.h" #include "hal_tick.h" +#include "rtc_api_hal.h" #if DEVICE_SLEEP @@ -90,6 +91,10 @@ void deepsleep(void) // Restart HAL systick HAL_ResumeTick(); + +#if DEVICE_LOWPOWERTIMER + rtc_synchronize(); +#endif } #endif