/* * rtc.c * * Created on: Oct 16, 2024 * Author: true */ #include #include #include "rtc.h" #define RTC_INIT_PATTERN 0x1337 static const uint8_t days_per_mon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; uint8_t rtc_state; void rtc_set_state(uint16_t state) { rtc_state = state; } /* * @fn rtc_is_leapyear * @brief Returns true if year is a leap year. * * @param year * * @return 1 - Yes * 0 - No */ uint8_t rtc_is_leapyear(u16 year) { if (year % 4 == 0) { if (year % 100 == 0) { if (year % 400 == 0) { return 1; } else { return 0; } } else return 1; } else return 0; } /* * @fn rtc_set_clock * @brief Set Time. * * @param Struct of RTClock * * @return 1 - error * 0 - success */ int8_t rtc_set_clock(struct RTClock *c) { uint16_t x; uint8_t m; uint32_t count = 0; if(c->year < 1970 || c->year > 2099) return -1; for(x = 1970; x < c->year; x++) { if (rtc_is_leapyear(x)) count += 31622400; else count += 31536000; } m = c->mon - 1; for(x = 0; x < m; x++){ count += (u32)days_per_mon[x] * 86400; if(rtc_is_leapyear(c->year) && x == 1) count += 86400; } count += (u32)(c->day - 1) * 86400; count += (u32)c->h * 3600; count += (u32)c->m * 60; count += c->s; PWR_BackupAccessCmd(ENABLE); RTC_SetCounter(count); RTC_WaitForLastTask(); return 0; } int8_t rtc_init() { uint32_t timeout; static const struct RTClock clock = { .year = 2024, .mon = 11, .day = 1, .h = 8, .m = 0, .s = 0 }; // enable access to RTC registers PWR_BackupAccessCmd(ENABLE); // get RTC state // if things aren't configured it'll be initialized in a moment rtc_state = BKP_ReadBackupRegister(RTC_STATE_DR); // is RTC already configured? if (BKP_ReadBackupRegister(RTC_INIT_DR) != RTC_INIT_PATTERN) { // must not be. initialize rtc BKP_DeInit(); RCC_LSEConfig(RCC_LSE_ON); timeout = SystemCoreClock / 2; while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && timeout--); // if crystal didn't start in time, let the application know if (!timeout) return -1; // use crystal for RTC and enable it RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); RCC_RTCCLKCmd(ENABLE); RTC_WaitForLastTask(); RTC_WaitForSynchro(); // RTC_ITConfig(RTC_IT_ALR, ENABLE); // RTC_ITConfig(RTC_IT_SEC, ENABLE); // RTC_WaitForLastTask(); RTC_EnterConfigMode(); RTC_SetPrescaler(32767); RTC_WaitForLastTask(); // set an initial time rtc_set_clock((struct RTClock *)&clock); RTC_ExitConfigMode(); rtc_state = RTC_STATE_CLOCK_NOT_SET; BKP_WriteBackupRegister(RTC_STATE_DR, rtc_state); BKP_WriteBackupRegister(RTC_INIT_DR, RTC_INIT_PATTERN); // RTC_NVIC_Config(); // RTC_Get(); } return 0; }