/*! * \file xc_drv_rtc.c * * \brief Target xc aotimer driver implementation * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * * _ __ _ ________ _ * | |/ /(_)___ / ____/ /_ (_)___ * | // / __ \/ / / __ \/ / __ \ * / |/ / / / / /___/ / / / / /_/ / * /_/|_/_/_/ /_/\____/_/ /_/_/ .___/ * /_/ * (C) 2022-2025 XinChip * * \endcode * * \author ( XinChip ) Alex-J * * \author ( XinChip ) */ /*----------------------------------------------------------------------------------- INCLUDE HEADE FILES ------------------------------------------------------------------------------------*/ #include "xc6xxx.h" /*------------------------------------------------------------------------------------ Local Variables -------------------------------------------------------------------------------------*/ static volatile uint8_t calibration_flag = 0; /*------------------------------------------------------------------------------------ Global Variables -------------------------------------------------------------------------------------*/ uint8_t AO_Timer_Callback(uint8_t calib_flag); RTC_Intr_Cb_t RTC_Intr_cb = { AO_Timer_Callback, T1_CMR_Callback, T2_CMR_Callback, T3_CMR_Callback, Sec_Callback, Min_Callback, Hour_Callback, Day_Callback}; /*------------------------------------------------------------------------------------ Func Prototype -------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------ Functions -------------------------------------------------------------------------------------*/ void xc_rtc_start(void) { rtc_icr__rtc__cnt_e__setf(RTC_ICR_CNTE_ENABLE); } void xc_rtc_stop(void) { rtc_icr__rtc__cnt_e__setf(RTC_ICR_CNTE_DISABLE); } static void xc_rtc_matchtime_set(RTC_InitCfg_t *rtc_cfg) { if (rtc_cfg->MatchTime.ch == RTC_MATCH_T1) { rtc_cmr_one_pack(rtc_cfg->MatchTime.Week, rtc_cfg->MatchTime.Hour, rtc_cfg->MatchTime.Min, rtc_cfg->MatchTime.Sec); } else if (rtc_cfg->MatchTime.ch == RTC_MATCH_T2) { rtc_cmr_two_pack(rtc_cfg->MatchTime.Week, rtc_cfg->MatchTime.Hour, rtc_cfg->MatchTime.Min, rtc_cfg->MatchTime.Sec); } else if (rtc_cfg->MatchTime.ch == RTC_MATCH_T3) { rtc_cmr_three_pack(rtc_cfg->MatchTime.Week, rtc_cfg->MatchTime.Hour, rtc_cfg->MatchTime.Min, rtc_cfg->MatchTime.Sec); } } void xc_rtc_date_get(Rtc_DateTypeDef_t *Date) { __rtc_dateget(Date); } void xc_rtc_init(RTC_InitCfg_t *rtc_cfg) { cpr_ctlapbclken_grctl__rtc_pclk_en__setf(ENABLE); cprao_aon_clken_grctl__rtc_clk_en__setf(ENABLE); rtc_icr_set(DISABLE); rtc_raw_limit__setf(xc_clock_lfclk_in_get()); rtc_datelimitSet(rtc_cfg); rtc_dateSet(rtc_cfg); if (rtc_cfg->MatchTimeEnable) { xc_rtc_matchtime_set(rtc_cfg); rtc_config_matchtimeit(rtc_cfg); } if (rtc_cfg->SecIT_Enable) { rtc_config_secit(rtc_cfg); } if (rtc_cfg->MinIT_Enable) { rtc_config_minit(rtc_cfg); } if (rtc_cfg->HourIT_Enable) { rtc_config_hourit(rtc_cfg); } if (rtc_cfg->DayIT_Enable) { rtc_config_dayit(rtc_cfg); } } uint8_t AO_Timer_Callback(uint8_t calib_flag) { calib_flag = 1; return calib_flag; } void RTC_Handler(void) { uint32_t val; val = rtc_all_intr_ao_get(); if (val & RTC_AO_ALL_INTR_AO_TIMER_INTR_Msk) { rtc_ao_timer_ctl__rtc_ao_timer_clr__setf(RTC_AO_TIMER_CTL_AO_TIMER_CLR_SET); rtc_ao_timer_ctl__rtc_ao_timer_en__setf(RTC_AO_TIMER_CTL_AO_TIMER_EN_DISABLE); calibration_flag = RTC_Intr_cb.AO_Timer_Callback(calibration_flag); } val = rtc_isr_eoi_get(); if (val) { rtc_isr_eoi_set(val); if ((val & RTC_ICR_T1E_Msk) == RTC_ICR_T1E_Msk){ RTC_Intr_cb.T1_CMR_Callback(); } if ((val & RTC_ICR_T2E_Msk) == RTC_ICR_T2E_Msk){ RTC_Intr_cb.T2_CMR_Callback(); } if ((val & RTC_ICR_T3E_Msk) == RTC_ICR_T3E_Msk){ RTC_Intr_cb.T3_CMR_Callback(); } if ((val & RTC_ICR_DaE_Msk) == RTC_ICR_DaE_Msk){ RTC_Intr_cb.Day_Callback(); } if ((val & RTC_ICR_HoE_Msk) == RTC_ICR_HoE_Msk){ RTC_Intr_cb.Hour_Callback(); } if ((val & RTC_ICR_MiE_Msk) == RTC_ICR_MiE_Msk){ RTC_Intr_cb.Min_Callback(); } if ((val & RTC_ICR_SeE_Msk) == RTC_ICR_SeE_Msk){ RTC_Intr_cb.Sec_Callback(); } } } __WEAK uint8_t T1_CMR_Callback(void) { return 0; } __WEAK uint8_t T2_CMR_Callback(void) { return 0; } __WEAK uint8_t T3_CMR_Callback(void) { return 0; } __WEAK uint8_t Sec_Callback(void) { return 0; } __WEAK uint8_t Min_Callback(void) { return 0; } __WEAK uint8_t Hour_Callback(void) { return 0; } __WEAK uint8_t Day_Callback(void) { return 0; } /*********************************************************************************** ***************************** RC32 Calibration ****************************** ***********************************************************************************/ /** * @brief RC32k_Count_Calib * @details 鏍″噯 RC32K 瀹為檯璁℃暟鍊? * * @param RTC 瀵勫瓨鍣ㄧ储寮? * @retval uint8_t */ uint8_t xc_rc32k_count_calib() { volatile int32_t hw_timeout = 10000; uint32_t val; float freq = 0.0; rtc_ao_timer_ctl__rtc_ao_timer_value__setf(32); rtc_ao_timer_ctl__rtc_freq_timer_en__setf(1); while ((!(calibration_flag)) && (hw_timeout > 0)) { __nop(); hw_timeout--; } if (hw_timeout < 0) { return 1; } val = rtc_freq_32k_timer_val_get(); val *= (32000000.0f / xc_clock_hfclk_in_get()); rtc_ao_timer_ctl__rtc_ao_timer_en__setf(DISABLE); rtc_ao_timer_ctl__rtc_ao_timer_clr__setf(ENABLE); freq = (float)(15625.0f / (float)val) * 32768.0f; DEBUG("Calib freq: %u\n", (uint32_t)freq); rtc_raw_limit__setf((uint32_t)freq); return 0; }