mbed library sources. Supersedes mbed-src.

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

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

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 172:7d866c31b3c5 1 /* mbed Microcontroller Library
AnnaBridge 172:7d866c31b3c5 2 * Copyright (c) 2015-2016 Nuvoton
AnnaBridge 172:7d866c31b3c5 3 *
AnnaBridge 172:7d866c31b3c5 4 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 172:7d866c31b3c5 5 * you may not use this file except in compliance with the License.
AnnaBridge 172:7d866c31b3c5 6 * You may obtain a copy of the License at
AnnaBridge 172:7d866c31b3c5 7 *
AnnaBridge 172:7d866c31b3c5 8 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 172:7d866c31b3c5 9 *
AnnaBridge 172:7d866c31b3c5 10 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 172:7d866c31b3c5 11 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 172:7d866c31b3c5 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 172:7d866c31b3c5 13 * See the License for the specific language governing permissions and
AnnaBridge 172:7d866c31b3c5 14 * limitations under the License.
AnnaBridge 172:7d866c31b3c5 15 */
AnnaBridge 172:7d866c31b3c5 16
AnnaBridge 172:7d866c31b3c5 17 #include "rtc_api.h"
AnnaBridge 172:7d866c31b3c5 18
AnnaBridge 172:7d866c31b3c5 19 #if DEVICE_RTC
AnnaBridge 172:7d866c31b3c5 20
AnnaBridge 172:7d866c31b3c5 21 #include "mbed_wait_api.h"
AnnaBridge 172:7d866c31b3c5 22 #include "mbed_error.h"
AnnaBridge 172:7d866c31b3c5 23 #include "nu_modutil.h"
AnnaBridge 172:7d866c31b3c5 24 #include "nu_miscutil.h"
AnnaBridge 176:447f873cad2f 25 #include "mbed_mktime.h"
AnnaBridge 172:7d866c31b3c5 26
AnnaBridge 184:08ed48f1de7f 27 /* Micro seconds per second */
AnnaBridge 184:08ed48f1de7f 28 #define NU_US_PER_SEC 1000000
AnnaBridge 184:08ed48f1de7f 29 /* Timer clock per second
AnnaBridge 184:08ed48f1de7f 30 *
AnnaBridge 184:08ed48f1de7f 31 * NOTE: This dependents on real hardware.
AnnaBridge 184:08ed48f1de7f 32 */
AnnaBridge 184:08ed48f1de7f 33 #define NU_RTCCLK_PER_SEC ((CLK->CLKSEL3 & CLK_CLKSEL3_SC0SEL_Msk) ? __LIRC : __LXT)
AnnaBridge 184:08ed48f1de7f 34
AnnaBridge 184:08ed48f1de7f 35 /* Strategy for implementation of RTC HAL
AnnaBridge 184:08ed48f1de7f 36 *
AnnaBridge 184:08ed48f1de7f 37 * H/W RTC just supports year range 2000~2099, which cannot fully cover POSIX time (starting since 2970)
AnnaBridge 184:08ed48f1de7f 38 * and date time of struct TM (starting since 1900).
AnnaBridge 184:08ed48f1de7f 39 *
AnnaBridge 184:08ed48f1de7f 40 * To conquer the difficulty, we don't use H/W RTC to keep real date time. Instead, we use it to keep
AnnaBridge 184:08ed48f1de7f 41 * elapsed time in seconds since one reference time point. The strategy would be:
AnnaBridge 184:08ed48f1de7f 42 *
AnnaBridge 184:08ed48f1de7f 43 * 1. Choose DATETIME_HWRTC_ORIGIN (00:00:00 UTC, Saturday, 1 January 2000) as reference time point of H/W RTC.
AnnaBridge 184:08ed48f1de7f 44 * 2. t_hwrtc_origin = DATETIME_HWRTC_ORIGIN in POSIX time
AnnaBridge 184:08ed48f1de7f 45 * 3. t_hwrtc_elapsed = t_hwrtc_origin + elapsed time since t_hwrtc_origin
AnnaBridge 184:08ed48f1de7f 46 * 4. t_write = POSIX time set by rtc_write().
AnnaBridge 184:08ed48f1de7f 47 * 5. t_present = rtc_read() = t_write + (t_hwrtc_elapsed - t_hwrtc_origin)
AnnaBridge 184:08ed48f1de7f 48 *
AnnaBridge 184:08ed48f1de7f 49 * 1900
AnnaBridge 184:08ed48f1de7f 50 * |---------------------------------------------------------------------------------|
AnnaBridge 184:08ed48f1de7f 51 * 1970 t_write t_present
AnnaBridge 184:08ed48f1de7f 52 * |---------|-------|-----------------|---------------------------------------------|
AnnaBridge 184:08ed48f1de7f 53 *
AnnaBridge 184:08ed48f1de7f 54 * 2000
AnnaBridge 184:08ed48f1de7f 55 * |-----------------|---------------------------------------------------------------|
AnnaBridge 184:08ed48f1de7f 56 * t_hwrtc_origin t_hwrtc_elapsed
AnnaBridge 184:08ed48f1de7f 57 *
AnnaBridge 184:08ed48f1de7f 58 */
AnnaBridge 184:08ed48f1de7f 59 /* Start year of struct TM*/
AnnaBridge 184:08ed48f1de7f 60 #define NU_TM_YEAR0 1900
AnnaBridge 184:08ed48f1de7f 61 /* Start year of POSIX time (set_time()/time()) */
AnnaBridge 184:08ed48f1de7f 62 #define NU_POSIX_YEAR0 1970
AnnaBridge 184:08ed48f1de7f 63 /* Start year of H/W RTC */
AnnaBridge 184:08ed48f1de7f 64 #define NU_HWRTC_YEAR0 2000
AnnaBridge 184:08ed48f1de7f 65
AnnaBridge 184:08ed48f1de7f 66 /* RTC H/W origin time: 00:00:00 UTC, Saturday, 1 January 2000 */
AnnaBridge 184:08ed48f1de7f 67 static const S_RTC_TIME_DATA_T DATETIME_HWRTC_ORIGIN = {
AnnaBridge 184:08ed48f1de7f 68 2000, /* Year value, range between 2000 ~ 2099 */
AnnaBridge 184:08ed48f1de7f 69 1, /* Month value, range between 1 ~ 12 */
AnnaBridge 184:08ed48f1de7f 70 1, /* Day value, range between 1 ~ 31 */
AnnaBridge 184:08ed48f1de7f 71 RTC_SATURDAY, /* Day of the week */
AnnaBridge 184:08ed48f1de7f 72 0, /* Hour value, range between 0 ~ 23 */
AnnaBridge 184:08ed48f1de7f 73 0, /* Minute value, range between 0 ~ 59 */
AnnaBridge 184:08ed48f1de7f 74 0, /* Second value, range between 0 ~ 59 */
AnnaBridge 184:08ed48f1de7f 75 RTC_CLOCK_24, /* 12-Hour (RTC_CLOCK_12) / 24-Hour (RTC_CLOCK_24) */
AnnaBridge 184:08ed48f1de7f 76 0 /* RTC_AM / RTC_PM (used only for 12-Hour) */
AnnaBridge 184:08ed48f1de7f 77 };
AnnaBridge 184:08ed48f1de7f 78 /* t_hwrtc_origin initialized or not? */
AnnaBridge 184:08ed48f1de7f 79 static bool t_hwrtc_origin_inited = 0;
AnnaBridge 184:08ed48f1de7f 80 /* POSIX time of DATETIME_HWRTC_ORIGIN (since 00:00:00 UTC, Thursday, 1 January 1970) */
AnnaBridge 184:08ed48f1de7f 81 static time_t t_hwrtc_origin = 0;
AnnaBridge 184:08ed48f1de7f 82 /* POSIX time set by rtc_write() */
AnnaBridge 184:08ed48f1de7f 83 static time_t t_write = 0;
AnnaBridge 184:08ed48f1de7f 84 /* Convert date time from H/W RTC to struct TM */
AnnaBridge 184:08ed48f1de7f 85 static void rtc_convert_datetime_hwrtc_to_tm(struct tm *datetime_tm, const S_RTC_TIME_DATA_T *datetime_hwrtc);
AnnaBridge 172:7d866c31b3c5 86
AnnaBridge 172:7d866c31b3c5 87 static const struct nu_modinit_s rtc_modinit = {RTC_0, RTC_MODULE, 0, 0, 0, RTC_IRQn, NULL};
AnnaBridge 172:7d866c31b3c5 88
AnnaBridge 172:7d866c31b3c5 89 void rtc_init(void)
AnnaBridge 172:7d866c31b3c5 90 {
AnnaBridge 172:7d866c31b3c5 91 if (rtc_isenabled()) {
AnnaBridge 172:7d866c31b3c5 92 return;
AnnaBridge 172:7d866c31b3c5 93 }
AnnaBridge 172:7d866c31b3c5 94
AnnaBridge 172:7d866c31b3c5 95 RTC_Open(NULL);
AnnaBridge 184:08ed48f1de7f 96
AnnaBridge 184:08ed48f1de7f 97 /* POSIX time origin (00:00:00 UTC, Thursday, 1 January 1970) */
AnnaBridge 184:08ed48f1de7f 98 rtc_write(0);
AnnaBridge 172:7d866c31b3c5 99 }
AnnaBridge 172:7d866c31b3c5 100
AnnaBridge 172:7d866c31b3c5 101 void rtc_free(void)
AnnaBridge 172:7d866c31b3c5 102 {
Anna Bridge 186:707f6e361f3e 103 CLK_DisableModuleClock(rtc_modinit.clkidx);
AnnaBridge 172:7d866c31b3c5 104 }
AnnaBridge 172:7d866c31b3c5 105
AnnaBridge 172:7d866c31b3c5 106 int rtc_isenabled(void)
AnnaBridge 172:7d866c31b3c5 107 {
AnnaBridge 172:7d866c31b3c5 108 // NOTE: To access (RTC) registers, clock must be enabled first.
AnnaBridge 172:7d866c31b3c5 109 if (! (CLK->APBCLK0 & CLK_APBCLK0_RTCCKEN_Msk)) {
AnnaBridge 172:7d866c31b3c5 110 // Enable IP clock
AnnaBridge 172:7d866c31b3c5 111 CLK_EnableModuleClock(rtc_modinit.clkidx);
AnnaBridge 172:7d866c31b3c5 112 }
AnnaBridge 172:7d866c31b3c5 113
AnnaBridge 172:7d866c31b3c5 114 // NOTE: Check RTC Init Active flag to support crossing reset cycle.
AnnaBridge 172:7d866c31b3c5 115 return !! (RTC->INIT & RTC_INIT_ACTIVE_Msk);
AnnaBridge 172:7d866c31b3c5 116 }
Anna Bridge 186:707f6e361f3e 117
AnnaBridge 184:08ed48f1de7f 118 time_t rtc_read(void)
AnnaBridge 184:08ed48f1de7f 119 {
AnnaBridge 184:08ed48f1de7f 120 /* NOTE: After boot, RTC time registers are not synced immediately, about 1 sec latency.
AnnaBridge 184:08ed48f1de7f 121 * RTC time got (through RTC_GetDateAndTime()) in this sec would be last-synced and incorrect.
AnnaBridge 184:08ed48f1de7f 122 * NUC472/M453: Known issue
AnnaBridge 184:08ed48f1de7f 123 * M487: Fixed
AnnaBridge 184:08ed48f1de7f 124 */
AnnaBridge 184:08ed48f1de7f 125 if (! rtc_isenabled()) {
AnnaBridge 184:08ed48f1de7f 126 rtc_init();
AnnaBridge 184:08ed48f1de7f 127 }
AnnaBridge 184:08ed48f1de7f 128
AnnaBridge 184:08ed48f1de7f 129 /* Used for intermediary between date time of H/W RTC and POSIX time */
AnnaBridge 184:08ed48f1de7f 130 struct tm datetime_tm;
AnnaBridge 184:08ed48f1de7f 131
AnnaBridge 184:08ed48f1de7f 132 if (! t_hwrtc_origin_inited) {
AnnaBridge 184:08ed48f1de7f 133 t_hwrtc_origin_inited = 1;
AnnaBridge 184:08ed48f1de7f 134
AnnaBridge 184:08ed48f1de7f 135 /* Convert date time from H/W RTC to struct TM */
AnnaBridge 184:08ed48f1de7f 136 rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &DATETIME_HWRTC_ORIGIN);
AnnaBridge 184:08ed48f1de7f 137 /* Convert date time of struct TM to POSIX time */
AnnaBridge 184:08ed48f1de7f 138 if (! _rtc_maketime(&datetime_tm, &t_hwrtc_origin, RTC_FULL_LEAP_YEAR_SUPPORT)) {
AnnaBridge 184:08ed48f1de7f 139 return 0;
AnnaBridge 184:08ed48f1de7f 140 }
Anna Bridge 186:707f6e361f3e 141
Anna Bridge 186:707f6e361f3e 142 /* Load t_write from RTC spare register to cross reset cycle */
Anna Bridge 186:707f6e361f3e 143 RTC_WaitAccessEnable();
Anna Bridge 186:707f6e361f3e 144 RTC_EnableSpareAccess();
Anna Bridge 186:707f6e361f3e 145 RTC_WaitAccessEnable();
Anna Bridge 186:707f6e361f3e 146 t_write = RTC_READ_SPARE_REGISTER(0);
AnnaBridge 184:08ed48f1de7f 147 }
AnnaBridge 184:08ed48f1de7f 148
AnnaBridge 184:08ed48f1de7f 149 S_RTC_TIME_DATA_T hwrtc_datetime_2K_present;
Anna Bridge 186:707f6e361f3e 150 RTC_WaitAccessEnable();
AnnaBridge 184:08ed48f1de7f 151 RTC_GetDateAndTime(&hwrtc_datetime_2K_present);
AnnaBridge 184:08ed48f1de7f 152 /* Convert date time from H/W RTC to struct TM */
AnnaBridge 184:08ed48f1de7f 153 rtc_convert_datetime_hwrtc_to_tm(&datetime_tm, &hwrtc_datetime_2K_present);
AnnaBridge 184:08ed48f1de7f 154 /* Convert date time of struct TM to POSIX time */
AnnaBridge 184:08ed48f1de7f 155 time_t t_hwrtc_elapsed;
AnnaBridge 184:08ed48f1de7f 156 if (! _rtc_maketime(&datetime_tm, &t_hwrtc_elapsed, RTC_FULL_LEAP_YEAR_SUPPORT)) {
AnnaBridge 184:08ed48f1de7f 157 return 0;
AnnaBridge 184:08ed48f1de7f 158 }
AnnaBridge 184:08ed48f1de7f 159
AnnaBridge 184:08ed48f1de7f 160 /* Present time in POSIX time */
AnnaBridge 184:08ed48f1de7f 161 time_t t_present = t_write + (t_hwrtc_elapsed - t_hwrtc_origin);
AnnaBridge 184:08ed48f1de7f 162 return t_present;
AnnaBridge 184:08ed48f1de7f 163 }
AnnaBridge 184:08ed48f1de7f 164
AnnaBridge 184:08ed48f1de7f 165 void rtc_write(time_t t)
AnnaBridge 184:08ed48f1de7f 166 {
AnnaBridge 184:08ed48f1de7f 167 if (! rtc_isenabled()) {
AnnaBridge 184:08ed48f1de7f 168 rtc_init();
AnnaBridge 184:08ed48f1de7f 169 }
AnnaBridge 184:08ed48f1de7f 170
AnnaBridge 184:08ed48f1de7f 171 t_write = t;
AnnaBridge 184:08ed48f1de7f 172
Anna Bridge 186:707f6e361f3e 173 /* Store t_write to RTC spare register to cross reset cycle */
Anna Bridge 186:707f6e361f3e 174 RTC_WaitAccessEnable();
Anna Bridge 186:707f6e361f3e 175 RTC_EnableSpareAccess();
Anna Bridge 186:707f6e361f3e 176 RTC_WaitAccessEnable();
Anna Bridge 186:707f6e361f3e 177 RTC_WRITE_SPARE_REGISTER(0, t_write);
Anna Bridge 186:707f6e361f3e 178
Anna Bridge 186:707f6e361f3e 179 RTC_WaitAccessEnable();
AnnaBridge 184:08ed48f1de7f 180 RTC_SetDateAndTime((S_RTC_TIME_DATA_T *) &DATETIME_HWRTC_ORIGIN);
AnnaBridge 184:08ed48f1de7f 181 /* NOTE: When engine is clocked by low power clock source (LXT/LIRC), we need to wait for 3 engine clocks. */
AnnaBridge 184:08ed48f1de7f 182 wait_us((NU_US_PER_SEC / NU_RTCCLK_PER_SEC) * 3);
AnnaBridge 184:08ed48f1de7f 183 }
AnnaBridge 172:7d866c31b3c5 184
AnnaBridge 172:7d866c31b3c5 185 /*
AnnaBridge 172:7d866c31b3c5 186 struct tm
AnnaBridge 172:7d866c31b3c5 187 tm_sec seconds after the minute 0-61
AnnaBridge 172:7d866c31b3c5 188 tm_min minutes after the hour 0-59
AnnaBridge 172:7d866c31b3c5 189 tm_hour hours since midnight 0-23
AnnaBridge 172:7d866c31b3c5 190 tm_mday day of the month 1-31
AnnaBridge 172:7d866c31b3c5 191 tm_mon months since January 0-11
AnnaBridge 172:7d866c31b3c5 192 tm_year years since 1900
AnnaBridge 172:7d866c31b3c5 193 tm_wday days since Sunday 0-6
AnnaBridge 172:7d866c31b3c5 194 tm_yday days since January 1 0-365
AnnaBridge 172:7d866c31b3c5 195 tm_isdst Daylight Saving Time flag
AnnaBridge 172:7d866c31b3c5 196 */
AnnaBridge 184:08ed48f1de7f 197 static void rtc_convert_datetime_hwrtc_to_tm(struct tm *datetime_tm, const S_RTC_TIME_DATA_T *datetime_hwrtc)
AnnaBridge 172:7d866c31b3c5 198 {
AnnaBridge 184:08ed48f1de7f 199 datetime_tm->tm_year = datetime_hwrtc->u32Year - NU_TM_YEAR0;
AnnaBridge 184:08ed48f1de7f 200 datetime_tm->tm_mon = datetime_hwrtc->u32Month - 1;
AnnaBridge 184:08ed48f1de7f 201 datetime_tm->tm_mday = datetime_hwrtc->u32Day;
AnnaBridge 184:08ed48f1de7f 202 datetime_tm->tm_wday = datetime_hwrtc->u32DayOfWeek;
AnnaBridge 184:08ed48f1de7f 203 datetime_tm->tm_hour = datetime_hwrtc->u32Hour;
AnnaBridge 184:08ed48f1de7f 204 if (datetime_hwrtc->u32TimeScale == RTC_CLOCK_12 && datetime_hwrtc->u32AmPm == RTC_PM) {
AnnaBridge 184:08ed48f1de7f 205 datetime_tm->tm_hour += 12;
AnnaBridge 176:447f873cad2f 206 }
AnnaBridge 184:08ed48f1de7f 207 datetime_tm->tm_min = datetime_hwrtc->u32Minute;
AnnaBridge 184:08ed48f1de7f 208 datetime_tm->tm_sec = datetime_hwrtc->u32Second;
AnnaBridge 172:7d866c31b3c5 209 }
AnnaBridge 172:7d866c31b3c5 210
AnnaBridge 172:7d866c31b3c5 211 #endif