Knight KE
/
Game_Master
游戏王对战板,目前code还是空的
mbed-os/targets/TARGET_STM/rtc_api.c@0:9b3d4731edbb, 2018-06-21 (annotated)
- Committer:
- WFKnight
- Date:
- Thu Jun 21 13:51:43 2018 +0000
- Revision:
- 0:9b3d4731edbb
UART, RTOS, LED
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WFKnight | 0:9b3d4731edbb | 1 | /* mbed Microcontroller Library |
WFKnight | 0:9b3d4731edbb | 2 | ******************************************************************************* |
WFKnight | 0:9b3d4731edbb | 3 | * Copyright (c) 2018, STMicroelectronics |
WFKnight | 0:9b3d4731edbb | 4 | * All rights reserved. |
WFKnight | 0:9b3d4731edbb | 5 | * |
WFKnight | 0:9b3d4731edbb | 6 | * Redistribution and use in source and binary forms, with or without |
WFKnight | 0:9b3d4731edbb | 7 | * modification, are permitted provided that the following conditions are met: |
WFKnight | 0:9b3d4731edbb | 8 | * |
WFKnight | 0:9b3d4731edbb | 9 | * 1. Redistributions of source code must retain the above copyright notice, |
WFKnight | 0:9b3d4731edbb | 10 | * this list of conditions and the following disclaimer. |
WFKnight | 0:9b3d4731edbb | 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
WFKnight | 0:9b3d4731edbb | 12 | * this list of conditions and the following disclaimer in the documentation |
WFKnight | 0:9b3d4731edbb | 13 | * and/or other materials provided with the distribution. |
WFKnight | 0:9b3d4731edbb | 14 | * 3. Neither the name of STMicroelectronics nor the names of its contributors |
WFKnight | 0:9b3d4731edbb | 15 | * may be used to endorse or promote products derived from this software |
WFKnight | 0:9b3d4731edbb | 16 | * without specific prior written permission. |
WFKnight | 0:9b3d4731edbb | 17 | * |
WFKnight | 0:9b3d4731edbb | 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
WFKnight | 0:9b3d4731edbb | 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
WFKnight | 0:9b3d4731edbb | 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
WFKnight | 0:9b3d4731edbb | 21 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
WFKnight | 0:9b3d4731edbb | 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
WFKnight | 0:9b3d4731edbb | 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
WFKnight | 0:9b3d4731edbb | 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
WFKnight | 0:9b3d4731edbb | 25 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
WFKnight | 0:9b3d4731edbb | 26 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
WFKnight | 0:9b3d4731edbb | 27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
WFKnight | 0:9b3d4731edbb | 28 | ******************************************************************************* |
WFKnight | 0:9b3d4731edbb | 29 | */ |
WFKnight | 0:9b3d4731edbb | 30 | |
WFKnight | 0:9b3d4731edbb | 31 | #if DEVICE_RTC |
WFKnight | 0:9b3d4731edbb | 32 | |
WFKnight | 0:9b3d4731edbb | 33 | #include "rtc_api_hal.h" |
WFKnight | 0:9b3d4731edbb | 34 | #include "mbed_mktime.h" |
WFKnight | 0:9b3d4731edbb | 35 | #include "mbed_error.h" |
WFKnight | 0:9b3d4731edbb | 36 | |
WFKnight | 0:9b3d4731edbb | 37 | static RTC_HandleTypeDef RtcHandle; |
WFKnight | 0:9b3d4731edbb | 38 | |
WFKnight | 0:9b3d4731edbb | 39 | void rtc_init(void) |
WFKnight | 0:9b3d4731edbb | 40 | { |
WFKnight | 0:9b3d4731edbb | 41 | RCC_OscInitTypeDef RCC_OscInitStruct = {0}; |
WFKnight | 0:9b3d4731edbb | 42 | RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; |
WFKnight | 0:9b3d4731edbb | 43 | |
WFKnight | 0:9b3d4731edbb | 44 | // Enable access to Backup domain |
WFKnight | 0:9b3d4731edbb | 45 | __HAL_RCC_PWR_CLK_ENABLE(); |
WFKnight | 0:9b3d4731edbb | 46 | HAL_PWR_EnableBkUpAccess(); |
WFKnight | 0:9b3d4731edbb | 47 | |
WFKnight | 0:9b3d4731edbb | 48 | #if DEVICE_LPTICKER |
WFKnight | 0:9b3d4731edbb | 49 | if ( (rtc_isenabled()) && ((RTC->PRER & RTC_PRER_PREDIV_S) == PREDIV_S_VALUE) ) { |
WFKnight | 0:9b3d4731edbb | 50 | #else /* DEVICE_LPTICKER */ |
WFKnight | 0:9b3d4731edbb | 51 | if (rtc_isenabled()) { |
WFKnight | 0:9b3d4731edbb | 52 | #endif /* DEVICE_LPTICKER */ |
WFKnight | 0:9b3d4731edbb | 53 | return; |
WFKnight | 0:9b3d4731edbb | 54 | } |
WFKnight | 0:9b3d4731edbb | 55 | |
WFKnight | 0:9b3d4731edbb | 56 | #if MBED_CONF_TARGET_LSE_AVAILABLE |
WFKnight | 0:9b3d4731edbb | 57 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE; |
WFKnight | 0:9b3d4731edbb | 58 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! |
WFKnight | 0:9b3d4731edbb | 59 | RCC_OscInitStruct.LSEState = RCC_LSE_ON; |
WFKnight | 0:9b3d4731edbb | 60 | |
WFKnight | 0:9b3d4731edbb | 61 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { |
WFKnight | 0:9b3d4731edbb | 62 | error("Cannot initialize RTC with LSE\n"); |
WFKnight | 0:9b3d4731edbb | 63 | } |
WFKnight | 0:9b3d4731edbb | 64 | |
WFKnight | 0:9b3d4731edbb | 65 | __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSE); |
WFKnight | 0:9b3d4731edbb | 66 | __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSE); |
WFKnight | 0:9b3d4731edbb | 67 | |
WFKnight | 0:9b3d4731edbb | 68 | PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; |
WFKnight | 0:9b3d4731edbb | 69 | PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; |
WFKnight | 0:9b3d4731edbb | 70 | if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { |
WFKnight | 0:9b3d4731edbb | 71 | error("PeriphClkInitStruct RTC failed with LSE\n"); |
WFKnight | 0:9b3d4731edbb | 72 | } |
WFKnight | 0:9b3d4731edbb | 73 | #else /* MBED_CONF_TARGET_LSE_AVAILABLE */ |
WFKnight | 0:9b3d4731edbb | 74 | // Reset Backup domain |
WFKnight | 0:9b3d4731edbb | 75 | __HAL_RCC_BACKUPRESET_FORCE(); |
WFKnight | 0:9b3d4731edbb | 76 | __HAL_RCC_BACKUPRESET_RELEASE(); |
WFKnight | 0:9b3d4731edbb | 77 | |
WFKnight | 0:9b3d4731edbb | 78 | // Enable LSI clock |
WFKnight | 0:9b3d4731edbb | 79 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; |
WFKnight | 0:9b3d4731edbb | 80 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Mandatory, otherwise the PLL is reconfigured! |
WFKnight | 0:9b3d4731edbb | 81 | RCC_OscInitStruct.LSIState = RCC_LSI_ON; |
WFKnight | 0:9b3d4731edbb | 82 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { |
WFKnight | 0:9b3d4731edbb | 83 | error("Cannot initialize RTC with LSI\n"); |
WFKnight | 0:9b3d4731edbb | 84 | } |
WFKnight | 0:9b3d4731edbb | 85 | |
WFKnight | 0:9b3d4731edbb | 86 | __HAL_RCC_RTC_CLKPRESCALER(RCC_RTCCLKSOURCE_LSI); |
WFKnight | 0:9b3d4731edbb | 87 | __HAL_RCC_RTC_CONFIG(RCC_RTCCLKSOURCE_LSI); |
WFKnight | 0:9b3d4731edbb | 88 | |
WFKnight | 0:9b3d4731edbb | 89 | PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC; |
WFKnight | 0:9b3d4731edbb | 90 | PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; |
WFKnight | 0:9b3d4731edbb | 91 | if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { |
WFKnight | 0:9b3d4731edbb | 92 | error("PeriphClkInitStruct RTC failed with LSI\n"); |
WFKnight | 0:9b3d4731edbb | 93 | } |
WFKnight | 0:9b3d4731edbb | 94 | #endif /* MBED_CONF_TARGET_LSE_AVAILABLE */ |
WFKnight | 0:9b3d4731edbb | 95 | |
WFKnight | 0:9b3d4731edbb | 96 | // Enable RTC |
WFKnight | 0:9b3d4731edbb | 97 | __HAL_RCC_RTC_ENABLE(); |
WFKnight | 0:9b3d4731edbb | 98 | |
WFKnight | 0:9b3d4731edbb | 99 | RtcHandle.Instance = RTC; |
WFKnight | 0:9b3d4731edbb | 100 | RtcHandle.State = HAL_RTC_STATE_RESET; |
WFKnight | 0:9b3d4731edbb | 101 | |
WFKnight | 0:9b3d4731edbb | 102 | #if TARGET_STM32F1 |
WFKnight | 0:9b3d4731edbb | 103 | RtcHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND; |
WFKnight | 0:9b3d4731edbb | 104 | #else /* TARGET_STM32F1 */ |
WFKnight | 0:9b3d4731edbb | 105 | RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24; |
WFKnight | 0:9b3d4731edbb | 106 | RtcHandle.Init.AsynchPrediv = PREDIV_A_VALUE; |
WFKnight | 0:9b3d4731edbb | 107 | RtcHandle.Init.SynchPrediv = PREDIV_S_VALUE; |
WFKnight | 0:9b3d4731edbb | 108 | RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE; |
WFKnight | 0:9b3d4731edbb | 109 | RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; |
WFKnight | 0:9b3d4731edbb | 110 | RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; |
WFKnight | 0:9b3d4731edbb | 111 | #endif /* TARGET_STM32F1 */ |
WFKnight | 0:9b3d4731edbb | 112 | |
WFKnight | 0:9b3d4731edbb | 113 | if (HAL_RTC_Init(&RtcHandle) != HAL_OK) { |
WFKnight | 0:9b3d4731edbb | 114 | error("RTC initialization failed"); |
WFKnight | 0:9b3d4731edbb | 115 | } |
WFKnight | 0:9b3d4731edbb | 116 | |
WFKnight | 0:9b3d4731edbb | 117 | rtc_synchronize(); // Wait for RSF |
WFKnight | 0:9b3d4731edbb | 118 | |
WFKnight | 0:9b3d4731edbb | 119 | if (!rtc_isenabled()) { |
WFKnight | 0:9b3d4731edbb | 120 | rtc_write(0); |
WFKnight | 0:9b3d4731edbb | 121 | } |
WFKnight | 0:9b3d4731edbb | 122 | } |
WFKnight | 0:9b3d4731edbb | 123 | |
WFKnight | 0:9b3d4731edbb | 124 | void rtc_free(void) |
WFKnight | 0:9b3d4731edbb | 125 | { |
WFKnight | 0:9b3d4731edbb | 126 | // Disable access to Backup domain |
WFKnight | 0:9b3d4731edbb | 127 | HAL_PWR_DisableBkUpAccess(); |
WFKnight | 0:9b3d4731edbb | 128 | } |
WFKnight | 0:9b3d4731edbb | 129 | |
WFKnight | 0:9b3d4731edbb | 130 | /* |
WFKnight | 0:9b3d4731edbb | 131 | ST RTC_DateTypeDef structure |
WFKnight | 0:9b3d4731edbb | 132 | WeekDay 1=monday, 2=tuesday, ..., 7=sunday |
WFKnight | 0:9b3d4731edbb | 133 | Month 0x1=january, 0x2=february, ..., 0x12=december |
WFKnight | 0:9b3d4731edbb | 134 | Date day of the month 1-31 |
WFKnight | 0:9b3d4731edbb | 135 | Year year 0-99 |
WFKnight | 0:9b3d4731edbb | 136 | |
WFKnight | 0:9b3d4731edbb | 137 | ST RTC_TimeTypeDef structure |
WFKnight | 0:9b3d4731edbb | 138 | Hours 0-12 if the RTC_HourFormat_12 is selected during init |
WFKnight | 0:9b3d4731edbb | 139 | 0-23 if the RTC_HourFormat_24 is selected during init |
WFKnight | 0:9b3d4731edbb | 140 | Minutes 0-59 |
WFKnight | 0:9b3d4731edbb | 141 | Seconds 0-59 |
WFKnight | 0:9b3d4731edbb | 142 | TimeFormat RTC_HOURFORMAT12_AM/RTC_HOURFORMAT12_PM |
WFKnight | 0:9b3d4731edbb | 143 | SubSeconds time unit range between [0-1] Second with [1 Sec / SecondFraction +1] granularity |
WFKnight | 0:9b3d4731edbb | 144 | SecondFraction range or granularity of Sub Second register content corresponding to Synchronous pre-scaler factor value (PREDIV_S) |
WFKnight | 0:9b3d4731edbb | 145 | DayLightSaving RTC_DAYLIGHTSAVING_SUB1H/RTC_DAYLIGHTSAVING_ADD1H/RTC_DAYLIGHTSAVING_NONE |
WFKnight | 0:9b3d4731edbb | 146 | StoreOperation RTC_STOREOPERATION_RESET/RTC_STOREOPERATION_SET |
WFKnight | 0:9b3d4731edbb | 147 | |
WFKnight | 0:9b3d4731edbb | 148 | struct tm |
WFKnight | 0:9b3d4731edbb | 149 | tm_sec seconds after the minute 0-61 |
WFKnight | 0:9b3d4731edbb | 150 | tm_min minutes after the hour 0-59 |
WFKnight | 0:9b3d4731edbb | 151 | tm_hour hours since midnight 0-23 |
WFKnight | 0:9b3d4731edbb | 152 | tm_mday day of the month 1-31 |
WFKnight | 0:9b3d4731edbb | 153 | tm_mon months since January 0-11 |
WFKnight | 0:9b3d4731edbb | 154 | tm_year years since 1900 |
WFKnight | 0:9b3d4731edbb | 155 | tm_wday days since Sunday 0-6 |
WFKnight | 0:9b3d4731edbb | 156 | tm_yday days since January 1 0-365 |
WFKnight | 0:9b3d4731edbb | 157 | tm_isdst Daylight Saving Time flag |
WFKnight | 0:9b3d4731edbb | 158 | */ |
WFKnight | 0:9b3d4731edbb | 159 | |
WFKnight | 0:9b3d4731edbb | 160 | /* |
WFKnight | 0:9b3d4731edbb | 161 | Information about STM32F0, STM32F2, STM32F3, STM32F4, STM32F7, STM32L0, STM32L1, STM32L4: |
WFKnight | 0:9b3d4731edbb | 162 | BCD format is used to store the date in the RTC. The year is store on 2 * 4 bits. |
WFKnight | 0:9b3d4731edbb | 163 | Because the first year is reserved to see if the RTC is init, the supposed range is 01-99. |
WFKnight | 0:9b3d4731edbb | 164 | 1st point is to cover the standard range from 1970 to 2038 (limited by the 32 bits of time_t). |
WFKnight | 0:9b3d4731edbb | 165 | 2nd point is to keep the year 1970 and the leap years synchronized. |
WFKnight | 0:9b3d4731edbb | 166 | |
WFKnight | 0:9b3d4731edbb | 167 | So by moving it 68 years forward from 1970, it become 1969-2067 which include 1970-2038. |
WFKnight | 0:9b3d4731edbb | 168 | 68 is also a multiple of 4 so it let the leap year synchronized. |
WFKnight | 0:9b3d4731edbb | 169 | |
WFKnight | 0:9b3d4731edbb | 170 | Information about STM32F1: |
WFKnight | 0:9b3d4731edbb | 171 | 32bit register is used (no BCD format) for the seconds. |
WFKnight | 0:9b3d4731edbb | 172 | For date, there is no specific register, only a software structure. |
WFKnight | 0:9b3d4731edbb | 173 | It is then not a problem to not use shifts. |
WFKnight | 0:9b3d4731edbb | 174 | */ |
WFKnight | 0:9b3d4731edbb | 175 | |
WFKnight | 0:9b3d4731edbb | 176 | time_t rtc_read(void) |
WFKnight | 0:9b3d4731edbb | 177 | { |
WFKnight | 0:9b3d4731edbb | 178 | RTC_DateTypeDef dateStruct = {0}; |
WFKnight | 0:9b3d4731edbb | 179 | RTC_TimeTypeDef timeStruct = {0}; |
WFKnight | 0:9b3d4731edbb | 180 | struct tm timeinfo; |
WFKnight | 0:9b3d4731edbb | 181 | |
WFKnight | 0:9b3d4731edbb | 182 | RtcHandle.Instance = RTC; |
WFKnight | 0:9b3d4731edbb | 183 | |
WFKnight | 0:9b3d4731edbb | 184 | // Read actual date and time |
WFKnight | 0:9b3d4731edbb | 185 | // Warning: the time must be read first! |
WFKnight | 0:9b3d4731edbb | 186 | HAL_RTC_GetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN); |
WFKnight | 0:9b3d4731edbb | 187 | HAL_RTC_GetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN); |
WFKnight | 0:9b3d4731edbb | 188 | |
WFKnight | 0:9b3d4731edbb | 189 | #if TARGET_STM32F1 |
WFKnight | 0:9b3d4731edbb | 190 | /* date information is null before first write procedure */ |
WFKnight | 0:9b3d4731edbb | 191 | /* set 01/01/1970 as default values */ |
WFKnight | 0:9b3d4731edbb | 192 | if (dateStruct.Year == 0) { |
WFKnight | 0:9b3d4731edbb | 193 | dateStruct.Year = 2 ; |
WFKnight | 0:9b3d4731edbb | 194 | dateStruct.Month = 1 ; |
WFKnight | 0:9b3d4731edbb | 195 | dateStruct.Date = 1 ; |
WFKnight | 0:9b3d4731edbb | 196 | } |
WFKnight | 0:9b3d4731edbb | 197 | #endif |
WFKnight | 0:9b3d4731edbb | 198 | |
WFKnight | 0:9b3d4731edbb | 199 | // Setup a tm structure based on the RTC |
WFKnight | 0:9b3d4731edbb | 200 | /* tm_wday information is ignored by _rtc_maketime */ |
WFKnight | 0:9b3d4731edbb | 201 | /* tm_isdst information is ignored by _rtc_maketime */ |
WFKnight | 0:9b3d4731edbb | 202 | timeinfo.tm_mon = dateStruct.Month - 1; |
WFKnight | 0:9b3d4731edbb | 203 | timeinfo.tm_mday = dateStruct.Date; |
WFKnight | 0:9b3d4731edbb | 204 | timeinfo.tm_year = dateStruct.Year + 68; |
WFKnight | 0:9b3d4731edbb | 205 | timeinfo.tm_hour = timeStruct.Hours; |
WFKnight | 0:9b3d4731edbb | 206 | timeinfo.tm_min = timeStruct.Minutes; |
WFKnight | 0:9b3d4731edbb | 207 | timeinfo.tm_sec = timeStruct.Seconds; |
WFKnight | 0:9b3d4731edbb | 208 | |
WFKnight | 0:9b3d4731edbb | 209 | // Convert to timestamp |
WFKnight | 0:9b3d4731edbb | 210 | time_t t; |
WFKnight | 0:9b3d4731edbb | 211 | if (_rtc_maketime(&timeinfo, &t, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) { |
WFKnight | 0:9b3d4731edbb | 212 | return 0; |
WFKnight | 0:9b3d4731edbb | 213 | } |
WFKnight | 0:9b3d4731edbb | 214 | |
WFKnight | 0:9b3d4731edbb | 215 | return t; |
WFKnight | 0:9b3d4731edbb | 216 | } |
WFKnight | 0:9b3d4731edbb | 217 | |
WFKnight | 0:9b3d4731edbb | 218 | void rtc_write(time_t t) |
WFKnight | 0:9b3d4731edbb | 219 | { |
WFKnight | 0:9b3d4731edbb | 220 | RTC_DateTypeDef dateStruct = {0}; |
WFKnight | 0:9b3d4731edbb | 221 | RTC_TimeTypeDef timeStruct = {0}; |
WFKnight | 0:9b3d4731edbb | 222 | |
WFKnight | 0:9b3d4731edbb | 223 | RtcHandle.Instance = RTC; |
WFKnight | 0:9b3d4731edbb | 224 | |
WFKnight | 0:9b3d4731edbb | 225 | // Convert the time into a tm |
WFKnight | 0:9b3d4731edbb | 226 | struct tm timeinfo; |
WFKnight | 0:9b3d4731edbb | 227 | if (_rtc_localtime(t, &timeinfo, RTC_4_YEAR_LEAP_YEAR_SUPPORT) == false) { |
WFKnight | 0:9b3d4731edbb | 228 | return; |
WFKnight | 0:9b3d4731edbb | 229 | } |
WFKnight | 0:9b3d4731edbb | 230 | |
WFKnight | 0:9b3d4731edbb | 231 | // Fill RTC structures |
WFKnight | 0:9b3d4731edbb | 232 | if (timeinfo.tm_wday == 0) { |
WFKnight | 0:9b3d4731edbb | 233 | dateStruct.WeekDay = 7; |
WFKnight | 0:9b3d4731edbb | 234 | } else { |
WFKnight | 0:9b3d4731edbb | 235 | dateStruct.WeekDay = timeinfo.tm_wday; |
WFKnight | 0:9b3d4731edbb | 236 | } |
WFKnight | 0:9b3d4731edbb | 237 | dateStruct.Month = timeinfo.tm_mon + 1; |
WFKnight | 0:9b3d4731edbb | 238 | dateStruct.Date = timeinfo.tm_mday; |
WFKnight | 0:9b3d4731edbb | 239 | dateStruct.Year = timeinfo.tm_year - 68; |
WFKnight | 0:9b3d4731edbb | 240 | timeStruct.Hours = timeinfo.tm_hour; |
WFKnight | 0:9b3d4731edbb | 241 | timeStruct.Minutes = timeinfo.tm_min; |
WFKnight | 0:9b3d4731edbb | 242 | timeStruct.Seconds = timeinfo.tm_sec; |
WFKnight | 0:9b3d4731edbb | 243 | |
WFKnight | 0:9b3d4731edbb | 244 | #if !(TARGET_STM32F1) |
WFKnight | 0:9b3d4731edbb | 245 | timeStruct.TimeFormat = RTC_HOURFORMAT_24; |
WFKnight | 0:9b3d4731edbb | 246 | timeStruct.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; |
WFKnight | 0:9b3d4731edbb | 247 | timeStruct.StoreOperation = RTC_STOREOPERATION_RESET; |
WFKnight | 0:9b3d4731edbb | 248 | #endif /* TARGET_STM32F1 */ |
WFKnight | 0:9b3d4731edbb | 249 | |
WFKnight | 0:9b3d4731edbb | 250 | // Change the RTC current date/time |
WFKnight | 0:9b3d4731edbb | 251 | if (HAL_RTC_SetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN) != HAL_OK) { |
WFKnight | 0:9b3d4731edbb | 252 | error("HAL_RTC_SetDate error\n"); |
WFKnight | 0:9b3d4731edbb | 253 | } |
WFKnight | 0:9b3d4731edbb | 254 | if (HAL_RTC_SetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN) != HAL_OK) { |
WFKnight | 0:9b3d4731edbb | 255 | error("HAL_RTC_SetTime error\n"); |
WFKnight | 0:9b3d4731edbb | 256 | } |
WFKnight | 0:9b3d4731edbb | 257 | } |
WFKnight | 0:9b3d4731edbb | 258 | |
WFKnight | 0:9b3d4731edbb | 259 | int rtc_isenabled(void) |
WFKnight | 0:9b3d4731edbb | 260 | { |
WFKnight | 0:9b3d4731edbb | 261 | #if !(TARGET_STM32F1) |
WFKnight | 0:9b3d4731edbb | 262 | return ( ((RTC->ISR & RTC_ISR_INITS) == RTC_ISR_INITS) && ((RTC->ISR & RTC_ISR_RSF) == RTC_ISR_RSF) ); |
WFKnight | 0:9b3d4731edbb | 263 | #else /* TARGET_STM32F1 */ |
WFKnight | 0:9b3d4731edbb | 264 | return ((RTC->CRL & RTC_CRL_RSF) == RTC_CRL_RSF); |
WFKnight | 0:9b3d4731edbb | 265 | #endif /* TARGET_STM32F1 */ |
WFKnight | 0:9b3d4731edbb | 266 | } |
WFKnight | 0:9b3d4731edbb | 267 | |
WFKnight | 0:9b3d4731edbb | 268 | void rtc_synchronize(void) |
WFKnight | 0:9b3d4731edbb | 269 | { |
WFKnight | 0:9b3d4731edbb | 270 | RtcHandle.Instance = RTC; |
WFKnight | 0:9b3d4731edbb | 271 | if (HAL_RTC_WaitForSynchro(&RtcHandle) != HAL_OK) { |
WFKnight | 0:9b3d4731edbb | 272 | error("rtc_synchronize error\n"); |
WFKnight | 0:9b3d4731edbb | 273 | } |
WFKnight | 0:9b3d4731edbb | 274 | } |
WFKnight | 0:9b3d4731edbb | 275 | |
WFKnight | 0:9b3d4731edbb | 276 | #if DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM |
WFKnight | 0:9b3d4731edbb | 277 | |
WFKnight | 0:9b3d4731edbb | 278 | static void RTC_IRQHandler(void); |
WFKnight | 0:9b3d4731edbb | 279 | static void (*irq_handler)(void); |
WFKnight | 0:9b3d4731edbb | 280 | |
WFKnight | 0:9b3d4731edbb | 281 | volatile uint8_t lp_Fired = 0; |
WFKnight | 0:9b3d4731edbb | 282 | volatile uint32_t LP_continuous_time = 0; |
WFKnight | 0:9b3d4731edbb | 283 | volatile uint32_t LP_last_RTC_time = 0; |
WFKnight | 0:9b3d4731edbb | 284 | |
WFKnight | 0:9b3d4731edbb | 285 | static void RTC_IRQHandler(void) |
WFKnight | 0:9b3d4731edbb | 286 | { |
WFKnight | 0:9b3d4731edbb | 287 | /* Update HAL state */ |
WFKnight | 0:9b3d4731edbb | 288 | RtcHandle.Instance = RTC; |
WFKnight | 0:9b3d4731edbb | 289 | if(__HAL_RTC_WAKEUPTIMER_GET_IT(&RtcHandle, RTC_IT_WUT)) { |
WFKnight | 0:9b3d4731edbb | 290 | /* Get the status of the Interrupt */ |
WFKnight | 0:9b3d4731edbb | 291 | if((uint32_t)(RTC->CR & RTC_IT_WUT) != (uint32_t)RESET) { |
WFKnight | 0:9b3d4731edbb | 292 | /* Clear the WAKEUPTIMER interrupt pending bit */ |
WFKnight | 0:9b3d4731edbb | 293 | __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF); |
WFKnight | 0:9b3d4731edbb | 294 | |
WFKnight | 0:9b3d4731edbb | 295 | lp_Fired = 0; |
WFKnight | 0:9b3d4731edbb | 296 | if (irq_handler) { |
WFKnight | 0:9b3d4731edbb | 297 | irq_handler(); |
WFKnight | 0:9b3d4731edbb | 298 | } |
WFKnight | 0:9b3d4731edbb | 299 | } |
WFKnight | 0:9b3d4731edbb | 300 | } |
WFKnight | 0:9b3d4731edbb | 301 | |
WFKnight | 0:9b3d4731edbb | 302 | if (lp_Fired) { |
WFKnight | 0:9b3d4731edbb | 303 | lp_Fired = 0; |
WFKnight | 0:9b3d4731edbb | 304 | if (irq_handler) { |
WFKnight | 0:9b3d4731edbb | 305 | irq_handler(); |
WFKnight | 0:9b3d4731edbb | 306 | } |
WFKnight | 0:9b3d4731edbb | 307 | } |
WFKnight | 0:9b3d4731edbb | 308 | |
WFKnight | 0:9b3d4731edbb | 309 | __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); |
WFKnight | 0:9b3d4731edbb | 310 | } |
WFKnight | 0:9b3d4731edbb | 311 | |
WFKnight | 0:9b3d4731edbb | 312 | uint32_t rtc_read_lp(void) |
WFKnight | 0:9b3d4731edbb | 313 | { |
WFKnight | 0:9b3d4731edbb | 314 | RTC_TimeTypeDef timeStruct = {0}; |
WFKnight | 0:9b3d4731edbb | 315 | RTC_DateTypeDef dateStruct = {0}; |
WFKnight | 0:9b3d4731edbb | 316 | |
WFKnight | 0:9b3d4731edbb | 317 | RtcHandle.Instance = RTC; |
WFKnight | 0:9b3d4731edbb | 318 | HAL_RTC_GetTime(&RtcHandle, &timeStruct, RTC_FORMAT_BIN); |
WFKnight | 0:9b3d4731edbb | 319 | |
WFKnight | 0:9b3d4731edbb | 320 | /* Reading RTC current time locks the values in calendar shadow registers until Current date is read |
WFKnight | 0:9b3d4731edbb | 321 | to ensure consistency between the time and date values */ |
WFKnight | 0:9b3d4731edbb | 322 | HAL_RTC_GetDate(&RtcHandle, &dateStruct, RTC_FORMAT_BIN); |
WFKnight | 0:9b3d4731edbb | 323 | |
WFKnight | 0:9b3d4731edbb | 324 | if (timeStruct.SubSeconds > timeStruct.SecondFraction) { |
WFKnight | 0:9b3d4731edbb | 325 | /* SS can be larger than PREDIV_S only after a shift operation. In that case, the correct |
WFKnight | 0:9b3d4731edbb | 326 | time/date is one second less than as indicated by RTC_TR/RTC_DR. */ |
WFKnight | 0:9b3d4731edbb | 327 | timeStruct.Seconds -= 1; |
WFKnight | 0:9b3d4731edbb | 328 | } |
WFKnight | 0:9b3d4731edbb | 329 | uint32_t RTC_time_s = timeStruct.Seconds + timeStruct.Minutes * 60 + timeStruct.Hours * 60 * 60; // Max 0x0001-517F => * 8191 + 8191 = 0x2A2E-AE80 |
WFKnight | 0:9b3d4731edbb | 330 | |
WFKnight | 0:9b3d4731edbb | 331 | if (LP_last_RTC_time <= RTC_time_s) { |
WFKnight | 0:9b3d4731edbb | 332 | LP_continuous_time += (RTC_time_s - LP_last_RTC_time); |
WFKnight | 0:9b3d4731edbb | 333 | } else { |
WFKnight | 0:9b3d4731edbb | 334 | LP_continuous_time += (24 * 60 * 60 + RTC_time_s - LP_last_RTC_time); |
WFKnight | 0:9b3d4731edbb | 335 | } |
WFKnight | 0:9b3d4731edbb | 336 | LP_last_RTC_time = RTC_time_s; |
WFKnight | 0:9b3d4731edbb | 337 | |
WFKnight | 0:9b3d4731edbb | 338 | return LP_continuous_time * PREDIV_S_VALUE + timeStruct.SecondFraction - timeStruct.SubSeconds; |
WFKnight | 0:9b3d4731edbb | 339 | } |
WFKnight | 0:9b3d4731edbb | 340 | |
WFKnight | 0:9b3d4731edbb | 341 | void rtc_set_wake_up_timer(timestamp_t timestamp) |
WFKnight | 0:9b3d4731edbb | 342 | { |
WFKnight | 0:9b3d4731edbb | 343 | uint32_t WakeUpCounter; |
WFKnight | 0:9b3d4731edbb | 344 | uint32_t current_lp_time; |
WFKnight | 0:9b3d4731edbb | 345 | |
WFKnight | 0:9b3d4731edbb | 346 | current_lp_time = rtc_read_lp(); |
WFKnight | 0:9b3d4731edbb | 347 | |
WFKnight | 0:9b3d4731edbb | 348 | if (timestamp < current_lp_time) { |
WFKnight | 0:9b3d4731edbb | 349 | WakeUpCounter = 0xFFFFFFFF - current_lp_time + timestamp; |
WFKnight | 0:9b3d4731edbb | 350 | } else { |
WFKnight | 0:9b3d4731edbb | 351 | WakeUpCounter = timestamp - current_lp_time; |
WFKnight | 0:9b3d4731edbb | 352 | } |
WFKnight | 0:9b3d4731edbb | 353 | |
WFKnight | 0:9b3d4731edbb | 354 | if (WakeUpCounter > 0xFFFF) { |
WFKnight | 0:9b3d4731edbb | 355 | WakeUpCounter = 0xFFFF; |
WFKnight | 0:9b3d4731edbb | 356 | } |
WFKnight | 0:9b3d4731edbb | 357 | |
WFKnight | 0:9b3d4731edbb | 358 | RtcHandle.Instance = RTC; |
WFKnight | 0:9b3d4731edbb | 359 | if (HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, WakeUpCounter, RTC_WAKEUPCLOCK_RTCCLK_DIV4) != HAL_OK) { |
WFKnight | 0:9b3d4731edbb | 360 | error("rtc_set_wake_up_timer init error\n"); |
WFKnight | 0:9b3d4731edbb | 361 | } |
WFKnight | 0:9b3d4731edbb | 362 | |
WFKnight | 0:9b3d4731edbb | 363 | NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); |
WFKnight | 0:9b3d4731edbb | 364 | irq_handler = (void (*)(void))lp_ticker_irq_handler; |
WFKnight | 0:9b3d4731edbb | 365 | NVIC_EnableIRQ(RTC_WKUP_IRQn); |
WFKnight | 0:9b3d4731edbb | 366 | } |
WFKnight | 0:9b3d4731edbb | 367 | |
WFKnight | 0:9b3d4731edbb | 368 | void rtc_fire_interrupt(void) |
WFKnight | 0:9b3d4731edbb | 369 | { |
WFKnight | 0:9b3d4731edbb | 370 | lp_Fired = 1; |
WFKnight | 0:9b3d4731edbb | 371 | NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); |
WFKnight | 0:9b3d4731edbb | 372 | irq_handler = (void (*)(void))lp_ticker_irq_handler; |
WFKnight | 0:9b3d4731edbb | 373 | NVIC_SetPendingIRQ(RTC_WKUP_IRQn); |
WFKnight | 0:9b3d4731edbb | 374 | NVIC_EnableIRQ(RTC_WKUP_IRQn); |
WFKnight | 0:9b3d4731edbb | 375 | } |
WFKnight | 0:9b3d4731edbb | 376 | |
WFKnight | 0:9b3d4731edbb | 377 | void rtc_deactivate_wake_up_timer(void) |
WFKnight | 0:9b3d4731edbb | 378 | { |
WFKnight | 0:9b3d4731edbb | 379 | RtcHandle.Instance = RTC; |
WFKnight | 0:9b3d4731edbb | 380 | HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle); |
WFKnight | 0:9b3d4731edbb | 381 | } |
WFKnight | 0:9b3d4731edbb | 382 | |
WFKnight | 0:9b3d4731edbb | 383 | #endif /* DEVICE_LPTICKER && !MBED_CONF_TARGET_LPTICKER_LPTIM */ |
WFKnight | 0:9b3d4731edbb | 384 | |
WFKnight | 0:9b3d4731edbb | 385 | #endif /* DEVICE_RTC */ |