Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

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