mbed library sources. Supersedes mbed-src.

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

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
188:bcfe06ba3d64
mbed library release version 165

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
AnnaBridge 189:f392fc9709a3 96 #if defined __HAL_RCC_RTCAPB_CLK_ENABLE /* part of STM32L4 */
AnnaBridge 189:f392fc9709a3 97 __HAL_RCC_RTCAPB_CLK_ENABLE();
AnnaBridge 189:f392fc9709a3 98 #endif /* __HAL_RCC_RTCAPB_CLK_ENABLE */
AnnaBridge 189:f392fc9709a3 99
Anna Bridge 180:96ed750bd169 100 RtcHandle.Instance = RTC;
Anna Bridge 180:96ed750bd169 101 RtcHandle.State = HAL_RTC_STATE_RESET;
Anna Bridge 180:96ed750bd169 102
<> 154:37f96f9d4de2 103 #if TARGET_STM32F1
<> 154:37f96f9d4de2 104 RtcHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
<> 154:37f96f9d4de2 105 #else /* TARGET_STM32F1 */
<> 154:37f96f9d4de2 106 RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
Anna Bridge 186:707f6e361f3e 107 RtcHandle.Init.AsynchPrediv = PREDIV_A_VALUE;
Anna Bridge 186:707f6e361f3e 108 RtcHandle.Init.SynchPrediv = PREDIV_S_VALUE;
<> 154:37f96f9d4de2 109 RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
<> 154:37f96f9d4de2 110 RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
<> 154:37f96f9d4de2 111 RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
AnnaBridge 189:f392fc9709a3 112 #if defined (RTC_OUTPUT_REMAP_NONE)
AnnaBridge 189:f392fc9709a3 113 RtcHandle.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
AnnaBridge 189:f392fc9709a3 114 #endif /* defined (RTC_OUTPUT_REMAP_NONE) */
AnnaBridge 189:f392fc9709a3 115 #if defined (RTC_OUTPUT_PULLUP_NONE)
AnnaBridge 189:f392fc9709a3 116 RtcHandle.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
AnnaBridge 189:f392fc9709a3 117 #endif /* defined (RTC_OUTPUT_PULLUP_NONE) */
<> 154:37f96f9d4de2 118 #endif /* TARGET_STM32F1 */
<> 154:37f96f9d4de2 119
<> 154:37f96f9d4de2 120 if (HAL_RTC_Init(&RtcHandle) != HAL_OK) {
AnnaBridge 188:bcfe06ba3d64 121 error("RTC initialization failed\n");
<> 154:37f96f9d4de2 122 }
<> 154:37f96f9d4de2 123
AnnaBridge 187:0387e8f68319 124 #if !(TARGET_STM32F1) && !(TARGET_STM32F2)
AnnaBridge 187:0387e8f68319 125 /* STM32F1 : there are no shadow registers */
AnnaBridge 187:0387e8f68319 126 /* STM32F2 : shadow registers can not be bypassed */
AnnaBridge 187:0387e8f68319 127 if (HAL_RTCEx_EnableBypassShadow(&RtcHandle) != HAL_OK) {
AnnaBridge 188:bcfe06ba3d64 128 error("EnableBypassShadow error\n");
<> 154:37f96f9d4de2 129 }
AnnaBridge 187:0387e8f68319 130 #endif /* TARGET_STM32F1 || TARGET_STM32F2 */
<> 154:37f96f9d4de2 131 }
<> 154:37f96f9d4de2 132
<> 154:37f96f9d4de2 133 void rtc_free(void)
<> 154:37f96f9d4de2 134 {
AnnaBridge 187:0387e8f68319 135 /* RTC clock can not be reset */
<> 154:37f96f9d4de2 136 }
<> 154:37f96f9d4de2 137
<> 160:d5399cc887bb 138
<> 160:d5399cc887bb 139 /*
<> 160:d5399cc887bb 140 Information about STM32F0, STM32F2, STM32F3, STM32F4, STM32F7, STM32L0, STM32L1, STM32L4:
<> 160:d5399cc887bb 141 BCD format is used to store the date in the RTC. The year is store on 2 * 4 bits.
<> 160:d5399cc887bb 142 Because the first year is reserved to see if the RTC is init, the supposed range is 01-99.
<> 160:d5399cc887bb 143 1st point is to cover the standard range from 1970 to 2038 (limited by the 32 bits of time_t).
<> 160:d5399cc887bb 144 2nd point is to keep the year 1970 and the leap years synchronized.
<> 160:d5399cc887bb 145
<> 160:d5399cc887bb 146 So by moving it 68 years forward from 1970, it become 1969-2067 which include 1970-2038.
<> 160:d5399cc887bb 147 68 is also a multiple of 4 so it let the leap year synchronized.
<> 160:d5399cc887bb 148
<> 160:d5399cc887bb 149 Information about STM32F1:
AnnaBridge 182:a56a73fd2a6f 150 32bit register is used (no BCD format) for the seconds.
AnnaBridge 182:a56a73fd2a6f 151 For date, there is no specific register, only a software structure.
<> 160:d5399cc887bb 152 It is then not a problem to not use shifts.
<> 160:d5399cc887bb 153 */
<> 154:37f96f9d4de2 154 time_t rtc_read(void)
<> 154:37f96f9d4de2 155 {
AnnaBridge 188:bcfe06ba3d64 156 #if TARGET_STM32F1
<> 154:37f96f9d4de2 157
<> 154:37f96f9d4de2 158 RtcHandle.Instance = RTC;
AnnaBridge 188:bcfe06ba3d64 159 return RTC_ReadTimeCounter(&RtcHandle);
<> 154:37f96f9d4de2 160
AnnaBridge 187:0387e8f68319 161 #else /* TARGET_STM32F1 */
AnnaBridge 187:0387e8f68319 162
AnnaBridge 187:0387e8f68319 163 struct tm timeinfo;
AnnaBridge 187:0387e8f68319 164
AnnaBridge 187:0387e8f68319 165 /* 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 166 uint32_t Read_time = RTC->TR & RTC_TR_RESERVED_MASK;
AnnaBridge 187:0387e8f68319 167 uint32_t Read_date = RTC->DR & RTC_DR_RESERVED_MASK;
AnnaBridge 187:0387e8f68319 168
AnnaBridge 187:0387e8f68319 169 while ((Read_time != (RTC->TR & RTC_TR_RESERVED_MASK)) || (Read_date != (RTC->DR & RTC_DR_RESERVED_MASK))) {
AnnaBridge 187:0387e8f68319 170 Read_time = RTC->TR & RTC_TR_RESERVED_MASK;
AnnaBridge 187:0387e8f68319 171 Read_date = RTC->DR & RTC_DR_RESERVED_MASK;
AnnaBridge 187:0387e8f68319 172 }
AnnaBridge 187:0387e8f68319 173
AnnaBridge 187:0387e8f68319 174 /* Setup a tm structure based on the RTC
AnnaBridge 187:0387e8f68319 175 struct tm :
AnnaBridge 187:0387e8f68319 176 tm_sec seconds after the minute 0-61
AnnaBridge 187:0387e8f68319 177 tm_min minutes after the hour 0-59
AnnaBridge 187:0387e8f68319 178 tm_hour hours since midnight 0-23
AnnaBridge 187:0387e8f68319 179 tm_mday day of the month 1-31
AnnaBridge 187:0387e8f68319 180 tm_mon months since January 0-11
AnnaBridge 187:0387e8f68319 181 tm_year years since 1900
AnnaBridge 187:0387e8f68319 182 tm_yday information is ignored by _rtc_maketime
AnnaBridge 187:0387e8f68319 183 tm_wday information is ignored by _rtc_maketime
AnnaBridge 187:0387e8f68319 184 tm_isdst information is ignored by _rtc_maketime
AnnaBridge 187:0387e8f68319 185 */
AnnaBridge 187:0387e8f68319 186 timeinfo.tm_mday = RTC_Bcd2ToByte((uint8_t)(Read_date & (RTC_DR_DT | RTC_DR_DU)));
AnnaBridge 187:0387e8f68319 187 timeinfo.tm_mon = RTC_Bcd2ToByte((uint8_t)((Read_date & (RTC_DR_MT | RTC_DR_MU)) >> 8)) - 1;
AnnaBridge 187:0387e8f68319 188 timeinfo.tm_year = RTC_Bcd2ToByte((uint8_t)((Read_date & (RTC_DR_YT | RTC_DR_YU)) >> 16)) + 68;
AnnaBridge 187:0387e8f68319 189 timeinfo.tm_hour = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_HT | RTC_TR_HU)) >> 16));
AnnaBridge 187:0387e8f68319 190 timeinfo.tm_min = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_MNT | RTC_TR_MNU)) >> 8));
AnnaBridge 187:0387e8f68319 191 timeinfo.tm_sec = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_ST | RTC_TR_SU)) >> 0));
AnnaBridge 187:0387e8f68319 192
AnnaBridge 187:0387e8f68319 193 // Convert to timestamp
AnnaBridge 187:0387e8f68319 194 time_t t;
AnnaBridge 187:0387e8f68319 195 if (_rtc_maketime(&timeinfo, &t, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) {
AnnaBridge 187:0387e8f68319 196 return 0;
AnnaBridge 187:0387e8f68319 197 }
AnnaBridge 187:0387e8f68319 198
AnnaBridge 187:0387e8f68319 199 return t;
AnnaBridge 188:bcfe06ba3d64 200
AnnaBridge 188:bcfe06ba3d64 201 #endif /* TARGET_STM32F1 */
AnnaBridge 187:0387e8f68319 202 }
AnnaBridge 187:0387e8f68319 203
AnnaBridge 188:bcfe06ba3d64 204
AnnaBridge 187:0387e8f68319 205
<> 154:37f96f9d4de2 206 void rtc_write(time_t t)
<> 154:37f96f9d4de2 207 {
AnnaBridge 188:bcfe06ba3d64 208 #if TARGET_STM32F1
AnnaBridge 188:bcfe06ba3d64 209
AnnaBridge 188:bcfe06ba3d64 210 RtcHandle.Instance = RTC;
AnnaBridge 188:bcfe06ba3d64 211 if (RTC_WriteTimeCounter(&RtcHandle, t) != HAL_OK) {
AnnaBridge 188:bcfe06ba3d64 212 error("RTC_WriteTimeCounter error\n");
AnnaBridge 188:bcfe06ba3d64 213 }
AnnaBridge 188:bcfe06ba3d64 214
AnnaBridge 188:bcfe06ba3d64 215 #else /* TARGET_STM32F1 */
AnnaBridge 188:bcfe06ba3d64 216
AnnaBridge 176:447f873cad2f 217 RTC_DateTypeDef dateStruct = {0};
AnnaBridge 176:447f873cad2f 218 RTC_TimeTypeDef timeStruct = {0};
<> 154:37f96f9d4de2 219
AnnaBridge 187:0387e8f68319 220 core_util_critical_section_enter();
<> 154:37f96f9d4de2 221 RtcHandle.Instance = RTC;
<> 154:37f96f9d4de2 222
<> 154:37f96f9d4de2 223 // Convert the time into a tm
AnnaBridge 167:e84263d55307 224 struct tm timeinfo;
AnnaBridge 184:08ed48f1de7f 225 if (_rtc_localtime(t, &timeinfo, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) {
AnnaBridge 167:e84263d55307 226 return;
AnnaBridge 167:e84263d55307 227 }
<> 154:37f96f9d4de2 228
<> 154:37f96f9d4de2 229 // Fill RTC structures
AnnaBridge 187:0387e8f68319 230 if (timeinfo.tm_wday == 0) { /* Sunday specific case */
AnnaBridge 187:0387e8f68319 231 dateStruct.WeekDay = RTC_WEEKDAY_SUNDAY;
<> 160:d5399cc887bb 232 } else {
AnnaBridge 167:e84263d55307 233 dateStruct.WeekDay = timeinfo.tm_wday;
<> 160:d5399cc887bb 234 }
AnnaBridge 167:e84263d55307 235 dateStruct.Month = timeinfo.tm_mon + 1;
AnnaBridge 167:e84263d55307 236 dateStruct.Date = timeinfo.tm_mday;
AnnaBridge 167:e84263d55307 237 dateStruct.Year = timeinfo.tm_year - 68;
AnnaBridge 167:e84263d55307 238 timeStruct.Hours = timeinfo.tm_hour;
AnnaBridge 167:e84263d55307 239 timeStruct.Minutes = timeinfo.tm_min;
AnnaBridge 167:e84263d55307 240 timeStruct.Seconds = timeinfo.tm_sec;
<> 154:37f96f9d4de2 241 timeStruct.TimeFormat = RTC_HOURFORMAT_24;
<> 154:37f96f9d4de2 242 timeStruct.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
<> 154:37f96f9d4de2 243 timeStruct.StoreOperation = RTC_STOREOPERATION_RESET;
<> 154:37f96f9d4de2 244
AnnaBridge 187:0387e8f68319 245 #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
AnnaBridge 188:bcfe06ba3d64 246 /* Before setting the new time, we need to update the LPTICKER_counter value */
AnnaBridge 188:bcfe06ba3d64 247 /* rtc_read_lp function is then called */
AnnaBridge 187:0387e8f68319 248 rtc_read_lp();
AnnaBridge 187:0387e8f68319 249
AnnaBridge 188:bcfe06ba3d64 250 /* In rtc_read_lp, LPTICKER_RTC_time value has been updated with the current time */
AnnaBridge 188:bcfe06ba3d64 251 /* We need now to overwrite the value with the new RTC time */
AnnaBridge 188:bcfe06ba3d64 252 /* Note that when a new RTC time is set by HW, the RTC SubSeconds counter is reset to PREDIV_S_VALUE */
AnnaBridge 188:bcfe06ba3d64 253 LPTICKER_RTC_time = (timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60) * PREDIV_S_VALUE;
AnnaBridge 187:0387e8f68319 254 #endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
AnnaBridge 187:0387e8f68319 255
<> 154:37f96f9d4de2 256 // Change the RTC current date/time
Anna Bridge 180:96ed750bd169 257 if (HAL_RTC_SetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN) != HAL_OK) {
Anna Bridge 180:96ed750bd169 258 error("HAL_RTC_SetDate error\n");
Anna Bridge 180:96ed750bd169 259 }
Anna Bridge 180:96ed750bd169 260 if (HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN) != HAL_OK) {
Anna Bridge 180:96ed750bd169 261 error("HAL_RTC_SetTime error\n");
Anna Bridge 180:96ed750bd169 262 }
AnnaBridge 187:0387e8f68319 263
AnnaBridge 187:0387e8f68319 264 core_util_critical_section_exit();
AnnaBridge 188:bcfe06ba3d64 265 #endif /* TARGET_STM32F1 */
<> 154:37f96f9d4de2 266 }
<> 154:37f96f9d4de2 267
<> 154:37f96f9d4de2 268 int rtc_isenabled(void)
<> 154:37f96f9d4de2 269 {
AnnaBridge 189:f392fc9709a3 270 #if defined (RTC_FLAG_INITS) /* all STM32 except STM32F1 */
AnnaBridge 189:f392fc9709a3 271 return LL_RTC_IsActiveFlag_INITS(RTC);
AnnaBridge 189:f392fc9709a3 272 #else /* RTC_FLAG_INITS */ /* TARGET_STM32F1 */
<> 160:d5399cc887bb 273 return ((RTC->CRL & RTC_CRL_RSF) == RTC_CRL_RSF);
AnnaBridge 189:f392fc9709a3 274 #endif /* RTC_FLAG_INITS */
<> 154:37f96f9d4de2 275 }
<> 154:37f96f9d4de2 276
Anna Bridge 180:96ed750bd169 277
Anna Bridge 186:707f6e361f3e 278 #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM
Anna Bridge 186:707f6e361f3e 279
Anna Bridge 186:707f6e361f3e 280 static void RTC_IRQHandler(void);
Anna Bridge 186:707f6e361f3e 281 static void (*irq_handler)(void);
Anna Bridge 186:707f6e361f3e 282
Anna Bridge 186:707f6e361f3e 283 volatile uint8_t lp_Fired = 0;
<> 154:37f96f9d4de2 284
<> 154:37f96f9d4de2 285 static void RTC_IRQHandler(void)
<> 154:37f96f9d4de2 286 {
AnnaBridge 176:447f873cad2f 287 /* Update HAL state */
Anna Bridge 180:96ed750bd169 288 RtcHandle.Instance = RTC;
AnnaBridge 187:0387e8f68319 289 if (__HAL_RTC_WAKEUPTIMER_GET_IT(&RtcHandle, RTC_IT_WUT)) {
Anna Bridge 186:707f6e361f3e 290 /* Get the status of the Interrupt */
AnnaBridge 187:0387e8f68319 291 if ((uint32_t)(RTC->CR & RTC_IT_WUT) != (uint32_t)RESET) {
Anna Bridge 186:707f6e361f3e 292 /* Clear the WAKEUPTIMER interrupt pending bit */
Anna Bridge 186:707f6e361f3e 293 __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF);
Anna Bridge 186:707f6e361f3e 294
Anna Bridge 186:707f6e361f3e 295 lp_Fired = 0;
Anna Bridge 186:707f6e361f3e 296 if (irq_handler) {
Anna Bridge 186:707f6e361f3e 297 irq_handler();
Anna Bridge 186:707f6e361f3e 298 }
Anna Bridge 186:707f6e361f3e 299 }
<> 154:37f96f9d4de2 300 }
Anna Bridge 186:707f6e361f3e 301
Anna Bridge 186:707f6e361f3e 302 if (lp_Fired) {
Anna Bridge 186:707f6e361f3e 303 lp_Fired = 0;
Anna Bridge 186:707f6e361f3e 304 if (irq_handler) {
Anna Bridge 186:707f6e361f3e 305 irq_handler();
Anna Bridge 186:707f6e361f3e 306 }
Anna Bridge 186:707f6e361f3e 307 }
Anna Bridge 186:707f6e361f3e 308
AnnaBridge 189:f392fc9709a3 309 #ifdef __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG
Anna Bridge 186:707f6e361f3e 310 __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
AnnaBridge 189:f392fc9709a3 311 #endif
<> 154:37f96f9d4de2 312 }
<> 154:37f96f9d4de2 313
Anna Bridge 186:707f6e361f3e 314 uint32_t rtc_read_lp(void)
<> 154:37f96f9d4de2 315 {
AnnaBridge 188:bcfe06ba3d64 316 /* RTC_time_tick is the addition of the RTC time register (in second) and the RTC sub-second register
AnnaBridge 188:bcfe06ba3d64 317 * This time value is breaking each 24h (= 86400s = 0x15180)
AnnaBridge 188:bcfe06ba3d64 318 * In order to get a U32 continuous time information, we use an internal counter : LPTICKER_counter
AnnaBridge 188:bcfe06ba3d64 319 * This counter is the addition of each spent time since last function call
AnnaBridge 188:bcfe06ba3d64 320 * Current RTC time is saved into LPTICKER_RTC_time
AnnaBridge 188:bcfe06ba3d64 321 * NB: rtc_read_lp() output is not the time in us, but the LPTICKER_counter (frequency LSE/4 = 8kHz => 122us)
AnnaBridge 188:bcfe06ba3d64 322 */
AnnaBridge 188:bcfe06ba3d64 323 core_util_critical_section_enter();
AnnaBridge 187:0387e8f68319 324 struct tm timeinfo;
AnnaBridge 181:57724642e740 325
AnnaBridge 187:0387e8f68319 326 /* 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 327 /* We don't have to read date as we bypass shadow registers */
AnnaBridge 187:0387e8f68319 328 uint32_t Read_time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK);
AnnaBridge 187:0387e8f68319 329 uint32_t Read_SubSeconds = (uint32_t)(RTC->SSR);
AnnaBridge 181:57724642e740 330
AnnaBridge 187:0387e8f68319 331 while ((Read_time != (RTC->TR & RTC_TR_RESERVED_MASK)) || (Read_SubSeconds != (RTC->SSR))) {
AnnaBridge 187:0387e8f68319 332 Read_time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK);
AnnaBridge 187:0387e8f68319 333 Read_SubSeconds = (uint32_t)(RTC->SSR);
AnnaBridge 187:0387e8f68319 334 }
AnnaBridge 181:57724642e740 335
AnnaBridge 187:0387e8f68319 336 timeinfo.tm_hour = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_HT | RTC_TR_HU)) >> 16));
AnnaBridge 187:0387e8f68319 337 timeinfo.tm_min = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_MNT | RTC_TR_MNU)) >> 8));
AnnaBridge 187:0387e8f68319 338 timeinfo.tm_sec = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_ST | RTC_TR_SU)) >> 0));
AnnaBridge 187:0387e8f68319 339
AnnaBridge 188:bcfe06ba3d64 340 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 341
AnnaBridge 188:bcfe06ba3d64 342 if (LPTICKER_RTC_time <= RTC_time_tick) {
AnnaBridge 188:bcfe06ba3d64 343 LPTICKER_counter += (RTC_time_tick - LPTICKER_RTC_time);
Anna Bridge 186:707f6e361f3e 344 } else {
AnnaBridge 188:bcfe06ba3d64 345 /* When RTC time is 0h00.01 and was 11H59.59, difference is "current time + 24h - previous time" */
AnnaBridge 188:bcfe06ba3d64 346 LPTICKER_counter += (RTC_time_tick + 24 * 60 * 60 * PREDIV_S_VALUE - LPTICKER_RTC_time);
Anna Bridge 186:707f6e361f3e 347 }
AnnaBridge 188:bcfe06ba3d64 348 LPTICKER_RTC_time = RTC_time_tick;
Anna Bridge 186:707f6e361f3e 349
AnnaBridge 188:bcfe06ba3d64 350 core_util_critical_section_exit();
AnnaBridge 188:bcfe06ba3d64 351 return LPTICKER_counter;
<> 154:37f96f9d4de2 352 }
<> 154:37f96f9d4de2 353
Anna Bridge 186:707f6e361f3e 354 void rtc_set_wake_up_timer(timestamp_t timestamp)
<> 154:37f96f9d4de2 355 {
AnnaBridge 189:f392fc9709a3 356 /* RTC periodic auto wake up timer is used
AnnaBridge 189:f392fc9709a3 357 * This WakeUpTimer is loaded to an init value => WakeUpCounter
AnnaBridge 189:f392fc9709a3 358 * then timer starts counting down (even in low-power modes)
AnnaBridge 189:f392fc9709a3 359 * When it reaches 0, the WUTF flag is set in the RTC_ISR register
AnnaBridge 189:f392fc9709a3 360 */
Anna Bridge 186:707f6e361f3e 361 uint32_t WakeUpCounter;
AnnaBridge 189:f392fc9709a3 362 uint32_t WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV4;
AnnaBridge 184:08ed48f1de7f 363
AnnaBridge 189:f392fc9709a3 364 core_util_critical_section_enter();
AnnaBridge 184:08ed48f1de7f 365
AnnaBridge 189:f392fc9709a3 366 /* MBED API gives the timestamp value to set
AnnaBridge 189:f392fc9709a3 367 * WakeUpCounter is then the delta between timestamp and the current tick (LPTICKER_counter)
AnnaBridge 189:f392fc9709a3 368 * If the current tick preceeds timestamp value, max U32 is added
AnnaBridge 189:f392fc9709a3 369 */
AnnaBridge 189:f392fc9709a3 370 uint32_t current_lp_time = rtc_read_lp();
Anna Bridge 186:707f6e361f3e 371 if (timestamp < current_lp_time) {
Anna Bridge 186:707f6e361f3e 372 WakeUpCounter = 0xFFFFFFFF - current_lp_time + timestamp;
AnnaBridge 184:08ed48f1de7f 373 } else {
Anna Bridge 186:707f6e361f3e 374 WakeUpCounter = timestamp - current_lp_time;
Anna Bridge 186:707f6e361f3e 375 }
Anna Bridge 186:707f6e361f3e 376
AnnaBridge 189:f392fc9709a3 377 /* RTC WakeUpCounter is 16 bits
AnnaBridge 189:f392fc9709a3 378 * Corresponding time value depends on WakeUpClock
AnnaBridge 189:f392fc9709a3 379 * - RTC clock divided by 4 : max WakeUpCounter value is 8s (precision around 122 us)
AnnaBridge 189:f392fc9709a3 380 * - RTC clock divided by 8 : max WakeUpCounter value is 16s (precision around 244 us)
AnnaBridge 189:f392fc9709a3 381 * - RTC clock divided by 16 : max WakeUpCounter value is 32s (precision around 488 us)
AnnaBridge 189:f392fc9709a3 382 * - 1 Hz internal clock 16b : max WakeUpCounter value is 18h (precision 1 s)
AnnaBridge 189:f392fc9709a3 383 * - 1 Hz internal clock 17b : max WakeUpCounter value is 36h (precision 1 s)
AnnaBridge 189:f392fc9709a3 384 */
Anna Bridge 186:707f6e361f3e 385 if (WakeUpCounter > 0xFFFF) {
AnnaBridge 189:f392fc9709a3 386 WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV8;
AnnaBridge 189:f392fc9709a3 387 WakeUpCounter = WakeUpCounter / 2;
AnnaBridge 189:f392fc9709a3 388
AnnaBridge 189:f392fc9709a3 389 if (WakeUpCounter > 0xFFFF) {
AnnaBridge 189:f392fc9709a3 390 WakeUpClock = RTC_WAKEUPCLOCK_RTCCLK_DIV16;
AnnaBridge 189:f392fc9709a3 391 WakeUpCounter = WakeUpCounter / 2;
AnnaBridge 189:f392fc9709a3 392
AnnaBridge 189:f392fc9709a3 393 if (WakeUpCounter > 0xFFFF) {
AnnaBridge 189:f392fc9709a3 394 /* Tick value needs to be translated in seconds : TICK * 16 (previous div16 value) / RTC clock (32768) */
AnnaBridge 189:f392fc9709a3 395 WakeUpClock = RTC_WAKEUPCLOCK_CK_SPRE_16BITS;
AnnaBridge 189:f392fc9709a3 396 WakeUpCounter = WakeUpCounter / 2048;
AnnaBridge 189:f392fc9709a3 397
AnnaBridge 189:f392fc9709a3 398 if (WakeUpCounter > 0xFFFF) {
AnnaBridge 189:f392fc9709a3 399 /* In this case 2^16 is added to the 16-bit counter value */
AnnaBridge 189:f392fc9709a3 400 WakeUpClock = RTC_WAKEUPCLOCK_CK_SPRE_17BITS;
AnnaBridge 189:f392fc9709a3 401 WakeUpCounter = WakeUpCounter - 0x10000;
AnnaBridge 189:f392fc9709a3 402 }
AnnaBridge 189:f392fc9709a3 403 }
AnnaBridge 189:f392fc9709a3 404 }
Anna Bridge 180:96ed750bd169 405 }
Anna Bridge 180:96ed750bd169 406
Anna Bridge 180:96ed750bd169 407 RtcHandle.Instance = RTC;
AnnaBridge 188:bcfe06ba3d64 408 HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
AnnaBridge 189:f392fc9709a3 409 if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, WakeUpCounter, WakeUpClock) != HAL_OK) {
AnnaBridge 184:08ed48f1de7f 410 error("rtc_set_wake_up_timer init error\n");
<> 154:37f96f9d4de2 411 }
Anna Bridge 186:707f6e361f3e 412
Anna Bridge 186:707f6e361f3e 413 NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
Anna Bridge 186:707f6e361f3e 414 irq_handler = (void (*)(void))lp_ticker_irq_handler;
Anna Bridge 186:707f6e361f3e 415 NVIC_EnableIRQ(RTC_WKUP_IRQn);
AnnaBridge 188:bcfe06ba3d64 416 core_util_critical_section_exit();
Anna Bridge 186:707f6e361f3e 417 }
Anna Bridge 186:707f6e361f3e 418
Anna Bridge 186:707f6e361f3e 419 void rtc_fire_interrupt(void)
Anna Bridge 186:707f6e361f3e 420 {
Anna Bridge 186:707f6e361f3e 421 lp_Fired = 1;
Anna Bridge 186:707f6e361f3e 422 NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
Anna Bridge 186:707f6e361f3e 423 irq_handler = (void (*)(void))lp_ticker_irq_handler;
Anna Bridge 186:707f6e361f3e 424 NVIC_SetPendingIRQ(RTC_WKUP_IRQn);
Anna Bridge 186:707f6e361f3e 425 NVIC_EnableIRQ(RTC_WKUP_IRQn);
<> 154:37f96f9d4de2 426 }
<> 154:37f96f9d4de2 427
<> 154:37f96f9d4de2 428 void rtc_deactivate_wake_up_timer(void)
<> 154:37f96f9d4de2 429 {
Anna Bridge 180:96ed750bd169 430 RtcHandle.Instance = RTC;
AnnaBridge 188:bcfe06ba3d64 431 HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
AnnaBridge 187:0387e8f68319 432 NVIC_DisableIRQ(RTC_WKUP_IRQn);
<> 154:37f96f9d4de2 433 }
<> 154:37f96f9d4de2 434
Anna Bridge 186:707f6e361f3e 435 #endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */
<> 154:37f96f9d4de2 436
<> 154:37f96f9d4de2 437 #endif /* DEVICE_RTC */