mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Thu Nov 08 11:46:34 2018 +0000
Revision:
188:bcfe06ba3d64
Parent:
187:0387e8f68319
Child:
189:f392fc9709a3
mbed-dev library. Release version 164

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 154:37f96f9d4de2 1 /* mbed Microcontroller Library
<> 154:37f96f9d4de2 2 *******************************************************************************
Anna Bridge 186:707f6e361f3e 3 * Copyright (c) 2018, STMicroelectronics
<> 154:37f96f9d4de2 4 * All rights reserved.
<> 154:37f96f9d4de2 5 *
<> 154:37f96f9d4de2 6 * Redistribution and use in source and binary forms, with or without
<> 154:37f96f9d4de2 7 * modification, are permitted provided that the following conditions are met:
<> 154:37f96f9d4de2 8 *
<> 154:37f96f9d4de2 9 * 1. Redistributions of source code must retain the above copyright notice,
<> 154:37f96f9d4de2 10 * this list of conditions and the following disclaimer.
<> 154:37f96f9d4de2 11 * 2. Redistributions in binary form must reproduce the above copyright notice,
<> 154:37f96f9d4de2 12 * this list of conditions and the following disclaimer in the documentation
<> 154:37f96f9d4de2 13 * and/or other materials provided with the distribution.
<> 154:37f96f9d4de2 14 * 3. Neither the name of STMicroelectronics nor the names of its contributors
<> 154:37f96f9d4de2 15 * may be used to endorse or promote products derived from this software
<> 154:37f96f9d4de2 16 * without specific prior written permission.
<> 154:37f96f9d4de2 17 *
<> 154:37f96f9d4de2 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
<> 154:37f96f9d4de2 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
<> 154:37f96f9d4de2 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
<> 154:37f96f9d4de2 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
<> 154:37f96f9d4de2 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
<> 154:37f96f9d4de2 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
<> 154:37f96f9d4de2 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
<> 154:37f96f9d4de2 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
<> 154:37f96f9d4de2 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
<> 154:37f96f9d4de2 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<> 154:37f96f9d4de2 28 *******************************************************************************
<> 154:37f96f9d4de2 29 */
Anna Bridge 180:96ed750bd169 30
<> 154:37f96f9d4de2 31 #if DEVICE_RTC
<> 154:37f96f9d4de2 32
<> 154:37f96f9d4de2 33 #include "rtc_api_hal.h"
AnnaBridge 167:e84263d55307 34 #include "mbed_mktime.h"
Anna Bridge 186:707f6e361f3e 35 #include "mbed_error.h"
AnnaBridge 187:0387e8f68319 36 #include "mbed_critical.h"
AnnaBridge 187:0387e8f68319 37
AnnaBridge 187:0387e8f68319 38 #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
AnnaBridge 188:bcfe06ba3d64 39 volatile uint32_t LPTICKER_counter = 0;
AnnaBridge 188:bcfe06ba3d64 40 volatile uint32_t LPTICKER_RTC_time = 0;
AnnaBridge 187:0387e8f68319 41 #endif
AnnaBridge 187:0387e8f68319 42
AnnaBridge 187:0387e8f68319 43 static int RTC_inited = 0;
<> 154:37f96f9d4de2 44
<> 154:37f96f9d4de2 45 static RTC_HandleTypeDef RtcHandle;
<> 154:37f96f9d4de2 46
<> 154:37f96f9d4de2 47 void rtc_init(void)
<> 154:37f96f9d4de2 48 {
AnnaBridge 176:447f873cad2f 49 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
AnnaBridge 176:447f873cad2f 50 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
<> 154:37f96f9d4de2 51
AnnaBridge 187:0387e8f68319 52 if (RTC_inited) {
AnnaBridge 187:0387e8f68319 53 return;
AnnaBridge 187:0387e8f68319 54 }
AnnaBridge 187:0387e8f68319 55 RTC_inited = 1;
AnnaBridge 187:0387e8f68319 56
<> 154:37f96f9d4de2 57 // Enable access to Backup domain
Anna Bridge 180:96ed750bd169 58 __HAL_RCC_PWR_CLK_ENABLE();
<> 154:37f96f9d4de2 59 HAL_PWR_EnableBkUpAccess();
<> 154:37f96f9d4de2 60
Anna Bridge 180:96ed750bd169 61 #if MBED_CONF_TARGET_LSE_AVAILABLE
AnnaBridge 184:08ed48f1de7f 62 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
AnnaBridge 188:bcfe06ba3d64 63 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
<> 154:37f96f9d4de2 64 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
Anna Bridge 180:96ed750bd169 65 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
<> 154:37f96f9d4de2 66 error("Cannot initialize RTC with LSE\n");
<> 154:37f96f9d4de2 67 }
<> 154:37f96f9d4de2 68
Anna Bridge 180:96ed750bd169 69 __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE);
Anna Bridge 180:96ed750bd169 70
<> 154:37f96f9d4de2 71 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
<> 154:37f96f9d4de2 72 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
<> 154:37f96f9d4de2 73 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
<> 154:37f96f9d4de2 74 error("PeriphClkInitStruct RTC failed with LSE\n");
<> 154:37f96f9d4de2 75 }
Anna Bridge 180:96ed750bd169 76 #else /* MBED_CONF_TARGET_LSE_AVAILABLE */
AnnaBridge 184:08ed48f1de7f 77 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
AnnaBridge 188:bcfe06ba3d64 78 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
<> 154:37f96f9d4de2 79 RCC_OscInitStruct.LSIState = RCC_LSI_ON;
<> 154:37f96f9d4de2 80 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
<> 154:37f96f9d4de2 81 error("Cannot initialize RTC with LSI\n");
<> 154:37f96f9d4de2 82 }
<> 154:37f96f9d4de2 83
<> 154:37f96f9d4de2 84 __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI);
<> 154:37f96f9d4de2 85
<> 154:37f96f9d4de2 86 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
<> 154:37f96f9d4de2 87 PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
<> 154:37f96f9d4de2 88 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
<> 154:37f96f9d4de2 89 error("PeriphClkInitStruct RTC failed with LSI\n");
<> 154:37f96f9d4de2 90 }
Anna Bridge 180:96ed750bd169 91 #endif /* MBED_CONF_TARGET_LSE_AVAILABLE */
<> 154:37f96f9d4de2 92
<> 154:37f96f9d4de2 93 // Enable RTC
<> 154:37f96f9d4de2 94 __HAL_RCC_RTC_ENABLE();
<> 154:37f96f9d4de2 95
Anna Bridge 180:96ed750bd169 96 RtcHandle.Instance = RTC;
Anna Bridge 180:96ed750bd169 97 RtcHandle.State = HAL_RTC_STATE_RESET;
Anna Bridge 180:96ed750bd169 98
<> 154:37f96f9d4de2 99 #if TARGET_STM32F1
<> 154:37f96f9d4de2 100 RtcHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
<> 154:37f96f9d4de2 101 #else /* TARGET_STM32F1 */
<> 154:37f96f9d4de2 102 RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
Anna Bridge 186:707f6e361f3e 103 RtcHandle.Init.AsynchPrediv = PREDIV_A_VALUE;
Anna Bridge 186:707f6e361f3e 104 RtcHandle.Init.SynchPrediv = PREDIV_S_VALUE;
<> 154:37f96f9d4de2 105 RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
<> 154:37f96f9d4de2 106 RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
<> 154:37f96f9d4de2 107 RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
<> 154:37f96f9d4de2 108 #endif /* TARGET_STM32F1 */
<> 154:37f96f9d4de2 109
<> 154:37f96f9d4de2 110 if (HAL_RTC_Init(&RtcHandle) != HAL_OK) {
AnnaBridge 188:bcfe06ba3d64 111 error("RTC initialization failed\n");
<> 154:37f96f9d4de2 112 }
<> 154:37f96f9d4de2 113
AnnaBridge 187:0387e8f68319 114 #if !(TARGET_STM32F1) && !(TARGET_STM32F2)
AnnaBridge 187:0387e8f68319 115 /* STM32F1 : there are no shadow registers */
AnnaBridge 187:0387e8f68319 116 /* STM32F2 : shadow registers can not be bypassed */
AnnaBridge 187:0387e8f68319 117 if (HAL_RTCEx_EnableBypassShadow(&RtcHandle) != HAL_OK) {
AnnaBridge 188:bcfe06ba3d64 118 error("EnableBypassShadow error\n");
<> 154:37f96f9d4de2 119 }
AnnaBridge 187:0387e8f68319 120 #endif /* TARGET_STM32F1 || TARGET_STM32F2 */
<> 154:37f96f9d4de2 121 }
<> 154:37f96f9d4de2 122
<> 154:37f96f9d4de2 123 void rtc_free(void)
<> 154:37f96f9d4de2 124 {
AnnaBridge 187:0387e8f68319 125 /* RTC clock can not be reset */
<> 154:37f96f9d4de2 126 }
<> 154:37f96f9d4de2 127
<> 160:d5399cc887bb 128
<> 160:d5399cc887bb 129 /*
<> 160:d5399cc887bb 130 Information about STM32F0, STM32F2, STM32F3, STM32F4, STM32F7, STM32L0, STM32L1, STM32L4:
<> 160:d5399cc887bb 131 BCD format is used to store the date in the RTC. The year is store on 2 * 4 bits.
<> 160:d5399cc887bb 132 Because the first year is reserved to see if the RTC is init, the supposed range is 01-99.
<> 160:d5399cc887bb 133 1st point is to cover the standard range from 1970 to 2038 (limited by the 32 bits of time_t).
<> 160:d5399cc887bb 134 2nd point is to keep the year 1970 and the leap years synchronized.
<> 160:d5399cc887bb 135
<> 160:d5399cc887bb 136 So by moving it 68 years forward from 1970, it become 1969-2067 which include 1970-2038.
<> 160:d5399cc887bb 137 68 is also a multiple of 4 so it let the leap year synchronized.
<> 160:d5399cc887bb 138
<> 160:d5399cc887bb 139 Information about STM32F1:
AnnaBridge 182:a56a73fd2a6f 140 32bit register is used (no BCD format) for the seconds.
AnnaBridge 182:a56a73fd2a6f 141 For date, there is no specific register, only a software structure.
<> 160:d5399cc887bb 142 It is then not a problem to not use shifts.
<> 160:d5399cc887bb 143 */
<> 154:37f96f9d4de2 144 time_t rtc_read(void)
<> 154:37f96f9d4de2 145 {
AnnaBridge 188:bcfe06ba3d64 146 #if TARGET_STM32F1
<> 154:37f96f9d4de2 147
<> 154:37f96f9d4de2 148 RtcHandle.Instance = RTC;
AnnaBridge 188:bcfe06ba3d64 149 return RTC_ReadTimeCounter(&RtcHandle);
<> 154:37f96f9d4de2 150
AnnaBridge 187:0387e8f68319 151 #else /* TARGET_STM32F1 */
AnnaBridge 187:0387e8f68319 152
AnnaBridge 187:0387e8f68319 153 struct tm timeinfo;
AnnaBridge 187:0387e8f68319 154
AnnaBridge 187:0387e8f68319 155 /* Since the shadow registers are bypassed we have to read the time twice and compare them until both times are the same */
AnnaBridge 187:0387e8f68319 156 uint32_t Read_time = RTC->TR & RTC_TR_RESERVED_MASK;
AnnaBridge 187:0387e8f68319 157 uint32_t Read_date = RTC->DR & RTC_DR_RESERVED_MASK;
AnnaBridge 187:0387e8f68319 158
AnnaBridge 187:0387e8f68319 159 while ((Read_time != (RTC->TR & RTC_TR_RESERVED_MASK)) || (Read_date != (RTC->DR & RTC_DR_RESERVED_MASK))) {
AnnaBridge 187:0387e8f68319 160 Read_time = RTC->TR & RTC_TR_RESERVED_MASK;
AnnaBridge 187:0387e8f68319 161 Read_date = RTC->DR & RTC_DR_RESERVED_MASK;
AnnaBridge 187:0387e8f68319 162 }
AnnaBridge 187:0387e8f68319 163
AnnaBridge 187:0387e8f68319 164 /* Setup a tm structure based on the RTC
AnnaBridge 187:0387e8f68319 165 struct tm :
AnnaBridge 187:0387e8f68319 166 tm_sec seconds after the minute 0-61
AnnaBridge 187:0387e8f68319 167 tm_min minutes after the hour 0-59
AnnaBridge 187:0387e8f68319 168 tm_hour hours since midnight 0-23
AnnaBridge 187:0387e8f68319 169 tm_mday day of the month 1-31
AnnaBridge 187:0387e8f68319 170 tm_mon months since January 0-11
AnnaBridge 187:0387e8f68319 171 tm_year years since 1900
AnnaBridge 187:0387e8f68319 172 tm_yday information is ignored by _rtc_maketime
AnnaBridge 187:0387e8f68319 173 tm_wday information is ignored by _rtc_maketime
AnnaBridge 187:0387e8f68319 174 tm_isdst information is ignored by _rtc_maketime
AnnaBridge 187:0387e8f68319 175 */
AnnaBridge 187:0387e8f68319 176 timeinfo.tm_mday = RTC_Bcd2ToByte((uint8_t)(Read_date & (RTC_DR_DT | RTC_DR_DU)));
AnnaBridge 187:0387e8f68319 177 timeinfo.tm_mon = RTC_Bcd2ToByte((uint8_t)((Read_date & (RTC_DR_MT | RTC_DR_MU)) >> 8)) - 1;
AnnaBridge 187:0387e8f68319 178 timeinfo.tm_year = RTC_Bcd2ToByte((uint8_t)((Read_date & (RTC_DR_YT | RTC_DR_YU)) >> 16)) + 68;
AnnaBridge 187:0387e8f68319 179 timeinfo.tm_hour = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_HT | RTC_TR_HU)) >> 16));
AnnaBridge 187:0387e8f68319 180 timeinfo.tm_min = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_MNT | RTC_TR_MNU)) >> 8));
AnnaBridge 187:0387e8f68319 181 timeinfo.tm_sec = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_ST | RTC_TR_SU)) >> 0));
AnnaBridge 187:0387e8f68319 182
AnnaBridge 187:0387e8f68319 183 // Convert to timestamp
AnnaBridge 187:0387e8f68319 184 time_t t;
AnnaBridge 187:0387e8f68319 185 if (_rtc_maketime(&timeinfo, &t, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) {
AnnaBridge 187:0387e8f68319 186 return 0;
AnnaBridge 187:0387e8f68319 187 }
AnnaBridge 187:0387e8f68319 188
AnnaBridge 187:0387e8f68319 189 return t;
AnnaBridge 188:bcfe06ba3d64 190
AnnaBridge 188:bcfe06ba3d64 191 #endif /* TARGET_STM32F1 */
AnnaBridge 187:0387e8f68319 192 }
AnnaBridge 187:0387e8f68319 193
AnnaBridge 188:bcfe06ba3d64 194
AnnaBridge 187:0387e8f68319 195
<> 154:37f96f9d4de2 196 void rtc_write(time_t t)
<> 154:37f96f9d4de2 197 {
AnnaBridge 188:bcfe06ba3d64 198 #if TARGET_STM32F1
AnnaBridge 188:bcfe06ba3d64 199
AnnaBridge 188:bcfe06ba3d64 200 RtcHandle.Instance = RTC;
AnnaBridge 188:bcfe06ba3d64 201 if (RTC_WriteTimeCounter(&RtcHandle, t) != HAL_OK) {
AnnaBridge 188:bcfe06ba3d64 202 error("RTC_WriteTimeCounter error\n");
AnnaBridge 188:bcfe06ba3d64 203 }
AnnaBridge 188:bcfe06ba3d64 204
AnnaBridge 188:bcfe06ba3d64 205 #else /* TARGET_STM32F1 */
AnnaBridge 188:bcfe06ba3d64 206
AnnaBridge 176:447f873cad2f 207 RTC_DateTypeDef dateStruct = {0};
AnnaBridge 176:447f873cad2f 208 RTC_TimeTypeDef timeStruct = {0};
<> 154:37f96f9d4de2 209
AnnaBridge 187:0387e8f68319 210 core_util_critical_section_enter();
<> 154:37f96f9d4de2 211 RtcHandle.Instance = RTC;
<> 154:37f96f9d4de2 212
<> 154:37f96f9d4de2 213 // Convert the time into a tm
AnnaBridge 167:e84263d55307 214 struct tm timeinfo;
AnnaBridge 184:08ed48f1de7f 215 if (_rtc_localtime(t, &timeinfo, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) {
AnnaBridge 167:e84263d55307 216 return;
AnnaBridge 167:e84263d55307 217 }
<> 154:37f96f9d4de2 218
<> 154:37f96f9d4de2 219 // Fill RTC structures
AnnaBridge 187:0387e8f68319 220 if (timeinfo.tm_wday == 0) { /* Sunday specific case */
AnnaBridge 187:0387e8f68319 221 dateStruct.WeekDay = RTC_WEEKDAY_SUNDAY;
<> 160:d5399cc887bb 222 } else {
AnnaBridge 167:e84263d55307 223 dateStruct.WeekDay = timeinfo.tm_wday;
<> 160:d5399cc887bb 224 }
AnnaBridge 167:e84263d55307 225 dateStruct.Month = timeinfo.tm_mon + 1;
AnnaBridge 167:e84263d55307 226 dateStruct.Date = timeinfo.tm_mday;
AnnaBridge 167:e84263d55307 227 dateStruct.Year = timeinfo.tm_year - 68;
AnnaBridge 167:e84263d55307 228 timeStruct.Hours = timeinfo.tm_hour;
AnnaBridge 167:e84263d55307 229 timeStruct.Minutes = timeinfo.tm_min;
AnnaBridge 167:e84263d55307 230 timeStruct.Seconds = timeinfo.tm_sec;
<> 154:37f96f9d4de2 231 timeStruct.TimeFormat = RTC_HOURFORMAT_24;
<> 154:37f96f9d4de2 232 timeStruct.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
<> 154:37f96f9d4de2 233 timeStruct.StoreOperation = RTC_STOREOPERATION_RESET;
<> 154:37f96f9d4de2 234
AnnaBridge 187:0387e8f68319 235 #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
AnnaBridge 188:bcfe06ba3d64 236 /* Before setting the new time, we need to update the LPTICKER_counter value */
AnnaBridge 188:bcfe06ba3d64 237 /* rtc_read_lp function is then called */
AnnaBridge 187:0387e8f68319 238 rtc_read_lp();
AnnaBridge 187:0387e8f68319 239
AnnaBridge 188:bcfe06ba3d64 240 /* In rtc_read_lp, LPTICKER_RTC_time value has been updated with the current time */
AnnaBridge 188:bcfe06ba3d64 241 /* We need now to overwrite the value with the new RTC time */
AnnaBridge 188:bcfe06ba3d64 242 /* Note that when a new RTC time is set by HW, the RTC SubSeconds counter is reset to PREDIV_S_VALUE */
AnnaBridge 188:bcfe06ba3d64 243 LPTICKER_RTC_time = (timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60) * PREDIV_S_VALUE;
AnnaBridge 187:0387e8f68319 244 #endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
AnnaBridge 187:0387e8f68319 245
<> 154:37f96f9d4de2 246 // Change the RTC current date/time
Anna Bridge 180:96ed750bd169 247 if (HAL_RTC_SetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN) != HAL_OK) {
Anna Bridge 180:96ed750bd169 248 error("HAL_RTC_SetDate error\n");
Anna Bridge 180:96ed750bd169 249 }
Anna Bridge 180:96ed750bd169 250 if (HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN) != HAL_OK) {
Anna Bridge 180:96ed750bd169 251 error("HAL_RTC_SetTime error\n");
Anna Bridge 180:96ed750bd169 252 }
AnnaBridge 187:0387e8f68319 253
AnnaBridge 187:0387e8f68319 254 core_util_critical_section_exit();
AnnaBridge 188:bcfe06ba3d64 255 #endif /* TARGET_STM32F1 */
<> 154:37f96f9d4de2 256 }
<> 154:37f96f9d4de2 257
<> 154:37f96f9d4de2 258 int rtc_isenabled(void)
<> 154:37f96f9d4de2 259 {
<> 160:d5399cc887bb 260 #if !(TARGET_STM32F1)
AnnaBridge 187:0387e8f68319 261 return ((RTC->ISR & RTC_ISR_INITS) == RTC_ISR_INITS);
<> 160:d5399cc887bb 262 #else /* TARGET_STM32F1 */
<> 160:d5399cc887bb 263 return ((RTC->CRL & RTC_CRL_RSF) == RTC_CRL_RSF);
<> 160:d5399cc887bb 264 #endif /* TARGET_STM32F1 */
<> 154:37f96f9d4de2 265 }
<> 154:37f96f9d4de2 266
Anna Bridge 180:96ed750bd169 267
Anna Bridge 186:707f6e361f3e 268 #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
Anna Bridge 186:707f6e361f3e 269
Anna Bridge 186:707f6e361f3e 270 static void RTC_IRQHandler(void);
Anna Bridge 186:707f6e361f3e 271 static void (*irq_handler)(void);
Anna Bridge 186:707f6e361f3e 272
Anna Bridge 186:707f6e361f3e 273 volatile uint8_t lp_Fired = 0;
<> 154:37f96f9d4de2 274
<> 154:37f96f9d4de2 275 static void RTC_IRQHandler(void)
<> 154:37f96f9d4de2 276 {
AnnaBridge 176:447f873cad2f 277 /* Update HAL state */
Anna Bridge 180:96ed750bd169 278 RtcHandle.Instance = RTC;
AnnaBridge 187:0387e8f68319 279 if (__HAL_RTC_WAKEUPTIMER_GET_IT(&RtcHandle, RTC_IT_WUT)) {
Anna Bridge 186:707f6e361f3e 280 /* Get the status of the Interrupt */
AnnaBridge 187:0387e8f68319 281 if ((uint32_t)(RTC->CR & RTC_IT_WUT) != (uint32_t)RESET) {
Anna Bridge 186:707f6e361f3e 282 /* Clear the WAKEUPTIMER interrupt pending bit */
Anna Bridge 186:707f6e361f3e 283 __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF);
Anna Bridge 186:707f6e361f3e 284
Anna Bridge 186:707f6e361f3e 285 lp_Fired = 0;
Anna Bridge 186:707f6e361f3e 286 if (irq_handler) {
Anna Bridge 186:707f6e361f3e 287 irq_handler();
Anna Bridge 186:707f6e361f3e 288 }
Anna Bridge 186:707f6e361f3e 289 }
<> 154:37f96f9d4de2 290 }
Anna Bridge 186:707f6e361f3e 291
Anna Bridge 186:707f6e361f3e 292 if (lp_Fired) {
Anna Bridge 186:707f6e361f3e 293 lp_Fired = 0;
Anna Bridge 186:707f6e361f3e 294 if (irq_handler) {
Anna Bridge 186:707f6e361f3e 295 irq_handler();
Anna Bridge 186:707f6e361f3e 296 }
Anna Bridge 186:707f6e361f3e 297 }
Anna Bridge 186:707f6e361f3e 298
Anna Bridge 186:707f6e361f3e 299 __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
<> 154:37f96f9d4de2 300 }
<> 154:37f96f9d4de2 301
Anna Bridge 186:707f6e361f3e 302 uint32_t rtc_read_lp(void)
<> 154:37f96f9d4de2 303 {
AnnaBridge 188:bcfe06ba3d64 304 /* RTC_time_tick is the addition of the RTC time register (in second) and the RTC sub-second register
AnnaBridge 188:bcfe06ba3d64 305 * This time value is breaking each 24h (= 86400s = 0x15180)
AnnaBridge 188:bcfe06ba3d64 306 * In order to get a U32 continuous time information, we use an internal counter : LPTICKER_counter
AnnaBridge 188:bcfe06ba3d64 307 * This counter is the addition of each spent time since last function call
AnnaBridge 188:bcfe06ba3d64 308 * Current RTC time is saved into LPTICKER_RTC_time
AnnaBridge 188:bcfe06ba3d64 309 * NB: rtc_read_lp() output is not the time in us, but the LPTICKER_counter (frequency LSE/4 = 8kHz => 122us)
AnnaBridge 188:bcfe06ba3d64 310 */
AnnaBridge 188:bcfe06ba3d64 311 core_util_critical_section_enter();
AnnaBridge 187:0387e8f68319 312 struct tm timeinfo;
AnnaBridge 181:57724642e740 313
AnnaBridge 187:0387e8f68319 314 /* Since the shadow registers are bypassed we have to read the time twice and compare them until both times are the same */
AnnaBridge 187:0387e8f68319 315 /* We don't have to read date as we bypass shadow registers */
AnnaBridge 187:0387e8f68319 316 uint32_t Read_time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK);
AnnaBridge 187:0387e8f68319 317 uint32_t Read_SubSeconds = (uint32_t)(RTC->SSR);
AnnaBridge 181:57724642e740 318
AnnaBridge 187:0387e8f68319 319 while ((Read_time != (RTC->TR & RTC_TR_RESERVED_MASK)) || (Read_SubSeconds != (RTC->SSR))) {
AnnaBridge 187:0387e8f68319 320 Read_time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK);
AnnaBridge 187:0387e8f68319 321 Read_SubSeconds = (uint32_t)(RTC->SSR);
AnnaBridge 187:0387e8f68319 322 }
AnnaBridge 181:57724642e740 323
AnnaBridge 187:0387e8f68319 324 timeinfo.tm_hour = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_HT | RTC_TR_HU)) >> 16));
AnnaBridge 187:0387e8f68319 325 timeinfo.tm_min = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_MNT | RTC_TR_MNU)) >> 8));
AnnaBridge 187:0387e8f68319 326 timeinfo.tm_sec = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_ST | RTC_TR_SU)) >> 0));
AnnaBridge 187:0387e8f68319 327
AnnaBridge 188:bcfe06ba3d64 328 uint32_t RTC_time_tick = (timeinfo.tm_sec + timeinfo.tm_min * 60 + timeinfo.tm_hour * 60 * 60) * PREDIV_S_VALUE + PREDIV_S_VALUE - Read_SubSeconds; // Max 0x0001-517F * 8191 + 8191 = 0x2A2E-AE80
AnnaBridge 181:57724642e740 329
AnnaBridge 188:bcfe06ba3d64 330 if (LPTICKER_RTC_time <= RTC_time_tick) {
AnnaBridge 188:bcfe06ba3d64 331 LPTICKER_counter += (RTC_time_tick - LPTICKER_RTC_time);
Anna Bridge 186:707f6e361f3e 332 } else {
AnnaBridge 188:bcfe06ba3d64 333 /* When RTC time is 0h00.01 and was 11H59.59, difference is "current time + 24h - previous time" */
AnnaBridge 188:bcfe06ba3d64 334 LPTICKER_counter += (RTC_time_tick + 24 * 60 * 60 * PREDIV_S_VALUE - LPTICKER_RTC_time);
Anna Bridge 186:707f6e361f3e 335 }
AnnaBridge 188:bcfe06ba3d64 336 LPTICKER_RTC_time = RTC_time_tick;
Anna Bridge 186:707f6e361f3e 337
AnnaBridge 188:bcfe06ba3d64 338 core_util_critical_section_exit();
AnnaBridge 188:bcfe06ba3d64 339 return LPTICKER_counter;
<> 154:37f96f9d4de2 340 }
<> 154:37f96f9d4de2 341
Anna Bridge 186:707f6e361f3e 342 void rtc_set_wake_up_timer(timestamp_t timestamp)
<> 154:37f96f9d4de2 343 {
Anna Bridge 186:707f6e361f3e 344 uint32_t WakeUpCounter;
Anna Bridge 186:707f6e361f3e 345 uint32_t current_lp_time;
AnnaBridge 184:08ed48f1de7f 346
Anna Bridge 186:707f6e361f3e 347 current_lp_time = rtc_read_lp();
AnnaBridge 184:08ed48f1de7f 348
Anna Bridge 186:707f6e361f3e 349 if (timestamp < current_lp_time) {
Anna Bridge 186:707f6e361f3e 350 WakeUpCounter = 0xFFFFFFFF - current_lp_time + timestamp;
AnnaBridge 184:08ed48f1de7f 351 } else {
Anna Bridge 186:707f6e361f3e 352 WakeUpCounter = timestamp - current_lp_time;
Anna Bridge 186:707f6e361f3e 353 }
Anna Bridge 186:707f6e361f3e 354
Anna Bridge 186:707f6e361f3e 355 if (WakeUpCounter > 0xFFFF) {
Anna Bridge 186:707f6e361f3e 356 WakeUpCounter = 0xFFFF;
Anna Bridge 180:96ed750bd169 357 }
Anna Bridge 180:96ed750bd169 358
AnnaBridge 188:bcfe06ba3d64 359 core_util_critical_section_enter();
Anna Bridge 180:96ed750bd169 360 RtcHandle.Instance = RTC;
AnnaBridge 188:bcfe06ba3d64 361 HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
Anna Bridge 186:707f6e361f3e 362 if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, WakeUpCounter, RTC_WAKEUPCLOCK_RTCCLK_DIV4) != HAL_OK) {
AnnaBridge 184:08ed48f1de7f 363 error("rtc_set_wake_up_timer init error\n");
<> 154:37f96f9d4de2 364 }
Anna Bridge 186:707f6e361f3e 365
Anna Bridge 186:707f6e361f3e 366 NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
Anna Bridge 186:707f6e361f3e 367 irq_handler = (void (*)(void))lp_ticker_irq_handler;
Anna Bridge 186:707f6e361f3e 368 NVIC_EnableIRQ(RTC_WKUP_IRQn);
AnnaBridge 188:bcfe06ba3d64 369 core_util_critical_section_exit();
Anna Bridge 186:707f6e361f3e 370 }
Anna Bridge 186:707f6e361f3e 371
Anna Bridge 186:707f6e361f3e 372 void rtc_fire_interrupt(void)
Anna Bridge 186:707f6e361f3e 373 {
Anna Bridge 186:707f6e361f3e 374 lp_Fired = 1;
Anna Bridge 186:707f6e361f3e 375 NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
Anna Bridge 186:707f6e361f3e 376 irq_handler = (void (*)(void))lp_ticker_irq_handler;
Anna Bridge 186:707f6e361f3e 377 NVIC_SetPendingIRQ(RTC_WKUP_IRQn);
Anna Bridge 186:707f6e361f3e 378 NVIC_EnableIRQ(RTC_WKUP_IRQn);
<> 154:37f96f9d4de2 379 }
<> 154:37f96f9d4de2 380
<> 154:37f96f9d4de2 381 void rtc_deactivate_wake_up_timer(void)
<> 154:37f96f9d4de2 382 {
Anna Bridge 180:96ed750bd169 383 RtcHandle.Instance = RTC;
AnnaBridge 188:bcfe06ba3d64 384 HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
AnnaBridge 187:0387e8f68319 385 NVIC_DisableIRQ(RTC_WKUP_IRQn);
<> 154:37f96f9d4de2 386 }
<> 154:37f96f9d4de2 387
Anna Bridge 186:707f6e361f3e 388 #endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
<> 154:37f96f9d4de2 389
<> 154:37f96f9d4de2 390 #endif /* DEVICE_RTC */