This repository has been archived on 2024-05-28. You can view files and clone it, but cannot push or open issues or pull requests.
2023-11-14 16:25:09 -05:00

183 lines
6.9 KiB
C++
Executable File

#ifndef STM32U5XX_HAL_RTC_HPP
#define STM32U5XX_HAL_RTC_HPP
#include "global_variable.h"
#include "stdint.h"
#include "stdlib.h"
#include "stm32u575xx.h"
#include "stm32u5xx.h"
class Rtc {
private:
public:
Rtc() = default;
void setup() {
RCC->AHB3ENR |= RCC_AHB3ENR_PWREN; // enable power clock
RCC->APB3ENR |= RCC_APB3ENR_RTCAPBEN; // enable rtc and temp apb
RCC->SRDAMR |= RCC_SRDAMR_RTCAPBAMEN; // enable rtc and temp apb
RCC->APB3SMENR |= RCC_APB3SMENR_RTCAPBSMEN; // enable rtc and temp apb
}
void rtc_setup_time(uint8_t year,
uint8_t month,
uint8_t day,
uint8_t hour,
uint8_t minute,
uint8_t second) {
SET_BIT(PWR->DBPR, PWR_DBPR_DBP); // enable backup domain write
// enable LSE as rtc clock source
RCC->BDCR |= RCC_BDCR_RTCEN;
RCC->BDCR |= RCC_BDCR_LSEON;
// wait for LSE to be ready
while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0) {}
MODIFY_REG(RCC->BDCR, RCC_BDCR_RTCSEL,
0b01 << RCC_BDCR_RTCSEL_Pos); // set rtc clock source to LSE
CLEAR_BIT(RTC->ICSR, RTC_ICSR_BIN); // set to BCD mode
// write protection disable
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// enter init_old mode
SET_BIT(RTC->ICSR, RTC_ICSR_INIT);
while ((RTC->ICSR & RTC_ICSR_INITF) == 0) {}
// set prescale to 1Hz
uint32_t tmpreg = 0;
tmpreg = 127 << RTC_PRER_PREDIV_A_Pos | // set async prescale to 127
255 << RTC_PRER_PREDIV_S_Pos; // sync prescale to 255
WRITE_REG(RTC->PRER, tmpreg);
tmpreg = 0;
tmpreg = 0b0 << RTC_TR_PM_Pos | // set to 24 hour mode
(hour / 10) << RTC_TR_HT_Pos | (hour % 10) << RTC_TR_HU_Pos | // set hour
(minute / 10) << RTC_TR_MNT_Pos | (minute % 10) << RTC_TR_MNU_Pos | // set minute
(second / 10) << RTC_TR_ST_Pos | (second % 10) << RTC_TR_SU_Pos; // set second
WRITE_REG(RTC->TR, tmpreg);
tmpreg = 0;
tmpreg = (year / 10) << RTC_DR_YT_Pos | (year % 10) << RTC_DR_YU_Pos | // set year
(month / 10) << RTC_DR_MT_Pos | (month % 10) << RTC_DR_MU_Pos | // set month
(day / 10) << RTC_DR_DT_Pos | (day % 10) << RTC_DR_DU_Pos; // set day
WRITE_REG(RTC->DR, tmpreg);
// TODO: test whether system reset will clear RTC registers
CLEAR_BIT(RTC->CR, RTC_CR_BYPSHAD); // clear bypass shadow register.
CLEAR_BIT(RTC->ICSR, RTC_ICSR_INIT); // exit init_old mode
CLEAR_BIT(PWR->DBPR, PWR_DBPR_DBP); // disable backup domain write. Protect RTC registers.
WRITE_REG(RTC->WPR, 0xFF); // write protection enable
}
/**
* @brief get current year from rtc
* @param year (return) current year
*/
void rtc_get_year(uint8_t *year) {
uint32_t tmpreg = RTC->DR;
*year =
((tmpreg & RTC_DR_YT) >> RTC_DR_YT_Pos) * 10 + ((tmpreg & RTC_DR_YU) >> RTC_DR_YU_Pos);
}
/**
* @brief get current month from rtc
* @param month (return) current month
*/
void rtc_get_month(uint8_t *month) {
uint32_t tmpreg = RTC->DR;
*month =
((tmpreg & RTC_DR_MT) >> RTC_DR_MT_Pos) * 10 + ((tmpreg & RTC_DR_MU) >> RTC_DR_MU_Pos);
}
/**
* @brief get current day from rtc
* @param day (return) current day
*/
void rtc_get_day(uint8_t *day) {
uint32_t tmpreg = RTC->DR;
*day =
((tmpreg & RTC_DR_DT) >> RTC_DR_DT_Pos) * 10 + ((tmpreg & RTC_DR_DU) >> RTC_DR_DU_Pos);
}
/**
* @brief get current hour from rtc
* @param hour (return) current hour
*/
void rtc_get_hour(uint8_t *hour) {
uint32_t tmpreg = RTC->TR;
*hour =
((tmpreg & RTC_TR_HT) >> RTC_TR_HT_Pos) * 10 + ((tmpreg & RTC_TR_HU) >> RTC_TR_HU_Pos);
}
/**
* @brief get current minute from rtc
* @param minute (return) current minute
*/
void rtc_get_minute(uint8_t *minute) {
uint32_t tmpreg = RTC->TR;
*minute = ((tmpreg & RTC_TR_MNT) >> RTC_TR_MNT_Pos) * 10 +
((tmpreg & RTC_TR_MNU) >> RTC_TR_MNU_Pos);
}
/**
* @brief get current second from rtc
* @param second (return) current second
*/
void rtc_get_second(uint8_t *second) {
uint32_t tmpreg = RTC->TR;
*second =
((tmpreg & RTC_TR_ST) >> RTC_TR_ST_Pos) * 10 + ((tmpreg & RTC_TR_SU) >> RTC_TR_SU_Pos);
}
/**
* @brief get current time from rtc
* @param hour (return) current hour
* @param minute (return) current minute
* @param second (return) current second
*/
void rtc_get_time(uint8_t *hour, uint8_t *minute, uint8_t *second) {
uint32_t tmpreg = RTC->TR;
*hour =
((tmpreg & RTC_TR_HT) >> RTC_TR_HT_Pos) * 10 + ((tmpreg & RTC_TR_HU) >> RTC_TR_HU_Pos);
*minute = ((tmpreg & RTC_TR_MNT) >> RTC_TR_MNT_Pos) * 10 +
((tmpreg & RTC_TR_MNU) >> RTC_TR_MNU_Pos);
*second =
((tmpreg & RTC_TR_ST) >> RTC_TR_ST_Pos) * 10 + ((tmpreg & RTC_TR_SU) >> RTC_TR_SU_Pos);
}
/**
* @brief get current date from rtc
* @param year (return) current year
* @param month (return) current month
* @param day (return) current day
*/
void rtc_get_date(uint8_t *year, uint8_t *month, uint8_t *day) {
uint32_t tmpreg = RTC->DR;
*year =
((tmpreg & RTC_DR_YT) >> RTC_DR_YT_Pos) * 10 + ((tmpreg & RTC_DR_YU) >> RTC_DR_YU_Pos);
*month =
((tmpreg & RTC_DR_MT) >> RTC_DR_MT_Pos) * 10 + ((tmpreg & RTC_DR_MU) >> RTC_DR_MU_Pos);
*day =
((tmpreg & RTC_DR_DT) >> RTC_DR_DT_Pos) * 10 + ((tmpreg & RTC_DR_DU) >> RTC_DR_DU_Pos);
}
/**
* @brief get current time and date from rtc
* @param year (return) current year
* @param month (return) current month
* @param day (return) current day
* @param hour (return) current hour
* @param minute (return) current minute
* @param second (return) current second
* @note this function will disable irq and RTC_CR_BYPSHAD should be cleared.
* This function should read shadow registers to avoid reading inconsistent values.
* @todo set timeout for while loop
*/
void rtc_get_datetime(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour,
uint8_t *minute, uint8_t *second) {
if (READ_BIT(RTC->CR, RTC_CR_BYPSHAD) != 0) { return; }
while (READ_BIT(RTC->ICSR, RTC_ICSR_RSF) == 0)
; // wait for sync. it will take 2 RTCCLK cycles (rtcclk is 32.768khz)
__disable_irq();
rtc_get_date(year, month, day);
rtc_get_time(hour, minute, second);
__enable_irq();
}
};
#endif // STM32U5XX_HAL_RTC_HPP