mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_STM/rtc_api.c@188:bcfe06ba3d64, 2018-11-08 (annotated)
- 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?
User | Revision | Line number | New 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 */ |