mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_STM/rtc_api.c@189:f392fc9709a3, 2019-02-20 (annotated)
- 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?
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 | |
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 */ |