File indexing completed on 2025-05-11 08:23:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "fsl_snvs_hp.h"
0010
0011
0012
0013
0014
0015
0016 #ifndef FSL_COMPONENT_ID
0017 #define FSL_COMPONENT_ID "platform.drivers.snvs_hp"
0018 #endif
0019
0020 #define SECONDS_IN_A_DAY (86400U)
0021 #define SECONDS_IN_A_HOUR (3600U)
0022 #define SECONDS_IN_A_MINUTE (60U)
0023 #define DAYS_IN_A_YEAR (365U)
0024 #define YEAR_RANGE_START (1970U)
0025 #define YEAR_RANGE_END (2099U)
0026
0027 #if !(defined(SNVS_HPSR_PI_MASK))
0028 #define SNVS_HPSR_PI_MASK (0x2U)
0029 #endif
0030 #if !(defined(SNVS_HPSR_HPTA_MASK))
0031 #define SNVS_HPSR_HPTA_MASK (0x1U)
0032 #endif
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 static bool SNVS_HP_CheckDatetimeFormat(const snvs_hp_rtc_datetime_t *datetime);
0045
0046
0047
0048
0049
0050
0051
0052
0053 static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *datetime);
0054
0055
0056
0057
0058
0059
0060
0061 static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datetime_t *datetime);
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 static uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base);
0073
0074 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
0075 defined(SNVS_HP_CLOCKS))
0076
0077
0078
0079
0080
0081
0082
0083 static uint32_t SNVS_HP_GetInstance(SNVS_Type *base);
0084 #endif
0085
0086
0087
0088
0089 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
0090 defined(SNVS_HP_CLOCKS))
0091
0092 static const clock_ip_name_t s_snvsHpClock[] = SNVS_HP_CLOCKS;
0093 #endif
0094
0095
0096
0097
0098 static bool SNVS_HP_CheckDatetimeFormat(const snvs_hp_rtc_datetime_t *datetime)
0099 {
0100 assert(datetime != NULL);
0101
0102
0103
0104
0105 uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
0106
0107
0108 if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) || (datetime->month > 12U) ||
0109 (datetime->month < 1U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) || (datetime->second >= 60U))
0110 {
0111
0112 return false;
0113 }
0114
0115
0116 if ((((datetime->year & 3U) == 0U) && (datetime->year % 100U != 0U)) || (datetime->year % 400U == 0U))
0117 {
0118 daysPerMonth[2] = 29U;
0119 }
0120
0121
0122 if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U))
0123 {
0124 return false;
0125 }
0126
0127 return true;
0128 }
0129
0130 static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *datetime)
0131 {
0132 assert(datetime != NULL);
0133
0134
0135
0136 uint16_t monthDays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
0137 uint32_t seconds;
0138
0139
0140 seconds = (((uint32_t)datetime->year - 1970U) * DAYS_IN_A_YEAR);
0141
0142 seconds += (((uint32_t)datetime->year / 4U) - (1970U / 4U));
0143
0144 seconds += monthDays[datetime->month];
0145
0146
0147 seconds += ((uint32_t)datetime->day - 1U);
0148
0149 if ((0U == (datetime->year & 3U)) && (datetime->month <= 2U))
0150 {
0151 seconds--;
0152 }
0153
0154 seconds = (seconds * SECONDS_IN_A_DAY) + (datetime->hour * SECONDS_IN_A_HOUR) +
0155 (datetime->minute * SECONDS_IN_A_MINUTE) + datetime->second;
0156
0157 return seconds;
0158 }
0159
0160 static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datetime_t *datetime)
0161 {
0162 assert(datetime != NULL);
0163
0164 uint32_t x;
0165 uint32_t secondsRemaining, days;
0166 uint16_t daysInYear;
0167
0168
0169
0170 uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
0171
0172
0173 secondsRemaining = seconds;
0174
0175
0176
0177
0178 days = secondsRemaining / SECONDS_IN_A_DAY + 1U;
0179
0180
0181 secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY;
0182
0183
0184 datetime->hour = (uint8_t)(secondsRemaining / SECONDS_IN_A_HOUR);
0185 secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
0186 datetime->minute = (uint8_t)(secondsRemaining / 60U);
0187 datetime->second = (uint8_t)(secondsRemaining % SECONDS_IN_A_MINUTE);
0188
0189
0190 daysInYear = DAYS_IN_A_YEAR;
0191 datetime->year = YEAR_RANGE_START;
0192 while (days > daysInYear)
0193 {
0194
0195 days -= daysInYear;
0196 datetime->year++;
0197
0198
0199 if ((datetime->year & 3U) != 0U)
0200 {
0201 daysInYear = DAYS_IN_A_YEAR;
0202 }
0203 else
0204 {
0205 daysInYear = DAYS_IN_A_YEAR + 1U;
0206 }
0207 }
0208
0209
0210 if (0U == (datetime->year & 3U))
0211 {
0212 daysPerMonth[2] = 29U;
0213 }
0214
0215 for (x = 1U; x <= 12U; x++)
0216 {
0217 if (days <= daysPerMonth[x])
0218 {
0219 datetime->month = (uint8_t)x;
0220 break;
0221 }
0222 else
0223 {
0224 days -= daysPerMonth[x];
0225 }
0226 }
0227
0228 datetime->day = (uint8_t)days;
0229 }
0230
0231 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
0232 defined(SNVS_HP_CLOCKS))
0233 static uint32_t SNVS_HP_GetInstance(SNVS_Type *base)
0234 {
0235 return 0U;
0236 }
0237 #endif
0238
0239
0240
0241
0242
0243
0244
0245
0246 void SNVS_HP_Init(SNVS_Type *base)
0247 {
0248 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
0249 defined(SNVS_HP_CLOCKS))
0250 uint32_t instance = SNVS_HP_GetInstance(base);
0251 CLOCK_EnableClock(s_snvsHpClock[instance]);
0252 #endif
0253 }
0254
0255
0256
0257
0258
0259
0260 void SNVS_HP_Deinit(SNVS_Type *base)
0261 {
0262 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \
0263 defined(SNVS_HP_CLOCKS))
0264 uint32_t instance = SNVS_HP_GetInstance(base);
0265 CLOCK_DisableClock(s_snvsHpClock[instance]);
0266 #endif
0267 }
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 void SNVS_HP_RTC_Init(SNVS_Type *base, const snvs_hp_rtc_config_t *config)
0278 {
0279 assert(config != NULL);
0280
0281 SNVS_HP_Init(base);
0282
0283 base->HPCOMR |= SNVS_HPCOMR_NPSWA_EN_MASK;
0284
0285 base->HPCR = (base->HPCR & ~SNVS_HPCR_PI_FREQ_MASK) | SNVS_HPCR_PI_FREQ(config->periodicInterruptFreq);
0286
0287 if (config->rtcCalEnable)
0288 {
0289 base->HPCR = (base->HPCR & ~SNVS_HPCR_HPCALB_VAL_MASK) | SNVS_HPCR_HPCALB_VAL(config->rtcCalValue);
0290 base->HPCR |= SNVS_HPCR_HPCALB_EN_MASK;
0291 }
0292 }
0293
0294
0295
0296
0297
0298
0299 void SNVS_HP_RTC_Deinit(SNVS_Type *base)
0300 {
0301 base->HPCR &= ~SNVS_HPCR_RTC_EN_MASK;
0302
0303 SNVS_HP_Deinit(base);
0304 }
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317 void SNVS_HP_RTC_GetDefaultConfig(snvs_hp_rtc_config_t *config)
0318 {
0319 assert(config != NULL);
0320
0321
0322 (void)memset(config, 0, sizeof(*config));
0323
0324 config->rtcCalEnable = false;
0325 config->rtcCalValue = 0U;
0326 config->periodicInterruptFreq = 0U;
0327 }
0328
0329 static uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base)
0330 {
0331 uint32_t seconds = 0;
0332 uint32_t tmp = 0;
0333
0334
0335 do
0336 {
0337 seconds = tmp;
0338 tmp = (base->HPRTCMR << 17U);
0339 tmp |= (base->HPRTCLR >> 15U);
0340 } while (tmp != seconds);
0341
0342 return seconds;
0343 }
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354 status_t SNVS_HP_RTC_SetDatetime(SNVS_Type *base, const snvs_hp_rtc_datetime_t *datetime)
0355 {
0356 assert(datetime != NULL);
0357
0358 uint32_t seconds = 0U;
0359 uint32_t tmp = base->HPCR;
0360
0361
0362 SNVS_HP_RTC_StopTimer(base);
0363
0364
0365 if (!(SNVS_HP_CheckDatetimeFormat(datetime)))
0366 {
0367 return kStatus_InvalidArgument;
0368 }
0369
0370
0371 seconds = SNVS_HP_ConvertDatetimeToSeconds(datetime);
0372
0373 base->HPRTCMR = (uint32_t)(seconds >> 17U);
0374 base->HPRTCLR = (uint32_t)(seconds << 15U);
0375
0376
0377 if ((tmp & SNVS_HPCR_RTC_EN_MASK) != 0U)
0378 {
0379 SNVS_HP_RTC_StartTimer(base);
0380 }
0381
0382 return kStatus_Success;
0383 }
0384
0385
0386
0387
0388
0389
0390
0391 void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime)
0392 {
0393 assert(datetime != NULL);
0394
0395 SNVS_HP_ConvertSecondsToDatetime(SNVS_HP_RTC_GetSeconds(base), datetime);
0396 }
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 status_t SNVS_HP_RTC_SetAlarm(SNVS_Type *base, const snvs_hp_rtc_datetime_t *alarmTime)
0413 {
0414 assert(alarmTime != NULL);
0415
0416 uint32_t alarmSeconds = 0U;
0417 uint32_t currSeconds = 0U;
0418 uint32_t tmp = base->HPCR;
0419
0420
0421 if (!(SNVS_HP_CheckDatetimeFormat(alarmTime)))
0422 {
0423 return kStatus_InvalidArgument;
0424 }
0425
0426 alarmSeconds = SNVS_HP_ConvertDatetimeToSeconds(alarmTime);
0427 currSeconds = SNVS_HP_RTC_GetSeconds(base);
0428
0429
0430 if (alarmSeconds < currSeconds)
0431 {
0432 return kStatus_Fail;
0433 }
0434
0435
0436 base->HPCR &= ~SNVS_HPCR_HPTA_EN_MASK;
0437 while ((base->HPCR & SNVS_HPCR_HPTA_EN_MASK) != 0U)
0438 {
0439 }
0440
0441
0442 base->HPTAMR = (uint32_t)(alarmSeconds >> 17U);
0443 base->HPTALR = (uint32_t)(alarmSeconds << 15U);
0444
0445
0446 base->HPCR = tmp;
0447
0448 return kStatus_Success;
0449 }
0450
0451
0452
0453
0454
0455
0456
0457 void SNVS_HP_RTC_GetAlarm(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime)
0458 {
0459 assert(datetime != NULL);
0460
0461 uint32_t alarmSeconds = 0U;
0462
0463
0464 alarmSeconds = (base->HPTAMR << 17U);
0465 alarmSeconds |= (base->HPTALR >> 15U);
0466
0467 SNVS_HP_ConvertSecondsToDatetime(alarmSeconds, datetime);
0468 }
0469
0470 #if (defined(FSL_FEATURE_SNVS_HAS_SRTC) && (FSL_FEATURE_SNVS_HAS_SRTC > 0))
0471
0472
0473
0474
0475
0476 void SNVS_HP_RTC_TimeSynchronize(SNVS_Type *base)
0477 {
0478 uint32_t tmp = base->HPCR;
0479
0480
0481 SNVS_HP_RTC_StopTimer(base);
0482
0483 base->HPCR |= SNVS_HPCR_HP_TS_MASK;
0484
0485
0486 if ((tmp & SNVS_HPCR_RTC_EN_MASK) != 0U)
0487 {
0488 SNVS_HP_RTC_StartTimer(base);
0489 }
0490 }
0491 #endif
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501 uint32_t SNVS_HP_RTC_GetStatusFlags(SNVS_Type *base)
0502 {
0503 uint32_t flags = 0U;
0504
0505 if ((base->HPSR & SNVS_HPSR_PI_MASK) != 0U)
0506 {
0507 flags |= (uint32_t)kSNVS_RTC_PeriodicInterruptFlag;
0508 }
0509
0510 if ((base->HPSR & SNVS_HPSR_HPTA_MASK) != 0U)
0511 {
0512 flags |= (uint32_t)kSNVS_RTC_AlarmInterruptFlag;
0513 }
0514
0515 return flags;
0516 }
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526 uint32_t SNVS_HP_RTC_GetEnabledInterrupts(SNVS_Type *base)
0527 {
0528 uint32_t val = 0U;
0529
0530 if ((base->HPCR & SNVS_HPCR_PI_EN_MASK) != 0U)
0531 {
0532 val |= (uint32_t)kSNVS_RTC_PeriodicInterrupt;
0533 }
0534
0535 if ((base->HPCR & SNVS_HPCR_HPTA_EN_MASK) != 0U)
0536 {
0537 val |= (uint32_t)kSNVS_RTC_AlarmInterrupt;
0538 }
0539
0540 return val;
0541 }
0542
0543 #if defined(FSL_FEATURE_SNVS_HAS_SET_LOCK) && (FSL_FEATURE_SNVS_HAS_SET_LOCK > 0)
0544
0545
0546
0547
0548
0549
0550 void SNVS_HP_SetLocks(SNVS_Type *base)
0551 {
0552 uint32_t sec_config = ((OCOTP_CTRL->HW_OCOTP_OTFAD_CFG3 & OCOTP_CTRL_HW_OCOTP_SEC_CONFIG1_MASK) >>
0553 OCOTP_CTRL_HW_OCOTP_SEC_CONFIG1_SHIFT);
0554
0555 if (sec_config == SEC_CONFIG_OPEN)
0556 {
0557
0558 base->HPCOMR |= SNVS_HPCOMR_NPSWA_EN(1);
0559 }
0560
0561
0562 base->HPCOMR |= SNVS_HPCOMR_LP_SWR_DIS(1);
0563 base->HPLR |= SNVS_HPLR_ZMK_WSL(1);
0564 }
0565 #endif