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:
187:0387e8f68319
mbed library release version 165

Who changed what in which revision?

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