Modified for BG96
Fork of mbed-dev by
targets/TARGET_STM/rtc_api.c@188:60408c49b6d4, 2018-09-20 (annotated)
- Committer:
- WaleedElmughrabi
- Date:
- Thu Sep 20 16:11:23 2018 +0000
- Revision:
- 188:60408c49b6d4
- Parent:
- 187:0387e8f68319
Fork modified for BG96 error
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 | 187:0387e8f68319 | 39 | volatile uint32_t LP_continuous_time = 0; |
AnnaBridge | 187:0387e8f68319 | 40 | volatile uint32_t LP_last_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; |
<> | 154:37f96f9d4de2 | 63 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! |
<> | 154:37f96f9d4de2 | 64 | RCC_OscInitStruct.LSEState = RCC_LSE_ON; |
<> | 154:37f96f9d4de2 | 65 | |
Anna Bridge |
180:96ed750bd169 | 66 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { |
<> | 154:37f96f9d4de2 | 67 | error("Cannot initialize RTC with LSE\n"); |
<> | 154:37f96f9d4de2 | 68 | } |
<> | 154:37f96f9d4de2 | 69 | |
Anna Bridge |
180:96ed750bd169 | 70 | __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE); |
Anna Bridge |
180:96ed750bd169 | 71 | __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); |
Anna Bridge |
180:96ed750bd169 | 72 | |
<> | 154:37f96f9d4de2 | 73 | PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; |
<> | 154:37f96f9d4de2 | 74 | PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; |
<> | 154:37f96f9d4de2 | 75 | if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { |
<> | 154:37f96f9d4de2 | 76 | error("PeriphClkInitStruct RTC failed with LSE\n"); |
<> | 154:37f96f9d4de2 | 77 | } |
Anna Bridge |
180:96ed750bd169 | 78 | #else /* MBED_CONF_TARGET_LSE_AVAILABLE */ |
<> | 154:37f96f9d4de2 | 79 | // Reset Backup domain |
<> | 154:37f96f9d4de2 | 80 | __HAL_RCC_BACKUPRESET_FORCE(); |
<> | 154:37f96f9d4de2 | 81 | __HAL_RCC_BACKUPRESET_RELEASE(); |
<> | 154:37f96f9d4de2 | 82 | |
<> | 154:37f96f9d4de2 | 83 | // Enable LSI clock |
AnnaBridge | 184:08ed48f1de7f | 84 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; |
<> | 154:37f96f9d4de2 | 85 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! |
<> | 154:37f96f9d4de2 | 86 | RCC_OscInitStruct.LSIState = RCC_LSI_ON; |
<> | 154:37f96f9d4de2 | 87 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { |
<> | 154:37f96f9d4de2 | 88 | error("Cannot initialize RTC with LSI\n"); |
<> | 154:37f96f9d4de2 | 89 | } |
<> | 154:37f96f9d4de2 | 90 | |
<> | 154:37f96f9d4de2 | 91 | __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSI); |
<> | 154:37f96f9d4de2 | 92 | __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI); |
<> | 154:37f96f9d4de2 | 93 | |
<> | 154:37f96f9d4de2 | 94 | PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; |
<> | 154:37f96f9d4de2 | 95 | PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; |
<> | 154:37f96f9d4de2 | 96 | if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { |
<> | 154:37f96f9d4de2 | 97 | error("PeriphClkInitStruct RTC failed with LSI\n"); |
<> | 154:37f96f9d4de2 | 98 | } |
Anna Bridge |
180:96ed750bd169 | 99 | #endif /* MBED_CONF_TARGET_LSE_AVAILABLE */ |
<> | 154:37f96f9d4de2 | 100 | |
<> | 154:37f96f9d4de2 | 101 | // Enable RTC |
<> | 154:37f96f9d4de2 | 102 | __HAL_RCC_RTC_ENABLE(); |
<> | 154:37f96f9d4de2 | 103 | |
Anna Bridge |
180:96ed750bd169 | 104 | RtcHandle.Instance = RTC; |
Anna Bridge |
180:96ed750bd169 | 105 | RtcHandle.State = HAL_RTC_STATE_RESET; |
Anna Bridge |
180:96ed750bd169 | 106 | |
<> | 154:37f96f9d4de2 | 107 | #if TARGET_STM32F1 |
<> | 154:37f96f9d4de2 | 108 | RtcHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND; |
<> | 154:37f96f9d4de2 | 109 | #else /* TARGET_STM32F1 */ |
<> | 154:37f96f9d4de2 | 110 | RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; |
Anna Bridge |
186:707f6e361f3e | 111 | RtcHandle.Init.AsynchPrediv = PREDIV_A_VALUE; |
Anna Bridge |
186:707f6e361f3e | 112 | RtcHandle.Init.SynchPrediv = PREDIV_S_VALUE; |
<> | 154:37f96f9d4de2 | 113 | RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; |
<> | 154:37f96f9d4de2 | 114 | RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; |
<> | 154:37f96f9d4de2 | 115 | RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; |
<> | 154:37f96f9d4de2 | 116 | #endif /* TARGET_STM32F1 */ |
<> | 154:37f96f9d4de2 | 117 | |
<> | 154:37f96f9d4de2 | 118 | if (HAL_RTC_Init(&RtcHandle) != HAL_OK) { |
Anna Bridge |
180:96ed750bd169 | 119 | error("RTC initialization failed"); |
<> | 154:37f96f9d4de2 | 120 | } |
<> | 154:37f96f9d4de2 | 121 | |
AnnaBridge | 187:0387e8f68319 | 122 | #if !(TARGET_STM32F1) && !(TARGET_STM32F2) |
AnnaBridge | 187:0387e8f68319 | 123 | /* STM32F1 : there are no shadow registers */ |
AnnaBridge | 187:0387e8f68319 | 124 | /* STM32F2 : shadow registers can not be bypassed */ |
AnnaBridge | 187:0387e8f68319 | 125 | if (HAL_RTCEx_EnableBypassShadow(&RtcHandle) != HAL_OK) { |
AnnaBridge | 187:0387e8f68319 | 126 | error("EnableBypassShadow error"); |
<> | 154:37f96f9d4de2 | 127 | } |
AnnaBridge | 187:0387e8f68319 | 128 | #endif /* TARGET_STM32F1 || TARGET_STM32F2 */ |
<> | 154:37f96f9d4de2 | 129 | } |
<> | 154:37f96f9d4de2 | 130 | |
<> | 154:37f96f9d4de2 | 131 | void rtc_free(void) |
<> | 154:37f96f9d4de2 | 132 | { |
AnnaBridge | 187:0387e8f68319 | 133 | /* RTC clock can not be reset */ |
<> | 154:37f96f9d4de2 | 134 | } |
<> | 154:37f96f9d4de2 | 135 | |
<> | 160:d5399cc887bb | 136 | |
<> | 160:d5399cc887bb | 137 | /* |
<> | 160:d5399cc887bb | 138 | Information about STM32F0, STM32F2, STM32F3, STM32F4, STM32F7, STM32L0, STM32L1, STM32L4: |
<> | 160:d5399cc887bb | 139 | BCD format is used to store the date in the RTC. The year is store on 2 * 4 bits. |
<> | 160:d5399cc887bb | 140 | Because the first year is reserved to see if the RTC is init, the supposed range is 01-99. |
<> | 160:d5399cc887bb | 141 | 1st point is to cover the standard range from 1970 to 2038 (limited by the 32 bits of time_t). |
<> | 160:d5399cc887bb | 142 | 2nd point is to keep the year 1970 and the leap years synchronized. |
<> | 160:d5399cc887bb | 143 | |
<> | 160:d5399cc887bb | 144 | So by moving it 68 years forward from 1970, it become 1969-2067 which include 1970-2038. |
<> | 160:d5399cc887bb | 145 | 68 is also a multiple of 4 so it let the leap year synchronized. |
<> | 160:d5399cc887bb | 146 | |
<> | 160:d5399cc887bb | 147 | Information about STM32F1: |
AnnaBridge | 182:a56a73fd2a6f | 148 | 32bit register is used (no BCD format) for the seconds. |
AnnaBridge | 182:a56a73fd2a6f | 149 | For date, there is no specific register, only a software structure. |
<> | 160:d5399cc887bb | 150 | It is then not a problem to not use shifts. |
<> | 160:d5399cc887bb | 151 | */ |
AnnaBridge | 187:0387e8f68319 | 152 | #if TARGET_STM32F1 |
<> | 154:37f96f9d4de2 | 153 | time_t rtc_read(void) |
<> | 154:37f96f9d4de2 | 154 | { |
AnnaBridge | 176:447f873cad2f | 155 | RTC_DateTypeDef dateStruct = {0}; |
AnnaBridge | 176:447f873cad2f | 156 | RTC_TimeTypeDef timeStruct = {0}; |
<> | 154:37f96f9d4de2 | 157 | struct tm timeinfo; |
<> | 154:37f96f9d4de2 | 158 | |
<> | 154:37f96f9d4de2 | 159 | RtcHandle.Instance = RTC; |
<> | 154:37f96f9d4de2 | 160 | |
<> | 154:37f96f9d4de2 | 161 | // Read actual date and time |
<> | 154:37f96f9d4de2 | 162 | // Warning: the time must be read first! |
<> | 160:d5399cc887bb | 163 | HAL_RTC_GetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN); |
<> | 160:d5399cc887bb | 164 | HAL_RTC_GetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN); |
<> | 154:37f96f9d4de2 | 165 | |
AnnaBridge | 182:a56a73fd2a6f | 166 | /* date information is null before first write procedure */ |
AnnaBridge | 182:a56a73fd2a6f | 167 | /* set 01/01/1970 as default values */ |
AnnaBridge | 182:a56a73fd2a6f | 168 | if (dateStruct.Year == 0) { |
AnnaBridge | 182:a56a73fd2a6f | 169 | dateStruct.Year = 2 ; |
AnnaBridge | 182:a56a73fd2a6f | 170 | dateStruct.Month = 1 ; |
AnnaBridge | 182:a56a73fd2a6f | 171 | dateStruct.Date = 1 ; |
AnnaBridge | 182:a56a73fd2a6f | 172 | } |
AnnaBridge | 182:a56a73fd2a6f | 173 | |
<> | 154:37f96f9d4de2 | 174 | // Setup a tm structure based on the RTC |
AnnaBridge | 182:a56a73fd2a6f | 175 | /* tm_wday information is ignored by _rtc_maketime */ |
AnnaBridge | 182:a56a73fd2a6f | 176 | /* tm_isdst information is ignored by _rtc_maketime */ |
<> | 154:37f96f9d4de2 | 177 | timeinfo.tm_mon = dateStruct.Month - 1; |
<> | 154:37f96f9d4de2 | 178 | timeinfo.tm_mday = dateStruct.Date; |
<> | 154:37f96f9d4de2 | 179 | timeinfo.tm_year = dateStruct.Year + 68; |
<> | 154:37f96f9d4de2 | 180 | timeinfo.tm_hour = timeStruct.Hours; |
<> | 154:37f96f9d4de2 | 181 | timeinfo.tm_min = timeStruct.Minutes; |
<> | 154:37f96f9d4de2 | 182 | timeinfo.tm_sec = timeStruct.Seconds; |
<> | 154:37f96f9d4de2 | 183 | |
<> | 154:37f96f9d4de2 | 184 | // Convert to timestamp |
AnnaBridge | 184:08ed48f1de7f | 185 | time_t t; |
AnnaBridge | 184:08ed48f1de7f | 186 | if (_rtc_maketime(&timeinfo, &t, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) { |
AnnaBridge | 184:08ed48f1de7f | 187 | return 0; |
AnnaBridge | 184:08ed48f1de7f | 188 | } |
<> | 154:37f96f9d4de2 | 189 | |
<> | 154:37f96f9d4de2 | 190 | return t; |
<> | 154:37f96f9d4de2 | 191 | } |
<> | 154:37f96f9d4de2 | 192 | |
AnnaBridge | 187:0387e8f68319 | 193 | #else /* TARGET_STM32F1 */ |
AnnaBridge | 187:0387e8f68319 | 194 | |
AnnaBridge | 187:0387e8f68319 | 195 | time_t rtc_read(void) |
AnnaBridge | 187:0387e8f68319 | 196 | { |
AnnaBridge | 187:0387e8f68319 | 197 | struct tm timeinfo; |
AnnaBridge | 187:0387e8f68319 | 198 | |
AnnaBridge | 187:0387e8f68319 | 199 | /* 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 | 200 | uint32_t Read_time = RTC->TR & RTC_TR_RESERVED_MASK; |
AnnaBridge | 187:0387e8f68319 | 201 | uint32_t Read_date = RTC->DR & RTC_DR_RESERVED_MASK; |
AnnaBridge | 187:0387e8f68319 | 202 | |
AnnaBridge | 187:0387e8f68319 | 203 | while ((Read_time != (RTC->TR & RTC_TR_RESERVED_MASK)) || (Read_date != (RTC->DR & RTC_DR_RESERVED_MASK))) { |
AnnaBridge | 187:0387e8f68319 | 204 | Read_time = RTC->TR & RTC_TR_RESERVED_MASK; |
AnnaBridge | 187:0387e8f68319 | 205 | Read_date = RTC->DR & RTC_DR_RESERVED_MASK; |
AnnaBridge | 187:0387e8f68319 | 206 | } |
AnnaBridge | 187:0387e8f68319 | 207 | |
AnnaBridge | 187:0387e8f68319 | 208 | /* Setup a tm structure based on the RTC |
AnnaBridge | 187:0387e8f68319 | 209 | struct tm : |
AnnaBridge | 187:0387e8f68319 | 210 | tm_sec seconds after the minute 0-61 |
AnnaBridge | 187:0387e8f68319 | 211 | tm_min minutes after the hour 0-59 |
AnnaBridge | 187:0387e8f68319 | 212 | tm_hour hours since midnight 0-23 |
AnnaBridge | 187:0387e8f68319 | 213 | tm_mday day of the month 1-31 |
AnnaBridge | 187:0387e8f68319 | 214 | tm_mon months since January 0-11 |
AnnaBridge | 187:0387e8f68319 | 215 | tm_year years since 1900 |
AnnaBridge | 187:0387e8f68319 | 216 | tm_yday information is ignored by _rtc_maketime |
AnnaBridge | 187:0387e8f68319 | 217 | tm_wday information is ignored by _rtc_maketime |
AnnaBridge | 187:0387e8f68319 | 218 | tm_isdst information is ignored by _rtc_maketime |
AnnaBridge | 187:0387e8f68319 | 219 | */ |
AnnaBridge | 187:0387e8f68319 | 220 | timeinfo.tm_mday = RTC_Bcd2ToByte((uint8_t)(Read_date & (RTC_DR_DT | RTC_DR_DU))); |
AnnaBridge | 187:0387e8f68319 | 221 | timeinfo.tm_mon = RTC_Bcd2ToByte((uint8_t)((Read_date & (RTC_DR_MT | RTC_DR_MU)) >> 8)) - 1; |
AnnaBridge | 187:0387e8f68319 | 222 | timeinfo.tm_year = RTC_Bcd2ToByte((uint8_t)((Read_date & (RTC_DR_YT | RTC_DR_YU)) >> 16)) + 68; |
AnnaBridge | 187:0387e8f68319 | 223 | timeinfo.tm_hour = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_HT | RTC_TR_HU)) >> 16)); |
AnnaBridge | 187:0387e8f68319 | 224 | timeinfo.tm_min = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_MNT | RTC_TR_MNU)) >> 8)); |
AnnaBridge | 187:0387e8f68319 | 225 | timeinfo.tm_sec = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_ST | RTC_TR_SU)) >> 0)); |
AnnaBridge | 187:0387e8f68319 | 226 | |
AnnaBridge | 187:0387e8f68319 | 227 | // Convert to timestamp |
AnnaBridge | 187:0387e8f68319 | 228 | time_t t; |
AnnaBridge | 187:0387e8f68319 | 229 | if (_rtc_maketime(&timeinfo, &t, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) { |
AnnaBridge | 187:0387e8f68319 | 230 | return 0; |
AnnaBridge | 187:0387e8f68319 | 231 | } |
AnnaBridge | 187:0387e8f68319 | 232 | |
AnnaBridge | 187:0387e8f68319 | 233 | return t; |
AnnaBridge | 187:0387e8f68319 | 234 | } |
AnnaBridge | 187:0387e8f68319 | 235 | |
AnnaBridge | 187:0387e8f68319 | 236 | #endif /* TARGET_STM32F1 */ |
AnnaBridge | 187:0387e8f68319 | 237 | |
<> | 154:37f96f9d4de2 | 238 | void rtc_write(time_t t) |
<> | 154:37f96f9d4de2 | 239 | { |
AnnaBridge | 176:447f873cad2f | 240 | RTC_DateTypeDef dateStruct = {0}; |
AnnaBridge | 176:447f873cad2f | 241 | RTC_TimeTypeDef timeStruct = {0}; |
<> | 154:37f96f9d4de2 | 242 | |
AnnaBridge | 187:0387e8f68319 | 243 | core_util_critical_section_enter(); |
<> | 154:37f96f9d4de2 | 244 | RtcHandle.Instance = RTC; |
<> | 154:37f96f9d4de2 | 245 | |
<> | 154:37f96f9d4de2 | 246 | // Convert the time into a tm |
AnnaBridge | 167:e84263d55307 | 247 | struct tm timeinfo; |
AnnaBridge | 184:08ed48f1de7f | 248 | if (_rtc_localtime(t, &timeinfo, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) { |
AnnaBridge | 167:e84263d55307 | 249 | return; |
AnnaBridge | 167:e84263d55307 | 250 | } |
<> | 154:37f96f9d4de2 | 251 | |
<> | 154:37f96f9d4de2 | 252 | // Fill RTC structures |
AnnaBridge | 187:0387e8f68319 | 253 | if (timeinfo.tm_wday == 0) { /* Sunday specific case */ |
AnnaBridge | 187:0387e8f68319 | 254 | dateStruct.WeekDay = RTC_WEEKDAY_SUNDAY; |
<> | 160:d5399cc887bb | 255 | } else { |
AnnaBridge | 167:e84263d55307 | 256 | dateStruct.WeekDay = timeinfo.tm_wday; |
<> | 160:d5399cc887bb | 257 | } |
AnnaBridge | 167:e84263d55307 | 258 | dateStruct.Month = timeinfo.tm_mon + 1; |
AnnaBridge | 167:e84263d55307 | 259 | dateStruct.Date = timeinfo.tm_mday; |
AnnaBridge | 167:e84263d55307 | 260 | dateStruct.Year = timeinfo.tm_year - 68; |
AnnaBridge | 167:e84263d55307 | 261 | timeStruct.Hours = timeinfo.tm_hour; |
AnnaBridge | 167:e84263d55307 | 262 | timeStruct.Minutes = timeinfo.tm_min; |
AnnaBridge | 167:e84263d55307 | 263 | timeStruct.Seconds = timeinfo.tm_sec; |
<> | 154:37f96f9d4de2 | 264 | |
<> | 154:37f96f9d4de2 | 265 | #if !(TARGET_STM32F1) |
<> | 154:37f96f9d4de2 | 266 | timeStruct.TimeFormat = RTC_HOURFORMAT_24; |
<> | 154:37f96f9d4de2 | 267 | timeStruct.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; |
<> | 154:37f96f9d4de2 | 268 | timeStruct.StoreOperation = RTC_STOREOPERATION_RESET; |
<> | 154:37f96f9d4de2 | 269 | #endif /* TARGET_STM32F1 */ |
<> | 154:37f96f9d4de2 | 270 | |
AnnaBridge | 187:0387e8f68319 | 271 | #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM |
AnnaBridge | 187:0387e8f68319 | 272 | /* Need to update LP_continuous_time value before new RTC time */ |
AnnaBridge | 187:0387e8f68319 | 273 | rtc_read_lp(); |
AnnaBridge | 187:0387e8f68319 | 274 | |
AnnaBridge | 187:0387e8f68319 | 275 | /* LP_last_RTC_time value is updated with the new RTC time */ |
AnnaBridge | 187:0387e8f68319 | 276 | LP_last_RTC_time = timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60; |
AnnaBridge | 187:0387e8f68319 | 277 | |
AnnaBridge | 187:0387e8f68319 | 278 | /* Save current SSR */ |
AnnaBridge | 187:0387e8f68319 | 279 | uint32_t Read_SubSeconds = (uint32_t)(RTC->SSR); |
AnnaBridge | 187:0387e8f68319 | 280 | #endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ |
AnnaBridge | 187:0387e8f68319 | 281 | |
<> | 154:37f96f9d4de2 | 282 | // Change the RTC current date/time |
Anna Bridge |
180:96ed750bd169 | 283 | if (HAL_RTC_SetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN) != HAL_OK) { |
Anna Bridge |
180:96ed750bd169 | 284 | error("HAL_RTC_SetDate error\n"); |
Anna Bridge |
180:96ed750bd169 | 285 | } |
Anna Bridge |
180:96ed750bd169 | 286 | if (HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN) != HAL_OK) { |
Anna Bridge |
180:96ed750bd169 | 287 | error("HAL_RTC_SetTime error\n"); |
Anna Bridge |
180:96ed750bd169 | 288 | } |
AnnaBridge | 187:0387e8f68319 | 289 | |
AnnaBridge | 187:0387e8f68319 | 290 | #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM |
AnnaBridge | 187:0387e8f68319 | 291 | while (Read_SubSeconds != (RTC->SSR)) { |
AnnaBridge | 187:0387e8f68319 | 292 | } |
AnnaBridge | 187:0387e8f68319 | 293 | #endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ |
AnnaBridge | 187:0387e8f68319 | 294 | |
AnnaBridge | 187:0387e8f68319 | 295 | core_util_critical_section_exit(); |
<> | 154:37f96f9d4de2 | 296 | } |
<> | 154:37f96f9d4de2 | 297 | |
<> | 154:37f96f9d4de2 | 298 | int rtc_isenabled(void) |
<> | 154:37f96f9d4de2 | 299 | { |
<> | 160:d5399cc887bb | 300 | #if !(TARGET_STM32F1) |
AnnaBridge | 187:0387e8f68319 | 301 | return ((RTC->ISR & RTC_ISR_INITS) == RTC_ISR_INITS); |
<> | 160:d5399cc887bb | 302 | #else /* TARGET_STM32F1 */ |
<> | 160:d5399cc887bb | 303 | return ((RTC->CRL & RTC_CRL_RSF) == RTC_CRL_RSF); |
<> | 160:d5399cc887bb | 304 | #endif /* TARGET_STM32F1 */ |
<> | 154:37f96f9d4de2 | 305 | } |
<> | 154:37f96f9d4de2 | 306 | |
Anna Bridge |
180:96ed750bd169 | 307 | |
Anna Bridge |
186:707f6e361f3e | 308 | #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM |
Anna Bridge |
186:707f6e361f3e | 309 | |
Anna Bridge |
186:707f6e361f3e | 310 | static void RTC_IRQHandler(void); |
Anna Bridge |
186:707f6e361f3e | 311 | static void (*irq_handler)(void); |
Anna Bridge |
186:707f6e361f3e | 312 | |
Anna Bridge |
186:707f6e361f3e | 313 | volatile uint8_t lp_Fired = 0; |
<> | 154:37f96f9d4de2 | 314 | |
<> | 154:37f96f9d4de2 | 315 | static void RTC_IRQHandler(void) |
<> | 154:37f96f9d4de2 | 316 | { |
AnnaBridge | 176:447f873cad2f | 317 | /* Update HAL state */ |
Anna Bridge |
180:96ed750bd169 | 318 | RtcHandle.Instance = RTC; |
AnnaBridge | 187:0387e8f68319 | 319 | if (__HAL_RTC_WAKEUPTIMER_GET_IT(&RtcHandle, RTC_IT_WUT)) { |
Anna Bridge |
186:707f6e361f3e | 320 | /* Get the status of the Interrupt */ |
AnnaBridge | 187:0387e8f68319 | 321 | if ((uint32_t)(RTC->CR & RTC_IT_WUT) != (uint32_t)RESET) { |
Anna Bridge |
186:707f6e361f3e | 322 | /* Clear the WAKEUPTIMER interrupt pending bit */ |
Anna Bridge |
186:707f6e361f3e | 323 | __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF); |
Anna Bridge |
186:707f6e361f3e | 324 | |
Anna Bridge |
186:707f6e361f3e | 325 | lp_Fired = 0; |
Anna Bridge |
186:707f6e361f3e | 326 | if (irq_handler) { |
Anna Bridge |
186:707f6e361f3e | 327 | irq_handler(); |
Anna Bridge |
186:707f6e361f3e | 328 | } |
Anna Bridge |
186:707f6e361f3e | 329 | } |
<> | 154:37f96f9d4de2 | 330 | } |
Anna Bridge |
186:707f6e361f3e | 331 | |
Anna Bridge |
186:707f6e361f3e | 332 | if (lp_Fired) { |
Anna Bridge |
186:707f6e361f3e | 333 | lp_Fired = 0; |
Anna Bridge |
186:707f6e361f3e | 334 | if (irq_handler) { |
Anna Bridge |
186:707f6e361f3e | 335 | irq_handler(); |
Anna Bridge |
186:707f6e361f3e | 336 | } |
Anna Bridge |
186:707f6e361f3e | 337 | } |
Anna Bridge |
186:707f6e361f3e | 338 | |
Anna Bridge |
186:707f6e361f3e | 339 | __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); |
<> | 154:37f96f9d4de2 | 340 | } |
<> | 154:37f96f9d4de2 | 341 | |
Anna Bridge |
186:707f6e361f3e | 342 | uint32_t rtc_read_lp(void) |
<> | 154:37f96f9d4de2 | 343 | { |
AnnaBridge | 187:0387e8f68319 | 344 | struct tm timeinfo; |
AnnaBridge | 181:57724642e740 | 345 | |
AnnaBridge | 187:0387e8f68319 | 346 | /* 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 | 347 | /* We don't have to read date as we bypass shadow registers */ |
AnnaBridge | 187:0387e8f68319 | 348 | uint32_t Read_SecondFraction = (uint32_t)(RTC->PRER & RTC_PRER_PREDIV_S); |
AnnaBridge | 187:0387e8f68319 | 349 | uint32_t Read_time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK); |
AnnaBridge | 187:0387e8f68319 | 350 | uint32_t Read_SubSeconds = (uint32_t)(RTC->SSR); |
AnnaBridge | 181:57724642e740 | 351 | |
AnnaBridge | 187:0387e8f68319 | 352 | while ((Read_time != (RTC->TR & RTC_TR_RESERVED_MASK)) || (Read_SubSeconds != (RTC->SSR))) { |
AnnaBridge | 187:0387e8f68319 | 353 | Read_time = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK); |
AnnaBridge | 187:0387e8f68319 | 354 | Read_SubSeconds = (uint32_t)(RTC->SSR); |
AnnaBridge | 187:0387e8f68319 | 355 | } |
AnnaBridge | 181:57724642e740 | 356 | |
AnnaBridge | 187:0387e8f68319 | 357 | timeinfo.tm_hour = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_HT | RTC_TR_HU)) >> 16)); |
AnnaBridge | 187:0387e8f68319 | 358 | timeinfo.tm_min = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_MNT | RTC_TR_MNU)) >> 8)); |
AnnaBridge | 187:0387e8f68319 | 359 | timeinfo.tm_sec = RTC_Bcd2ToByte((uint8_t)((Read_time & (RTC_TR_ST | RTC_TR_SU)) >> 0)); |
AnnaBridge | 187:0387e8f68319 | 360 | |
AnnaBridge | 187:0387e8f68319 | 361 | uint32_t RTC_time_s = timeinfo.tm_sec + timeinfo.tm_min * 60 + timeinfo.tm_hour * 60 * 60; // Max 0x0001-517F => * 8191 + 8191 = 0x2A2E-AE80 |
AnnaBridge | 181:57724642e740 | 362 | |
Anna Bridge |
186:707f6e361f3e | 363 | if (LP_last_RTC_time <= RTC_time_s) { |
Anna Bridge |
186:707f6e361f3e | 364 | LP_continuous_time += (RTC_time_s - LP_last_RTC_time); |
Anna Bridge |
186:707f6e361f3e | 365 | } else { |
AnnaBridge | 187:0387e8f68319 | 366 | /* Add 24h */ |
Anna Bridge |
186:707f6e361f3e | 367 | LP_continuous_time += (24 * 60 * 60 + RTC_time_s - LP_last_RTC_time); |
Anna Bridge |
186:707f6e361f3e | 368 | } |
Anna Bridge |
186:707f6e361f3e | 369 | LP_last_RTC_time = RTC_time_s; |
Anna Bridge |
186:707f6e361f3e | 370 | |
AnnaBridge | 187:0387e8f68319 | 371 | return LP_continuous_time * PREDIV_S_VALUE + Read_SecondFraction - Read_SubSeconds; |
<> | 154:37f96f9d4de2 | 372 | } |
<> | 154:37f96f9d4de2 | 373 | |
Anna Bridge |
186:707f6e361f3e | 374 | void rtc_set_wake_up_timer(timestamp_t timestamp) |
<> | 154:37f96f9d4de2 | 375 | { |
Anna Bridge |
186:707f6e361f3e | 376 | uint32_t WakeUpCounter; |
Anna Bridge |
186:707f6e361f3e | 377 | uint32_t current_lp_time; |
AnnaBridge | 184:08ed48f1de7f | 378 | |
Anna Bridge |
186:707f6e361f3e | 379 | current_lp_time = rtc_read_lp(); |
AnnaBridge | 184:08ed48f1de7f | 380 | |
Anna Bridge |
186:707f6e361f3e | 381 | if (timestamp < current_lp_time) { |
Anna Bridge |
186:707f6e361f3e | 382 | WakeUpCounter = 0xFFFFFFFF - current_lp_time + timestamp; |
AnnaBridge | 184:08ed48f1de7f | 383 | } else { |
Anna Bridge |
186:707f6e361f3e | 384 | WakeUpCounter = timestamp - current_lp_time; |
Anna Bridge |
186:707f6e361f3e | 385 | } |
Anna Bridge |
186:707f6e361f3e | 386 | |
Anna Bridge |
186:707f6e361f3e | 387 | if (WakeUpCounter > 0xFFFF) { |
Anna Bridge |
186:707f6e361f3e | 388 | WakeUpCounter = 0xFFFF; |
Anna Bridge |
180:96ed750bd169 | 389 | } |
Anna Bridge |
180:96ed750bd169 | 390 | |
Anna Bridge |
180:96ed750bd169 | 391 | RtcHandle.Instance = RTC; |
Anna Bridge |
186:707f6e361f3e | 392 | if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, WakeUpCounter, RTC_WAKEUPCLOCK_RTCCLK_DIV4) != HAL_OK) { |
AnnaBridge | 184:08ed48f1de7f | 393 | error("rtc_set_wake_up_timer init error\n"); |
<> | 154:37f96f9d4de2 | 394 | } |
Anna Bridge |
186:707f6e361f3e | 395 | |
Anna Bridge |
186:707f6e361f3e | 396 | NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); |
Anna Bridge |
186:707f6e361f3e | 397 | irq_handler = (void (*)(void))lp_ticker_irq_handler; |
Anna Bridge |
186:707f6e361f3e | 398 | NVIC_EnableIRQ(RTC_WKUP_IRQn); |
Anna Bridge |
186:707f6e361f3e | 399 | } |
Anna Bridge |
186:707f6e361f3e | 400 | |
Anna Bridge |
186:707f6e361f3e | 401 | void rtc_fire_interrupt(void) |
Anna Bridge |
186:707f6e361f3e | 402 | { |
Anna Bridge |
186:707f6e361f3e | 403 | lp_Fired = 1; |
Anna Bridge |
186:707f6e361f3e | 404 | NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); |
Anna Bridge |
186:707f6e361f3e | 405 | irq_handler = (void (*)(void))lp_ticker_irq_handler; |
Anna Bridge |
186:707f6e361f3e | 406 | NVIC_SetPendingIRQ(RTC_WKUP_IRQn); |
Anna Bridge |
186:707f6e361f3e | 407 | NVIC_EnableIRQ(RTC_WKUP_IRQn); |
<> | 154:37f96f9d4de2 | 408 | } |
<> | 154:37f96f9d4de2 | 409 | |
<> | 154:37f96f9d4de2 | 410 | void rtc_deactivate_wake_up_timer(void) |
<> | 154:37f96f9d4de2 | 411 | { |
Anna Bridge |
180:96ed750bd169 | 412 | RtcHandle.Instance = RTC; |
AnnaBridge | 187:0387e8f68319 | 413 | __HAL_RTC_WRITEPROTECTION_DISABLE(&RtcHandle); |
AnnaBridge | 187:0387e8f68319 | 414 | __HAL_RTC_WAKEUPTIMER_DISABLE(&RtcHandle); |
AnnaBridge | 187:0387e8f68319 | 415 | __HAL_RTC_WAKEUPTIMER_DISABLE_IT(&RtcHandle, RTC_IT_WUT); |
AnnaBridge | 187:0387e8f68319 | 416 | __HAL_RTC_WRITEPROTECTION_ENABLE(&RtcHandle); |
AnnaBridge | 187:0387e8f68319 | 417 | NVIC_DisableIRQ(RTC_WKUP_IRQn); |
<> | 154:37f96f9d4de2 | 418 | } |
<> | 154:37f96f9d4de2 | 419 | |
Anna Bridge |
186:707f6e361f3e | 420 | #endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ |
<> | 154:37f96f9d4de2 | 421 | |
<> | 154:37f96f9d4de2 | 422 | #endif /* DEVICE_RTC */ |